q9f / eth.rb

a straightforward library to build, sign, and broadcast ethereum transactions anywhere you can run ruby.
https://q9f.github.io/eth.rb
Apache License 2.0
204 stars 88 forks source link

eth/signature: Unable to recover/verify some signatures from Ledger wallets #138

Closed tiagofragoso closed 2 years ago

tiagofragoso commented 2 years ago

There's a notable inconsistency between different ETH client implementations regarding the last byte (v) of personal_sign. Most clients return 1b or 1c (27, 28) but some return 00 or 01. See example discussion.

The Ledger wallet returns 00 or 01, meaning that with the current implementation of this library, only 01 would work with the default chain_id = 1 (ETH mainnet).

https://github.com/q9f/eth.rb/blob/6e1a491f2cc4bc8be0abe2197b58e821cfd53abc/lib/eth/signature.rb#L73

I was able to verify signatures from the Ledger using Ethers with no problem and also found some code in eth ~> 0.4 that seems to address this issue, although I did not explicitly test it.

As pointed out here, message signatures should not depend on the chain id.

q9f commented 2 years ago

Thank you for raising this.

This was initially patched in https://github.com/se3000/ruby-eth/pull/48

We have a test case for this: https://github.com/q9f/eth.rb/blob/main/spec/eth/signature_spec.rb#L183-L188

However, it does not cover all valid ledger v as you correctly pointed out and was broken with #43

Should be easy to patch. Stay tuned.

mboyle commented 2 years ago

+1 on this--causing issues for us in production. Is there any guidance on how to fix?

tiagofragoso commented 2 years ago

@mboyle if your use case is message signatures but not transaction signatures, I think you could get away with using chain_id = 0 as your last argument to verify/personal_recover. That will fulfil the v < chain_id check and you should be able to extract/verify the signer. https://github.com/q9f/eth.rb/blob/6e1a491f2cc4bc8be0abe2197b58e821cfd53abc/lib/eth/signature.rb#L73

mboyle commented 2 years ago

@tiagofragoso this totally worked, thank you so much, you're a lifesaver!