Closed Netherdrake closed 6 years ago
If my memory is correct:
Short answer is yes, but you have to do some manipulation of the v
value since ethereum uses a non-standard v of 27/28
and eth-keys
uses what we refer to as the canonical v
of 0/1
.
You should take a look at this: https://github.com/ethereum/eth-account/blob/master/eth_account/signing.py
closing, but please continue to comment if you still need help.
http://eth-account.readthedocs.io/en/latest/eth_account.html#eth_account.account.Account.recoverMessage might be what you're looking for
I guess metamask implemented some version of https://github.com/ethereum/EIPs/pull/712 (perhaps at an older version than the current, which is still unmerged). There is no implementation of that yet AFAIK, but as soon as the draft EIP is merged, it seems reasonable to add it to eth-account & web3py.
Is there any python implementation of EIP712 at this time?
Not that I've seen
MicroRaiden has functions for current Metamask implementation. Look at its usage here.
Thanks @andrevmatos -- so to sign a typed data message now, you can:
Account.signHash()
That version of eth-account will be included in the next web3.py release.
Here is a copy of the hashing code, in case that commit disappears for whatever reason:
def eth_sign_typed_data_message(typed_data: List[TypedData]) -> bytes:
typed_data = [('{} {}'.format(type_, name), data) for type_, name, data in typed_data]
schema, data = [list(zipped) for zipped in zip(*typed_data)]
return keccak256(keccak256(*schema), keccak256(*data))
I am unable to verify MetaMask signed message with either Account.recoverHash()
or pruned version of Raiden's crypto.py
.
from src.contrib.crypto import (
eth_typed_data_message,
addr_from_sig,
)
from eth_utils import decode_hex
from eth_account import Account
address = '0xaaf3ffee9d4c976aa8d0cb1bb84c3c90ee6e9118'
signature = '0x965439c02ec9399b9fce8f9eac57bfa7f93385c885c96c536dc28070bcdf0ccc6cc45c9eaf4f43b0a40c32e8f8d7e97320a92ea675fa5d826ae67521d3e669af1c'
msg = [[{"type":"string","name":"Video ID","value":"v3jMYxUpBzZ2"},{"type":"uint8","name":"Vote Weight (%)","value":100}],"0xaaf3ffee9d4c976aa8d0cb1bb84c3c90ee6e9118"]
msg_hash = eth_typed_data_message(msg[0])
print('Expected', address)
print('Raiden', Account().recoverHash(msg_hash, signature=signature))
print('eth-account', addr_from_sig(decode_hex(signature), msg_hash))
Output:
Expected 0xaaf3ffee9d4c976aa8d0cb1bb84c3c90ee6e9118
Raiden 0xb2EFAFf151948a284e56d653802ED8a579c964Ef
eth-account 0xb2efaff151948a284e56d653802ed8a579c964ef
Note: This is how the message is signed in the first place:
let params = [
[
{type: 'string', name: 'Video ID', value: videoId},
{type: 'uint8', name: 'Vote Weight (%)', value: weight}
],
account,
];
w3.currentProvider.sendAsync({
method: 'eth_signTypedData',
params: params,
from: account,
}).then(...);
As per: https://medium.com/metamask/scaling-web3-with-signtypeddata-91d6efc8b290
I wouldn't be shocked if metamask's eth_signTypedData
hashes differently than the eth_typed_data_message
. I think the EIP proposal has gone through several revisions.
It looks like Metamask implementation uses a library with different packing method than the one provided by Raiden.
Does anyone know of a Python implementation of this: https://github.com/ethereumjs/ethereumjs-abi/blob/09c3c48fd3bed143df7fa8f36f6f164205e23796/lib/index.js#L441
Ok, found the culprit. pack
in crypto.py
does not automatically infer int size from type name.
@carver What is the current status for supporting eth_signTypedData
in eth-account & web3py? Do you have a rough estimate when this will be available for use?
@Netherdrake How did you deal with crypto.py
not automatically inferring int size from type name?
@Jmjin I'd like to see someone shepherd https://eips.ethereum.org/EIPS/eip-712 through to at least "Accepted" or "Last Call" before I work on adding it to eth-account/web3.
@carver Actually it's already merged: https://github.com/ethereum/EIPs/pull/712 Seems like https://eips.ethereum.org/EIPS/eip-712 is not up to date.
It was merged as a draft
: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md
Draft means it's still open to change: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1.md#eip-work-flow
This is captured in https://github.com/ethereum/eth-account/issues/35 which is the codebase where this would be implemented.
Also, regarding: https://github.com/ethereum/eth-account/issues/35 we are ready for it to be implemented if someone has capacity, but it will be heavily flagged as experimental until the EIP is finalized.
Is it possible to use
eth-keys
to validate web3 (Metamask backend) signed messages?I've been trying to piece it together from documentation, but no luck so far. https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethsign
Code (only guessing so far):
Web3js sign example:
Expectation: