-
Notifications
You must be signed in to change notification settings - Fork 183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
k256: v0.13.2 breaking verification #991
Comments
This was actually a bugfix: #675 accidentally removed checks for low-S normalization which was released as If you would like for the non-normalized signatures to verify, you need to normalize them first with |
In order to accept both low and high S, is it safe to do Signature::normalize_s also in |
@webmaster128 you'll also need to flip the lowest bit in the recovery ID if Also hopefully recovery now accepts non-normalized signatures as of this PR: RustCrypto/signatures#793 However you'd have to try |
Oh sweet, thanks a lot! Just to double check: this diff correctly restores the 0.13.1 behaviour for recover pubkey and from 0.14 onwards I can remove it again? --- a/packages/crypto/src/secp256k1.rs
+++ b/packages/crypto/src/secp256k1.rs
@@ -105,18 +105,24 @@ pub fn secp256k1_recover_pubkey(
let signature = read_signature(signature)?;
// params other than 0 and 1 are explicitly not supported
- let id = match recovery_param {
+ let mut id = match recovery_param {
0 => RecoveryId::new(false, false),
1 => RecoveryId::new(true, false),
_ => return Err(CryptoError::invalid_recovery_param()),
};
// Compose extended signature
- let signature = Signature::from_bytes(&signature.into())
+ let mut signature = Signature::from_bytes(&signature.into())
.map_err(|e| CryptoError::generic_err(e.to_string()))?;
// Recover
let message_digest = Identity256::new().chain(message_hash);
+
+ if let Some(normalized) = signature.normalize_s() {
+ signature = normalized;
+ id = RecoveryId::new(!id.is_y_odd(), id.is_x_reduced());
+ }
+
let pubkey = VerifyingKey::recover_from_digest(message_digest, &signature, id)
.map_err(|e| CryptoError::generic_err(e.to_string()))?;
let encoded: Vec<u8> = pubkey.to_encoded_point(false).as_bytes().into(); At least tests seem to be passing with this. |
I tried using the current version from git, but it fails to compile in sha2 with 0.11.0-pre.2:
However, the above diff passes all tests I have currently available using k256 version 0.13.3: CosmWasm/cosmwasm@818ec58 |
@webmaster128 I'll try to get another release out which fixes that, but in the meantime you can do the following: [patch.crates-io.sha2]
git = "https://github.com/RustCrypto/hashes.git" |
The version of |
Very nice, thanks! I got it working in two ways now:
Could you confirm the solution in 2. is correct? It passes tests but my math is not strong enough to ensure it's the right thing to do. Would be great to have something before 0.14.0 is out that does not require us to pin k256 to 0.13.1. |
@webmaster128 yep, that looks fine for now and can be removed in the next release |
Updating
k256
to v0.13.2 is breaking verification that worked with v0.13.1. A snippet of the code is below. The full example can be found at k256-failure. The key and signatures come from test X.509 data generated by OpenSSL.The text was updated successfully, but these errors were encountered: