Skip to content

Commit 2fa345d

Browse files
eferolloromen
andcommitted
feat(ml-dsa): Implement verifying_key method for SigningKey
Introduce a utility method to derive a VerifyingKey from a SigningKey, even when the original seed or precomputed public key is unavailable. This aids in scenarios where private keys are imported from external sources lacking associated public key data. References: - https://github.com/RustCrypto/signatures/blob/6cc40e5c10b04dae44d91500d5a1afc4a3ff2b49/ml-dsa/src/lib.rs#L856 Co-authored-by: Nicola Tuveri <[email protected]> Signed-off-by: Francesco Rollo <[email protected]> Change-Id: I6a6a6964ee2d466e43dc65bf07cfb6d5b4bfa6c4
1 parent 6cc40e5 commit 2fa345d

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

ml-dsa/src/lib.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,23 @@ impl<P: MlDsaParams> SigningKey<P> {
504504
None,
505505
)
506506
}
507+
508+
/// This auxiliary function derives a `VerifyingKey` from a bare
509+
/// `SigningKey` (even in the absence of the original seed)
510+
///
511+
/// This is a utility function that is useful when importing the private key
512+
/// from an external source which does not export the seed and does not
513+
/// provide the precomputed public key associated with the private key
514+
/// itself.
515+
pub fn verifying_key(&self) -> VerifyingKey<P> {
516+
let As1 = &self.A_hat * &self.s1_hat;
517+
let t = &As1.ntt_inverse() + &self.s2;
518+
519+
/* Discard t0 */
520+
let (t1, _) = t.power2round();
521+
522+
VerifyingKey::new(self.rho.clone(), t1, Some(self.A_hat.clone()), None)
523+
}
507524
}
508525

509526
/// The `Signer` implementation for `SigningKey` uses the optional deterministic variant of ML-DSA, and
@@ -947,6 +964,25 @@ mod test {
947964
encode_decode_round_trip_test::<MlDsa87>();
948965
}
949966

967+
fn public_from_private_test<P>()
968+
where
969+
P: MlDsaParams + PartialEq,
970+
{
971+
let kp = P::key_gen_internal(&Array::default());
972+
let sk = kp.signing_key;
973+
let vk = kp.verifying_key;
974+
let vk_derived = sk.verifying_key();
975+
976+
assert!(vk == vk_derived);
977+
}
978+
979+
#[test]
980+
fn public_from_private() {
981+
public_from_private_test::<MlDsa44>();
982+
public_from_private_test::<MlDsa65>();
983+
public_from_private_test::<MlDsa87>();
984+
}
985+
950986
fn sign_verify_round_trip_test<P>()
951987
where
952988
P: MlDsaParams,

0 commit comments

Comments
 (0)