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.
This commit is contained in:
xjd
2024-07-24 00:14:26 +08:00
committed by GitHub
parent 62419f8b10
commit 7bcbfdefa3
2 changed files with 28 additions and 11 deletions
Generated
+7
View File
@@ -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"
+21 -11
View File
@@ -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<C>,
recovery_id: RecoveryId,
) -> Result<Self> {
let vk = Self::recover_from_prehash_noverify(prehash, signature, recovery_id)?;
// Ensure signature verifies with the recovered key
verify_prehashed::<C>(
&ProjectivePoint::<C>::from(*vk.as_affine()),
&bits2field::<C>(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<C>,
recovery_id: RecoveryId,
) -> Result<Self> {
let (r, s) = signature.split_scalars();
let z = <Scalar<C> as Reduce<C::Uint>>::reduce_bytes(&bits2field::<C>(prehash)?);
@@ -296,16 +315,7 @@ where
let u1 = -(r_inv * z);
let u2 = r_inv * *s;
let pk = ProjectivePoint::<C>::lincomb(&[(ProjectivePoint::<C>::generator(), u1), (R, u2)]);
let vk = Self::from_affine(pk.into())?;
// Ensure signature verifies with the recovered key
verify_prehashed::<C>(
&ProjectivePoint::<C>::from(*vk.as_affine()),
&bits2field::<C>(prehash)?,
signature,
)?;
Ok(vk)
Self::from_affine(pk.into())
}
}