Vai al contenuto

Firme tipizzate EIP-712: domini, digest e verifica sicura

EIP-712 rende deterministici e leggibili i messaggi strutturati Ethereum, ma firmare in sicurezza richiede la verifica esatta di dominio, tipo, valore, nonce, scadenza, esecuzione e politica del firmatario.

Aggiornato

Solo a scopo educativo; non costituisce consulenza né raccomandazione d’investimento. Gli investimenti possono comportare perdite.

Risposta diretta

EIP-712 standardizza il modo in cui le applicazioni Ethereum descrivono, sottopongono a hash e fanno firmare dati strutturati tipizzati. Una richiesta contiene types, primaryType, domain e message; il digest è keccak256("\x19\x01" || domainSeparator || hashStruct(message)). La codifica diventa deterministica e un wallet compatibile può mostrare i campi più chiaramente di un hash opaco.

Lo standard non rende il messaggio veritiero, innocuo, revocabile o protetto dai replay. L’applicazione deve vincolare l’autorità alla chain e al verificatore corretti, definire ogni campo senza ambiguità, imporre nonce e limiti temporali, convalidare il firmatario giusto e limitare l’esecuzione. Una firma valida prova l’approvazione di un digest esatto secondo una regola di verifica; non prova identità, consenso informato o sicurezza del sito e del contratto.

Firme tipizzate EIP-712
0 / 5
0 elementi recensiti; 5 elementi ancora irrisolti

Il completamento di questa revisione non dimostra che una risorsa, una transazione o un sistema siano sicuri.

Come funziona

1. Identificare azione e percorso di verifica

Stabilire se la richiesta autorizza accesso, ordine, voto, allowance di token, trasferimento, chiamata tramite relayer o altro. Individuare il codice che ricostruisce il digest e consuma la firma. Per un account controllato esternamente si recupera spesso un indirizzo da una firma ECDSA; per un account contratto può servire ERC-1271 isValidSignature(hash, signature) con valore di successo 0x1626ba7e.

2. Fissare il dominio

Esaminare il tipo EIP712Domain esatto e i valori. I campi standard sono name, version, chainId, verifyingContract e salt, ma solo quelli presenti vengono inclusi nell’hash. Confermare in modo indipendente chain attiva, codice distribuito e verificatore previsto; nome, simbolo, etichetta proxy o indirizzo con checksum familiari non bastano. ERC-5267 eip712Domain() può esporre il dominio, ma il supporto è facoltativo e proxy o aggiornamenti restano da verificare.

3. Ricostruire il grafo dei tipi

Partire da primaryType, conservare l’ordine dei membri e raccogliere ricorsivamente le struct referenziate. encodeType aggiunge le loro definizioni ordinate per nome del tipo. EIP-712 supporta interi a larghezza fissa, address, bool, da bytes1 a bytes32, bytes e string dinamici, array e struct; lo standard non definisce gli alias uint e int, i tipi a virgola fissa né valori ciclici.

4. Decodificare ogni valore e unità

Associare ogni valore al tipo dichiarato e al significato applicativo. Verificare indirizzi completi, unità intere grezze, segni, ordine degli array, destinatari, spender, asset, importi, commissioni, limiti, destinazioni, hash di calldata e stringhe leggibili. bytes e string dinamici sono rappresentati in encodeData dall’hash Keccak-256 del contenuto; gli array usano l’hash delle codifiche concatenate e le struct annidate il proprio hashStruct.

5. Ricalcolare il digest in modo indipendente

Calcolare typeHash = keccak256(encodeType(primaryType)), quindi hashStruct(message) = keccak256(typeHash || encodeData(message)). Calcolare allo stesso modo il separatore di dominio e unirlo ai byte di versione ERC-191 0x19 0x01. Confrontare frontend, libreria di firma, contratto verificatore e implementazione indipendente; JSON visivamente uguali non provano una codifica tipizzata identica.

6. Verificare replay, tempo ed esecuzione

EIP-712 non include protezione dai replay. Verificare che il validatore controlli il firmatario previsto, consumi o invalidi il nonce corretto, applichi deadline o finestre di validità, vincoli tutti i parametri critici e mantenga il risultato previsto se un relayer o un frontrunner invia per primo. La separazione del dominio evita collisioni solo tra domini effettivamente codificati; campi assenti o errati possono lasciare riutilizzi tra contratti o chain.

7. Firmare il minimo e riconciliare il risultato

