EIPs/EIPS/eip-191.md
Leonid Logvinov d686a655de [WIP] Add eth_signTypedData as a standard for machine-verifiable and human-readable typed data signing with Ethereum keys (#712)
* 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
2018-06-09 20:19:15 +01:00

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 called RLPdata), r, s and v. If there are no syntactical constraints on signed_data, this means that RLPdata can be used as a syntactically valid presigned transaction.
  • Multisignature wallets have also had the problem that a presigned transaction has not been tied to a particular validator, i.e a specific wallet. Example:
    1. Users A, B and C have the 2/3-wallet X
    2. Users A, B and D have the 2/3-wallet Y
    3. User A and B submites presigned transaction to X.
    4. Attacker can now reuse their presigned transactions to X, and submit to Y.

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 and related rights waived via CC0.