Skip to content

set ecdsa_raw_recover to accept 0 or 1 as valid v values#100

Merged
pacrob merged 2 commits into
ApeWorX:mainfrom
pacrob:fix-v-value-check
Aug 30, 2024
Merged

set ecdsa_raw_recover to accept 0 or 1 as valid v values#100
pacrob merged 2 commits into
ApeWorX:mainfrom
pacrob:fix-v-value-check

Conversation

@pacrob

@pacrob pacrob commented Aug 27, 2024

Copy link
Copy Markdown
Contributor

What was wrong?

In ecdsa_raw_recover, the value check for v looked for `27 <= v <=34, while the error message indicated 27-31.

Closes #67

How was it fixed?

I believe the intended check should be looking for a v value of 27-30 inclusive, meaning the argument to the function should be in [0, 1, 2, 3]. This would be consistent with the error message, taking the python sense of range of lower number inclusive, higher number exclusive. I've clarified the error message range and used 0-3 instead of 27-30, as that is what the arg passed to the function would be.

On the actual value check, I'm unable to find any reference to a v value in [27-34]. Pre-EIP155 Ethereum used [0-1], other "standard" implementations use [0-3], and post-EIP155 Ethereum uses {0,1} + CHAIN_ID * 2 + 35. This function looks like it was written to accept [0-3], but in testing other functions in the same file, I'm not able to generate a v other that 0 or 1.

It would be great to update to work with post-EIP155 v values, but that would need more research to see what else is affected. Out of scope for this PR.

Updated: Setting to accept only values of 0 or 1, in line with the pre-EIP155 Ethereum-specific standard.

This same bug exists in py_ecc - https://github.com/ethereum/py_ecc/blob/93edf6d654c06fff017ba77a103d59aae48edcd7/py_ecc/secp256k1/secp256k1.py#L262

Once merged, I'll make the same fix there.

Todo:

  • Clean up commit history
  • Add or update documentation related to these changes
  • Add entry to the release notes

Cute Animal Picture

image

@pacrob pacrob force-pushed the fix-v-value-check branch from 2054e03 to db30752 Compare August 27, 2024 21:30
@pacrob pacrob requested review from fselmo, kclowes and reedsa August 28, 2024 17:29

@kclowes kclowes left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@fselmo fselmo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does the range 0-3 come from with "other implementations"? If we're to keep to Ethereum and not accounting for EIP-155, should we keep this check to 27 and 28 only? This may be different for py-ecc (not ethereum-specific) but I do think it's also going to be 0 or 1 only.

The error message also throws me off as a reader. I'd rather have the check 0-1 inclusive (if we choose 27-28) before we add 27 - so raising the BadSignature at line 155. Otherwise, we should keep 27-28 in the error message.

Comment thread eth_keys/backends/native/ecdsa.py Outdated
@fselmo

fselmo commented Aug 28, 2024

Copy link
Copy Markdown
Contributor

@pacrob I'm not convinced on 27-30 range. Where is that coming from? If this is meant to be used as Ethereum, should we not keep this to 0-1 v values (27-28)?

OpenZeppelin ECDSA.sol (0 or 1): https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol#L103

@pacrob

pacrob commented Aug 28, 2024

Copy link
Copy Markdown
Contributor Author

@fselmo It comes from other more generalized implementations of ecdsa. The second two links are examples. That, combined with what I dook as the intent of the original error message, are why I decided to keep it allowing 0-3 instead of just 0-1.

@fselmo

fselmo commented Aug 28, 2024

Copy link
Copy Markdown
Contributor

@pacrob the second link seems to reinforce the original implementation more than this one to me (27-34). Unless we are wanting to change this to the uncompressed key range only (27-30). But I'm not sure why we'd take that path either.

I'd prefer an approach where we consider the context of the library itself and the bounds within which the method should be used.

  • If eth-keys is meant for Ethereum, I think we should change this to 27-28 strictly. This is my current stance but I can be convinced otherwise.

  • If eth-keys is meant to handle more contexts, independent of what the intent of the original author was, I think we should then consider it based on that and apply that logic here.

If we take the second approach, I guess I'm confused why we're going from validating the whole range of uncompresssed + compressed key cases for the "recid" example in that comment (27-34) to validating only the uncompressed cases (27-30), when all we really care about, and all that Solidity and other implementations check for afaict, is 0 or 1 {27, 28}.

@pacrob pacrob force-pushed the fix-v-value-check branch from 36c76c4 to 1e843aa Compare August 28, 2024 19:14
@pacrob pacrob changed the title set ecdsa_raw_recover to accept 0-3 as valid v values set ecdsa_raw_recover to accept 0 or 1 as valid v values Aug 28, 2024

@fselmo fselmo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm 👍🏼

@pacrob pacrob merged commit 1cbc4ff into ApeWorX:main Aug 30, 2024
@pacrob pacrob deleted the fix-v-value-check branch August 30, 2024 19:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mismatch between error message and validation range

3 participants