owned this note
owned this note
Published
Linked with GitHub
---
eip: x
title: Signature Type Recognition
author:
discussions-to:
status: Draft
type: Standards Track
category: ERC
created: 2019-06-19
requires: 712, 1271
---
## Abstract
Enable Dapps to be able to recognize how a given signature was signed (e.g. by owner of a smart contract, EOA, etc) so that they can use the correct mechanism to verify the signature.
## Motivation
Currently Dapp developers are unable to identify the _type_ of a signature. By _type_ we are referring to how the signature was generated.
If the Dapp sees the user's EOA (externally-owned address) as their account, then any signature will have been generated by the private key of that address, and the Dapp would easily be able to validate the signer of this signature as being the same account. On the other hand, if what a Dapp sees is a user's smart contract address (which is indirectly owned by the user's EOA) then obviously the Dapp would find a mismatch between signer address and account address.
A real-world example would be using Metamask or [WalletConnect](https://walletconnect.org), where you could expose accounts which are either EOA accounts or smart contract accounts, which in turn would provide similar signatures but require different validation processes.
The solution to this issue is to append a byte to the end of the signature which will correspond to one of the given signature types listed below. Dapps can then query this byte to know how to validate the given signature.
_Note: this approach is [already in production use by 0x](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md#signature-types), and indeed this spec is based on their work._
## Formatting Signatures
Example for [EIP-712](#EIP712) compliant signatures:
```javascript
const signatureBuffer = Buffer.concat([
ethUtil.toBuffer(ecSignatureRSV.v),
ethUtil.toBuffer(ecSignatureRSV.r),
ethUtil.toBuffer(ecSignatureRSV.s),
ethUtil.toBuffer(SignatureType.EIP712),
]);
```
## Signature Types
All signatures are represented as a byte array of arbitrary length, where the last byte (the "signature byte") specifies the signature type. The signature type is popped from the signature byte array before validation. The following signature types are supported within the protocol:
| Signature byte | Signature type |
| -------------- | ----------------------- |
| 0x00 | [Illegal](#illegal) |
| 0x01 | [Invalid](#invalid) |
| 0x02 | [EIP712](#eip712) |
| 0x03 | [EthSign](#ethsign) |
| 0x04 | [Wallet](#wallet) |
### Illegal
The is the default value of the signature byte. A transaction that includes an Illegal signature will be reverted. Therefore, users must explicitly specify a valid signature type.
### Invalid
An `Invalid` signature always returns false. An invalid signature can always be recreated and is therefore offered explicitly. This signature type is largely used for testing purposes.
### EIP712
An [`EIP712`](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md) signature is considered valid if the address recovered from calling [`ecrecover`](#ecrecover-usage) with the given hash and decoded `v`, `r`, `s` values is the same as the specified signer. In this case, the signature is encoded in the following way:
| Offset | Length | Contents |
| ------ | ------ | ------------------- |
| 0x00 | 1 | v (always 27 or 28) |
| 0x01 | 32 | r |
| 0x21 | 32 | s |
### EthSign
An `EthSign` signature is considered valid if the address recovered from calling [`ecrecover`](#ecrecover-usage) with the an EthSign-prefixed hash and decoded `v`, `r`, `s` values is the same as the specified signer.
The prefixed `msgHash` is calculated with:
```
string constant ETH_PERSONAL_MESSAGE = "\x19Ethereum Signed Message:\n32";
bytes32 msgHash = keccak256(abi.encodePacked(ETH_PERSONAL_MESSAGE, hash));
```
`v`, `r`, and `s` are encoded in the signature byte array using the same scheme as [EIP712 signatures](#EIP712).
### Wallet
The `Wallet` signature type allows an EOA account to sign messages on behalf of a smart contract account.
As per [EIP-1271](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1271.md), smart contract accounts can validate signatures using the public method `isValidSignature`. This method has the following interface:
```typescript=
// @dev Verifies that a signature is valid.
// @param hash Message hash that is signed.
// @param signerAddress Address of signer.
// @param signature Proof of signing.
// @return Validity of order signature.
function isValidSignature(
bytes32 hash,
address signerAddress,
bytes memory signature
)
public
view
returns (bool isValid);
```
## Web3 JSON API support
We suggest appending an _optional_ parameter to existing Web3 signature functions. This parameter would contain key-value pairs. This is so that:
* Web3 clients can choose when and where to include a signature type byte.
* Existing code using these methods doesn't need to change.
* Additional options can easily be added in future.
Example using `web3.js`:
```js
web3.eth.personal.sign("...data...", "0x...", "password", /* callback */ null, {
typeByte: true,
})
```
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).