* Add eip-signTypedData * Change namespace from personal to eth * Change a way schema hash is combined together with data as proposed by @MicahZoltu * Add a note about it being implemented in MetaMask as an experimental feature * Add signerAddress as a parameter * Add test vectors * Fix an example * Missing commas, periods * Address the feedback * Add a missing signerAddress parameter in the example * Change the order of parameters to have an address as a second arg * Wrote motivation * WIP * First draft of specification * Fixes * Update to new EIP format * Assign EIP number * Clarify encoding of short static byte arrays * Removed Solidity changes * Fixup * Fix typos * WIP EIP191 * WIP TODO * WIP Replay attacks * Fixes the sorted by name example encoding * Remove Solidity hash * Added note on replay protection * Redesign domain separator * Include images and simple motivation * Fix up EIP metadata formatting * Add domain separator * Remove replay attacks from todo list * Add Jacob Evans to authors * Clarify encodeData * Rename Message example to Mail * Update mock signing screen * Rework EIP712Domain * Update Solidity example * Update Javascript example * Relocate files * Rename DomainSeparator to EIP712Domain (fix) * Move examples to separate files * Remove httpOrigin domain parameter * Update JSON-Schema * Add registery of version bytes * Add eip712 to eip191 registery * Add requires header * Set correct language on all snipets * GitHub highlighting for Solidity files * Update Web3 API specification * Use abi.encode where possible * Update JSON-RPC specification * Asset path repo is ethereums * Correctly spelling of registry
3.5 KiB
eip | title | author | status | type | category | created |
---|---|---|---|---|---|---|
191 | Signed Data Standard | Martin Holst Swende (@holiman), Nick Johnson <arachnid@notdot.net> | Draft | Standards Track | ERC | 2016-01-20 |
Abstract
This ERC proposes a specification about how to handle signed data in Ethereum contracts.
Motivation
Several multisignature wallet implementations have been created which accepts presigned
transactions. A presigned
transaction is a chunk of binary signed_data
, along with signature (r
, s
and v
). The interpretation of the signed_data
has not been specified, leading to several problems:
- Standard Ethereum transactions can be submitted as
signed_data
. An Ethereum transaction can be unpacked, into the following components:RLP<nonce, gasPrice, startGas, to, value, data>
(hereby calledRLPdata
),r
,s
andv
. If there are no syntactical constraints onsigned_data
, this means thatRLPdata
can be used as a syntactically validpresigned
transaction. - Multisignature wallets have also had the problem that a
presigned
transaction has not been tied to a particularvalidator
, i.e a specific wallet. Example:- Users
A
,B
andC
have the2/3
-walletX
- Users
A
,B
andD
have the2/3
-walletY
- User
A
andB
submitespresigned
transaction toX
. - Attacker can now reuse their presigned transactions to
X
, and submit toY
.
- Users
Specification
We propose the following format for signed_data
0x19 <1 byte version> <version specific data> <data to sign>.
Version 0
has <20 byte address>
for the version specific data, and the address
is the intended validator. In the case of a Multisig wallet, that is the wallet's own address .
The initial 0x19
byte is intended to ensure that the signed_data
is not valid RLP
For a single byte whose value is in the [0x00, 0x7f] range, that byte is its own RLP encoding.
That means that any signed_data
cannot be one RLP-structure, but a 1-byte RLP
payload followed by something else. Thus, any ERC-191 signed_data
can never be an Ethereum transaction.
Additionally, 0x19
has been chosen because since ethereum/go-ethereum#2940 , the following is prepended before hashing in personal_sign:
"\x19Ethereum Signed Message:\n" + len(message).
Using 0x19
thus makes it possible to extend the scheme by defining a version 0x45
(E
) to handle these kinds of signatures.
Registry of version bytes
Version byte | EIP | Description |
---|---|---|
0x00 |
191 | Data with intended validator |
0x01 |
712 | Structured data |
0x45 |
191 | personal_sign messages |
Example
function submitTransactionPreSigned(address destination, uint value, bytes data, uint nonce, uint8 v, bytes32 r, bytes32 s)
public
returns (bytes32 transactionHash)
{
// Arguments when calculating hash to validate
// 1: byte(0x19) - the initial 0x19 byte
// 2: byte(0) - the version byte
// 3: this - the validator address
// 4-7 : Application specific data
transactionHash = keccak256(byte(0x19),byte(0),this,destination, value, data, nonce);
sender = ecrecover(transactionHash, v, r, s);
// ...
}
Copyright
Copyright and related rights waived via CC0.