Rifiutare campi nascosti, tipi inspiegati, valori illimitati, scadenze lontane, contratti sconosciuti, chain ID discordanti, schermate di blind signing o contesto di esecuzione incompleto. Conservare JSON tipizzato e digest esatti, usare se possibile un account dedicato e verificare transazione, ricevuta, eventi, saldi, allowance, nonce, stato dell’ordine e finalità. Disconnettere il sito non revoca una firma utilizzabile né un’autorità già creata.

Esempi calcolati

Esempio 1: Costruzione di tipo e digest

Per Order(address maker,address token,uint256 amount,uint256 nonce,uint256 deadline), typeHash è l’hash Keccak-256 di questa stringa esatta, compreso l’ordine dei campi. L’hash del messaggio è keccak256(typeHash || maker || token || amount || nonce || deadline) e ogni membro occupa 32 byte. Il digest finale aggiunge 0x1901, separatore di dominio e hash del messaggio; cambiare amount da 250000000 a 250000001 cambia il digest e invalida la vecchia firma.

Esempio 2: Unità e scadenza

250 USDC di un token con sei decimali si codificano come valore grezzo 250000000, non 250. Se il timestamp attuale è 1727000000 e la scadenza 1727000900, la finestra è 900 seconds = 15 minutes. La visualizzazione decimale e l’orologio locale sono solo ausili; il verificatore usa l’intero grezzo e la regola temporale on-chain scelta.

Esempio 3: Controllo dei replay

Un ordine contiene nonce 41 e massimo 5 ETH. Dopo che il verificatore segna il nonce 41 come consumato, un secondo invio deve fallire anche se la firma resta valida. Se il contratto non consuma il nonce e l’esecuzione non è idempotente, la stessa firma può autorizzare altri 5 ETH; il separatore di dominio da solo non impedisce il replay.

Esempio 4: Validità di un wallet contratto

Un wallet contratto 2-su-3 approva un digest con firmatari A, B e C. Le firme di A e B possono far restituire oggi 0x1626ba7e a ERC-1271. Se un aggiornamento sostituisce B con D, gli stessi byte possono diventare invalidi: la validità ERC-1271 può dipendere da stato, politica, tempo e chiamate esterne attuali; il solo recupero dell’indirizzo non decide la validità dell’account contratto.

Rischi

  • chainId errato o assente
  • verifyingContract contraffatto o inatteso
  • name o version del dominio fuorviante
  • Implementazione proxy o dominio cambiati dopo un aggiornamento
  • primaryType errato o tipo ombra con etichetta simile
  • Ordine di membri, dipendenze o encoder discordante
  • Indirizzo troncato, sostituito o etichettato in modo ingannevole
  • Errore nei decimali o tra intero con e senza segno
  • Elemento array, struct annidata o payload bytes nascosto
  • Importo illimitato, ambito ampio o destinatario controllato dall’attaccante
  • Nonce assente, vecchio, condiviso o consumato in modo errato
  • Scadenza assente, lontana, in overflow o interpretata ambiguamente
  • Replay tra chain, contratti, account o azioni
  • Ritenzione, censura, front-running o deviazione del relayer
  • Malleabilità della firma o recupero ECDSA troppo permissivo
  • Cambio di firmatario, modulo, soglia, stato o codice ERC-1271
  • Rendering wallet, blind signing o tipo non supportato
  • JSON del frontend diverso dal digest del verificatore
  • Revoca o annullamento che perde una gara di ordinamento
  • Confondere esito del prompt con ricevuta, stato o finalità

Malintesi comuni

Mito 1: Le firme EIP-712 sono transazioni

Sono messaggi firmati off-chain. Un relayer può inviarli in seguito a un contratto; la transazione risultante può consumare Gas e cambiare stato senza essere inviata dal firmatario.

Mito 2: Una vista strutturata rende sicura la richiesta

I campi tipizzati facilitano l’ispezione, ma schemi, valori, contratti, etichette, annidamenti nascosti o rendering incompleti possono ancora ingannare.

Mito 3: Il separatore di dominio impedisce ogni replay

Separa solo il dominio codificato. Il replay nello stesso dominio richiede nonce, scadenza, annullamento, contabilità degli eseguiti o idempotenza; un campo omesso non crea alcun limite.

Mito 4: Recuperare l’indirizzo atteso prova l’autorizzazione

Il recupero prova una firma EOA sul digest, non la semantica applicativa. Gli account contratto richiedono la propria politica ERC-1271, non il normale recupero.

Mito 5: Chiudere la pagina o disconnettere il wallet annulla la firma

Una firma copiata resta utilizzabile finché nonce, scadenza, annullamento, stato o politica del verificatore non la invalidano. Conta lo stato on-chain, non la sessione.

Argomenti correlati

Fonti

Navigazione

Cerca nella wiki...