EIP-1271: Podepisování a ověřování podpisů chytrých kontraktů
Standard EIP-1271 (opens in a new tab) umožňuje chytrým kontraktům ověřovat podpisy.
V tomto tutoriálu poskytneme přehled digitálních podpisů, pozadí EIP-1271 a specifické implementace EIP-1271 používané službou Safe (opens in a new tab) (dříve Gnosis Safe). Celkově to může sloužit jako výchozí bod pro implementaci EIP-1271 ve vašich vlastních kontraktech.
Co je to podpis?
V tomto kontextu je podpis (přesněji „digitální podpis“) zpráva plus nějaký druh důkazu, že zpráva pochází od konkrétní osoby/odesílatele/adresy.
Digitální podpis může vypadat například takto:
- Zpráva: „Chci se na tuto webovou stránku přihlásit pomocí své peněženky Ethereum.“
- Podepisující: Moje adresa je
0x000… - Důkaz: Zde je důkaz, že já,
0x000..., jsem skutečně vytvořil celou tuto zprávu (obvykle se jedná o něco kryptografického).
Je důležité si uvědomit, že digitální podpis zahrnuje jak „zprávu“, tak „podpis“.
Proč? Pokud byste mi například dali k podpisu smlouvu a já bych odtrhl stránku s podpisem a vrátil vám pouze své podpisy bez zbytku smlouvy, smlouva by nebyla platná.
Stejně tak digitální podpis bez přidružené zprávy nic neznamená!
Proč existuje EIP-1271?
Abyste mohli vytvořit digitální podpis pro použití na blockchainechech založených na Ethereu, obecně potřebujete tajný privátní klíč, který nikdo jiný nezná. Díky tomu je váš podpis skutečně váš (nikdo jiný nemůže vytvořit stejný podpis bez znalosti tajného klíče).
Váš účet na Ethereu (tj. váš externě vlastněný účet / EOA) má s ním spojený privátní klíč, a to je privátní klíč, který se obvykle používá, když vás web nebo dapp požádá o podpis (např. pro „Přihlásit se pomocí Etherea“).
Aplikace může ověřit podpis (opens in a new tab), který vytvoříte pomocí knihovny třetí strany, jako je ethers.js, aniž by znala váš privátní klíč (opens in a new tab), a být si jistá, že jste to byli vy, kdo podpis vytvořil.
Ve skutečnosti, protože digitální podpisy EOA používají kryptografii s veřejným klíčem, mohou být generovány a ověřovány mimo blockchain! Takto funguje hlasování v DAO bez poplatků – místo odesílání hlasů na blockchainu lze digitální podpisy vytvářet a ověřovat mimo blockchain pomocí kryptografických knihoven.
Zatímco účty EOA mají privátní klíč, účty chytrých kontraktů nemají žádný privátní ani tajný klíč (takže "Přihlásit se pomocí Etherea" atd. nemůže nativně fungovat s účty chytrých kontraktů).
Problém, který se EIP-1271 snaží vyřešit: jak můžeme poznat, že podpis chytrého kontraktu je platný, pokud chytrý kontrakt nemá žádné „tajemství“, které by mohl do podpisu začlenit?
Jak EIP-1271 funguje?
Chytré kontrakty nemají privátní klíče, které by se daly použít k podepisování zpráv. Jak tedy poznáme, zda je podpis autentický?
Jedním z nápadů je, že se můžeme chytrého kontraktu jednoduše zeptat, zda je podpis autentický!
EIP-1271 standardizuje myšlenku „zeptat se“ chytrého kontraktu, zda je daný podpis platný.
Kontrakt, který implementuje EIP-1271, musí mít funkci s názvem isValidSignature, která přijímá zprávu a podpis. Kontrakt pak může spustit nějakou ověřovací logiku (specifikace zde nevynucuje nic konkrétního) a poté vrátit hodnotu označující, zda je podpis platný, či nikoli.
Pokud isValidSignature vrátí platný výsledek, je to v podstatě jako by kontrakt říkal „ano, schvaluji tento podpis + zprávu!“
Rozhraní
Zde je přesné rozhraní ve specifikaci EIP-1271 (o parametru _hash budeme mluvit níže, ale prozatím si ho představte jako zprávu, která je ověřována):
1pragma solidity ^0.5.0;23contract ERC1271 {45 // bytes4(keccak256("isValidSignature(bytes32,bytes)")6 bytes4 constant internal MAGICVALUE = 0x1626ba7e;78 /**9 * @dev Měla by vrátit, zda je poskytnutý podpis platný pro poskytnutý haš10 * @param _hash Haš dat k podepsání11 * @param _signature Pole bajtů podpisu spojené s _hash12 *13 * MUSÍ vrátit magickou hodnotu bytes4 0x1626ba7e, když funkce projde.14 * NESMÍ upravovat stav (pomocí STATICCALL pro solc < 0.5, modifikátor view pro solc > 0.5)15 * MUSÍ povolit externí volání16 */17 function isValidSignature(18 bytes32 _hash,19 bytes memory _signature)20 public21 view22 returns (bytes4 magicValue);23}Zobrazit všePříklad implementace EIP-1271: Safe
Kontrakty mohou implementovat isValidSignature mnoha způsoby — specifikace neříká mnoho o přesné implementaci.
Jedním z pozoruhodných kontraktů, který implementuje EIP-1271, je Safe (dříve Gnosis Safe).
V kódu Safe je isValidSignature implementována (opens in a new tab) tak, že podpisy lze vytvářet a ověřovat dvěma způsoby (opens in a new tab):
- Zprávy na blockchainu
- Vytvoření: vlastník Safe vytvoří novou transakci Safe k „podepsání“ zprávy a předá zprávu jako data do transakce. Jakmile transakci podepíše dostatek vlastníků k dosažení prahu pro multisig, transakce se odešle a spustí. V transakci je funkce Safe s názvem (
signMessage(bytes calldata _data)), která přidá zprávu na seznam „schválených“ zpráv. - Ověření: zavolejte
isValidSignaturena kontraktu Safe a předejte zprávu k ověření jako parametr zprávy a prázdnou hodnotu pro parametr podpisu (opens in a new tab) (tj.0x). Safe uvidí, že parametr podpisu je prázdný, a místo kryptografického ověření podpisu bude vědět, že má pouze zkontrolovat, zda je zpráva na seznamu „schválených“ zpráv.
- Vytvoření: vlastník Safe vytvoří novou transakci Safe k „podepsání“ zprávy a předá zprávu jako data do transakce. Jakmile transakci podepíše dostatek vlastníků k dosažení prahu pro multisig, transakce se odešle a spustí. V transakci je funkce Safe s názvem (
- Zprávy mimo blockchain:
- Vytvoření: vlastník Safe vytvoří zprávu mimo blockchain, poté nechá ostatní vlastníky Safe podepsat zprávu jednotlivě, dokud nebude dostatek podpisů k překonání prahu schválení multisig.
- Ověření: zavolejte
isValidSignature. Do parametru zprávy předejte zprávu k ověření. Do parametru podpisu předejte jednotlivé podpisy všech vlastníků Safe, všechny spojené za sebou. Safe zkontroluje, že je dostatek podpisů pro splnění prahu a že každý podpis je platný. Pokud ano, vrátí hodnotu označující úspěšné ověření podpisu.
Co přesně je parametr _hash? Proč nepředat celou zprávu?
Možná jste si všimli, že funkce isValidSignature v rozhraní EIP-1271 (opens in a new tab) nepřijímá samotnou zprávu, ale místo toho parametr _hash. To znamená, že místo předání celé zprávy libovolné délky do isValidSignature předáme 32bajtový haš zprávy (obvykle keccak256).
Každý bajt calldata — tj. data parametrů funkce předaná funkci chytrého kontraktu — stojí 16 jednotek paliva (4 jednotky paliva, pokud je to nulový bajt) (opens in a new tab), takže to může ušetřit spoustu paliva, pokud je zpráva dlouhá.
Předchozí specifikace EIP-1271
Existují specifikace EIP-1271, které mají funkci isValidSignature s prvním parametrem typu bytes (libovolná délka, místo pevné délky bytes32) a názvem parametru message. Toto je starší verze (opens in a new tab) standardu EIP-1271.
Jak by měl být EIP-1271 implementován v mých vlastních kontraktech?
Specifikace je v tomto ohledu velmi otevřená. Implementace Safe má několik dobrých nápadů:
- Můžete považovat podpisy EOA od "vlastníka" kontraktu za platné.
- Můžete si uložit seznam schválených zpráv a pouze ty považovat za platné.
Nakonec je to na vás jako na vývojáři kontraktu!
Závěr
EIP-1271 (opens in a new tab) je všestranný standard, který umožňuje chytrým kontraktům ověřovat podpisy. Otevírá dveře pro chytré kontrakty, aby se chovaly více jako EOA – například poskytuje způsob, jak "Přihlásit se pomocí Etherea" funguje s chytrými kontrakty – a může být implementován mnoha způsoby (Safe má netriviální, zajímavou implementaci k zvážení).
Stránka naposledy aktualizována: 16. ledna 2026