EOSIO / eosjs-ecc

Elliptic curve cryptography functions: Private Key, Public Key, Signature, AES, Encryption, Decryption
288 stars 119 forks source link

Unable to reliably recover Public Key deterministically from transaction #3

Closed ellipticasec closed 6 years ago

ellipticasec commented 6 years ago

I have test cases based on 2 signatures produced by the EOS C++ executable and I am unable to reliably (works or fails depending on signature) recover the Public Key matching the Private Key that was used for those signatures.

Keypair : EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV / 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3

Signatures: EOSK5yY5ehsnDMc6xcRhsLYzFuZGUaKwb4hc8oLmP5HA1EhU42NRo3ygx3zvLRJ1nkw1NA5nCSegwcYkSfkZBQBzqMDsCGnNK EOSKkwLhwDoRF8gpGFbcUKiaPdeeKo6U7eDuXQw9szMiNE4K4cFe17sffk6hmy3mWf1ogtzd5J5kvnvFD3Lq5cF6VyYb3KsGy

Test case 1 (PASS - matches Pub Key) eosjs_ecc.Signature.fromString('EOSK5yY5ehsnDMc6xcRhsLYzFuZGUaKwb4hc8oLmP5HA1EhU42NRo3ygx3zvLRJ1nkw1NA5nCSegwcYkSfkZBQBzqMDsCGnNK').recover(eos.Buffer('00'.repeat(32) + '20d8af5a0000b32bcc0e37eb0000000000010000000000ea305500409e9a2264b89a010000000000ea305500000000a8ed32327c0000000000ea305500001059b1abe93101000000010002c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf01000001000000010002c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf0100000100000000010000000000ea305500000000a8ed32320100', 'hex')).toString()

Test case 2 (FAIL - Pub Key is different) eosjs_ecc.Signature.fromStringOrThrow('EOSKkwLhwDoRF8gpGFbcUKiaPdeeKo6U7eDuXQw9szMiNE4K4cFe17sffk6hmy3mWf1ogtzd5J5kvnvFD3Lq5cF6VyYb3KsGy').recover(eosjs_ecc.Buffer('00'.repeat(32) + '30d3b35a0000be0194c22fe70000000000010000000000ea305500409e9a2264b89a010000000000ea305500000000a8ed32327c0000000000ea305500000059b1abe93101000000010002c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf01000001000000010002c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf0100000100000000010000000000ea305500000000a8ed32320100', 'hex')).toString()

ellipticasec commented 6 years ago

@abourget ^^

jcalfee commented 6 years ago

Here is what I get:

> ecc = Eos.modules.ecc
> ecc.recover('EOSK5yY5ehsnDMc6xcRhsLYzFuZGUaKwb4hc8oLmP5HA1EhU42NRo3ygx3zvLRJ1nkw1NA5nCSegwcYkSfkZBQBzqMDsCGnNK', Buffer.from('00'.repeat(32) + '20d8af5a0000b32bcc0e37eb0000000000010000000000ea305500409e9a2264b89a010000000000ea305500000000a8ed32327c0000000000ea305500001059b1abe93101000000010002c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf01000001000000010002c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf0100000100000000010000000000ea305500000000a8ed32320100', 'hex'))
'EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV'

> ecc.recover('EOSKkwLhwDoRF8gpGFbcUKiaPdeeKo6U7eDuXQw9szMiNE4K4cFe17sffk6hmy3mWf1ogtzd5J5kvnvFD3Lq5cF6VyYb3KsGy', Buffer.from('00'.repeat(32) + '30d3b35a0000be0194c22fe70000000000010000000000ea305500409e9a2264b89a010000000000ea305500000000a8ed32327c0000000000ea305500000059b1abe93101000000010002c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf01000001000000010002c0ded2bc1f1305fb0faac5e6c03ee3a1924234985427b6167ca569d13df435cf0100000100000000010000000000ea305500000000a8ed32320100', 'hex'))
'EOS5DguRMaGh72NvbVX5LKHTb5cvbRmAxgrm9i2NNPKv5TC7FadXs'

If your signature and transaction data do not match, you'll get a different public key. There will be no error, that is how the recover works.

Are you sure the second signature and transaction match? It is usually a bug in the data, the signature recovery is reliable.

jcalfee commented 6 years ago

As a side note, I recall now that the data parameter can be a string, but that the string is treated as utf-8 (so hex data does not work). That default should probably be changed from utf-8 to hex. If large binary or utf-8 were needed, it would be reasonable to expect a Buffer object.

abourget commented 6 years ago

@jcalfee are you aware of any changes recently about canonical signatures?

I've implemented something very similar to the JS algorithm (wrapping https://github.com/btcsuite/btcd/tree/master/btcec ) and I keep getting errors from the server (intermittent, though) saying the signature isn't canonical.

Have you worked on canonicalizing your sigs?

jcalfee commented 6 years ago

No recent changes on my side. I will need to check the server side as soon as I find some time.

jcalfee commented 6 years ago

@abourget no changes .. the back-end error is "signature is no canonical" .. Two files match, and recent changes to one involves porting to FreeBSD.

https://github.com/EOSIO/eos/search?utf8=%E2%9C%93&q=%22signature+is+not+canonical%22&type=

jcalfee commented 6 years ago

@ellipticasec is the problem still happening.. I noticed the transaction expiration dates were are apart maybe it was an error somewhere else?