From 7bcbfdefa378ec8b80fe333d4430bd4dee9e32fa Mon Sep 17 00:00:00 2001 From: xjd Date: Wed, 24 Jul 2024 00:14:26 +0800 Subject: [PATCH] ecdsa: add `VerifyingKey::recover_from_prehash_noverify` (#831) If the recovered public key isn't correct, an error occurs when comparing it to the correct public key or public key hash. Therefore, we can skip this expensive verification. --- Cargo.lock | 7 +++++++ ecdsa/src/recovery.rs | 32 +++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7ec9b4..478c274 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -676,6 +676,13 @@ version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +[[package]] +name = "ml-dsa" +version = "0.1.0-pre" +dependencies = [ + "signature", +] + [[package]] name = "num-bigint" version = "0.4.4" diff --git a/ecdsa/src/recovery.rs b/ecdsa/src/recovery.rs index 7846982..8b6e559 100644 --- a/ecdsa/src/recovery.rs +++ b/ecdsa/src/recovery.rs @@ -266,11 +266,30 @@ where /// Recover a [`VerifyingKey`] from the given `prehash` of a message, the /// signature over that prehashed message, and a [`RecoveryId`]. - #[allow(non_snake_case)] pub fn recover_from_prehash( prehash: &[u8], signature: &Signature, recovery_id: RecoveryId, + ) -> Result { + let vk = Self::recover_from_prehash_noverify(prehash, signature, recovery_id)?; + // Ensure signature verifies with the recovered key + verify_prehashed::( + &ProjectivePoint::::from(*vk.as_affine()), + &bits2field::(prehash)?, + signature, + )?; + Ok(vk) + } + + /// Recover a [`VerifyingKey`] from the given `prehash` of a message, the + /// signature over that prehashed message, and a [`RecoveryId`]. Compared to + /// `recover_from_prehash`, this function skips verification with the + /// recovered key. + #[allow(non_snake_case)] + pub fn recover_from_prehash_noverify( + prehash: &[u8], + signature: &Signature, + recovery_id: RecoveryId, ) -> Result { let (r, s) = signature.split_scalars(); let z = as Reduce>::reduce_bytes(&bits2field::(prehash)?); @@ -296,16 +315,7 @@ where let u1 = -(r_inv * z); let u2 = r_inv * *s; let pk = ProjectivePoint::::lincomb(&[(ProjectivePoint::::generator(), u1), (R, u2)]); - let vk = Self::from_affine(pk.into())?; - - // Ensure signature verifies with the recovered key - verify_prehashed::( - &ProjectivePoint::::from(*vk.as_affine()), - &bits2field::(prehash)?, - signature, - )?; - - Ok(vk) + Self::from_affine(pk.into()) } }