ml-dsa: rename ExpandedSigningKey field/method to expanded_key (#1340)

This is a vestige from when `SigningKey` was a keypair type.

Also marks it `#[doc(hidden)]` as it exists primarily for testing.
This commit is contained in:
Tony Arcieri
2026-05-08 09:34:29 -06:00
committed by GitHub
parent e5f9f64231
commit f9f4c60d78
8 changed files with 45 additions and 44 deletions
+3 -3
View File
@@ -27,7 +27,7 @@ fn criterion_benchmark(c: &mut Criterion) {
let ctx: B32 = rand(&mut rng);
let kp = MlDsa65::from_seed(&xi);
let sk = kp.signing_key();
let sk = kp.expanded_key();
let vk = kp.verifying_key();
let sig = sk.sign_deterministic(&m, &ctx).unwrap();
@@ -39,7 +39,7 @@ fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("keygen", |b| {
b.iter(|| {
let kp = MlDsa65::from_seed(&xi);
let _sk_bytes = kp.signing_key().to_expanded();
let _sk_bytes = kp.expanded_key().to_expanded();
let _vk_bytes = kp.verifying_key().encode();
});
});
@@ -65,7 +65,7 @@ fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("round_trip", |b| {
b.iter(|| {
let kp = MlDsa65::from_seed(&xi);
let sig = kp.signing_key().sign_deterministic(&m, &ctx).unwrap();
let sig = kp.expanded_key().sign_deterministic(&m, &ctx).unwrap();
let _ver = kp.verifying_key().verify_with_context(&m, &ctx, &sig);
});
});
+21 -21
View File
@@ -10,11 +10,11 @@
#![allow(clippy::many_single_char_names)] // Allow notation matching the spec
#![allow(clippy::clone_on_copy)] // Be explicit about moving data
//! # Quickstart
//! # Usage
//!
//! ```
//! # #[cfg(feature = "rand_core")]
//! # {
#![cfg_attr(feature = "rand_core", doc = "```")]
#![cfg_attr(not(feature = "rand_core"), doc = "```ignore")]
//! # fn main() -> Result<(), signature::Error> {
//! use ml_dsa::{
//! signature::{Keypair, Signer, Verifier},
//! MlDsa65, KeyGen,
@@ -22,13 +22,13 @@
//! use getrandom::{SysRng, rand_core::UnwrapErr};
//!
//! let mut rng = UnwrapErr(SysRng);
//! let kp = MlDsa65::key_gen(&mut rng);
//! let sk = MlDsa65::key_gen(&mut rng);
//!
//! let msg = b"Hello world";
//! let sig = kp.signing_key().sign(msg);
//! let sig = sk.sign(msg);
//!
//! assert!(kp.verifying_key().verify(msg, &sig).is_ok());
//! # }
//! sk.verifying_key().verify(msg, &sig)?;
//! # Ok(()) }
//! ```
#[cfg(feature = "alloc")]
@@ -307,7 +307,7 @@ where
let signing_key = ExpandedSigningKey::new(rho, K, tr, s1, s2, t0, A_hat);
SigningKey {
signing_key,
expanded_key: signing_key,
seed: xi.clone(),
}
}
@@ -385,7 +385,7 @@ mod test {
let ssk = P::from_seed(&seed);
assert_eq!(ssk.to_seed(), seed);
let sk = &ssk.signing_key;
let sk = &ssk.expanded_key;
let vk = ssk.verifying_key();
let vk_bytes = vk.encode();
@@ -419,7 +419,7 @@ mod test {
P: MlDsaParams + PartialEq,
{
let ssk = P::from_seed(&Array::default());
let sk = &ssk.signing_key;
let sk = &ssk.expanded_key;
let vk = ssk.verifying_key();
let vk_derived = sk.verifying_key();
@@ -438,7 +438,7 @@ mod test {
P: MlDsaParams,
{
let ssk = P::from_seed(&Array::default());
let sk = &ssk.signing_key;
let sk = &ssk.expanded_key;
let vk = ssk.verifying_key();
let M = b"Hello world";
@@ -462,7 +462,7 @@ mod test {
P: MlDsaParams,
{
let ssk = P::from_seed(&Array::default());
let sk = &ssk.signing_key;
let sk = &ssk.expanded_key;
let vk = ssk.verifying_key();
let M = b"Hello world";
@@ -484,7 +484,7 @@ mod test {
P: MlDsaParams,
{
let ssk = P::from_seed(&Array::default());
let sk = &ssk.signing_key;
let sk = &ssk.expanded_key;
let vk = ssk.verifying_key();
let M = b"Hello world";
@@ -506,7 +506,7 @@ mod test {
P: MlDsaParams,
{
let ssk = P::from_seed(&Array::default());
let sk = &ssk.signing_key;
let sk = &ssk.expanded_key;
let vk = ssk.verifying_key();
let M = b"Hello world";
@@ -530,7 +530,7 @@ mod test {
let seed = Seed::default();
let ssk = P::from_seed(&seed);
let sk1 = ExpandedSigningKey::<P>::from_seed(&seed);
assert_eq!(ssk.signing_key, sk1);
assert_eq!(ssk.expanded_key, sk1);
}
assert_from_seed_equality::<MlDsa44>();
assert_from_seed_equality::<MlDsa65>();
@@ -560,7 +560,7 @@ mod test {
let msg = b"Hello world";
let rnd = Array([0u8; 32]);
let mut sig = kp.signing_key().sign_internal(&[msg], &rnd);
let mut sig = kp.expanded_key().sign_internal(&[msg], &rnd);
sig.c_tilde[0] ^= 0xFF;
assert!(!vk.verify_with_context(msg, &[], &sig));
@@ -579,7 +579,7 @@ mod test {
let msg1 = b"Hello world";
let msg2 = b"Wrong message";
let rnd = Array([0u8; 32]);
let sig = kp.signing_key().sign_internal(&[msg1], &rnd);
let sig = kp.expanded_key().sign_internal(&[msg1], &rnd);
assert!(!vk.verify_with_context(msg2, &[], &sig));
}
@@ -592,7 +592,7 @@ mod test {
fn context_length_validation() {
fn test_ctx_length<P: MlDsaParams>() {
let ssk = P::from_seed(&Array::default());
let sk = ssk.signing_key();
let sk = ssk.expanded_key();
let vk = ssk.verifying_key();
let msg = b"Hello world";
@@ -615,7 +615,7 @@ mod test {
fn test_derived_vk<P: MlDsaParams>() {
let seed = Array([42u8; 32]);
let ssk = P::from_seed(&seed);
let sk = ssk.signing_key();
let sk = ssk.expanded_key();
let derived_vk = sk.verifying_key();
let msg = b"Test message for derived key";
@@ -644,7 +644,7 @@ mod test {
assert!(kp_debug.contains("SigningKey"));
let mut sk_debug = alloc::string::String::new();
write!(&mut sk_debug, "{:?}", kp.signing_key()).unwrap();
write!(&mut sk_debug, "{:?}", kp.expanded_key()).unwrap();
assert!(sk_debug.contains("ExpandedSigningKey"));
}
test_debug::<MlDsa44>();
+1 -1
View File
@@ -151,7 +151,7 @@ where
fn try_from(private_key_info: ::pkcs8::PrivateKeyInfoRef<'_>) -> ::pkcs8::Result<Self> {
let keypair = SigningKey::try_from(private_key_info)?;
Ok(keypair.signing_key)
Ok(keypair.expanded_key)
}
}
+14 -13
View File
@@ -33,19 +33,14 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
// TODO(tarcieri): reduce field-level visibility.
#[derive(Clone)]
pub struct SigningKey<P: MlDsaParams> {
/// The signing key of the key pair
pub(crate) signing_key: ExpandedSigningKey<P>,
/// The expanded form of the signing key.
pub(crate) expanded_key: ExpandedSigningKey<P>,
/// The seed this signing key was derived from
pub(crate) seed: B32,
}
impl<P: MlDsaParams> SigningKey<P> {
/// The signing key of the key pair
pub fn signing_key(&self) -> &ExpandedSigningKey<P> {
&self.signing_key
}
/// Serialize the [`Seed`] value: 32-bytes which can be used to reconstruct the
/// [`SigningKey`].
///
@@ -58,6 +53,12 @@ impl<P: MlDsaParams> SigningKey<P> {
pub fn to_seed(&self) -> Seed {
self.seed
}
/// The expanded form of the signing key.
#[doc(hidden)]
pub fn expanded_key(&self) -> &ExpandedSigningKey<P> {
&self.expanded_key
}
}
impl<P: MlDsaParams> fmt::Debug for SigningKey<P> {
@@ -69,7 +70,7 @@ impl<P: MlDsaParams> fmt::Debug for SigningKey<P> {
impl<P: MlDsaParams> signature::Keypair for SigningKey<P> {
type VerifyingKey = VerifyingKey<P>;
fn verifying_key(&self) -> VerifyingKey<P> {
self.signing_key.verifying_key()
self.expanded_key.verifying_key()
}
}
@@ -85,7 +86,7 @@ impl<P: MlDsaParams> Signer<Signature<P>> for SigningKey<P> {
/// only supports signing with an empty context string.
impl<P: MlDsaParams> MultipartSigner<Signature<P>> for SigningKey<P> {
fn try_multipart_sign(&self, msg: &[&[u8]]) -> Result<Signature<P>, Error> {
self.signing_key.raw_sign_deterministic(msg, &[])
self.expanded_key.raw_sign_deterministic(msg, &[])
}
}
@@ -96,7 +97,7 @@ impl<P: MlDsaParams> DigestSigner<Shake256, Signature<P>> for SigningKey<P> {
&self,
f: F,
) -> Result<Signature<P>, Error> {
self.signing_key.try_sign_digest(&f)
self.expanded_key.try_sign_digest(&f)
}
}
@@ -108,8 +109,8 @@ impl<P: MlDsaParams> PartialEq for SigningKey<P> {
impl<P: MlDsaParams> CtEq for SigningKey<P> {
fn ct_eq(&self, other: &Self) -> Choice {
self.signing_key
.ct_eq(&other.signing_key)
self.expanded_key
.ct_eq(&other.expanded_key)
.and(self.seed.ct_eq(&other.seed))
}
}
@@ -180,7 +181,7 @@ impl<P: MlDsaParams> ExpandedSigningKey<P> {
#[must_use]
pub fn from_seed(seed: &Seed) -> Self {
let kp = P::from_seed(seed);
kp.signing_key
kp.expanded_key
}
/// This method reflects the ML-DSA.Sign_internal algorithm from FIPS 204. It does not
+1 -1
View File
@@ -36,7 +36,7 @@ fn verify<P: MlDsaParams>(tc: &acvp::TestCase) {
let sk_bytes = ExpandedSigningKeyBytes::<P>::try_from(tc.sk.as_slice()).unwrap();
let ssk = P::from_seed(&seed);
let sk = ssk.signing_key().clone();
let sk = ssk.expanded_key().clone();
let vk = ssk.verifying_key().clone();
assert_eq!(vk.encode(), vk_bytes);
+1 -1
View File
@@ -22,7 +22,7 @@ fn private_key_serialization() {
{
let sk = ExpandedSigningKey::<P>::from_pkcs8_pem(private_bytes).expect("parse private key");
let ssk = SigningKey::<P>::from_pkcs8_pem(private_bytes).expect("parse private key");
assert!(sk == *ssk.signing_key());
assert!(sk == *ssk.expanded_key());
assert_eq!(
ssk.to_pkcs8_pem(LineEnding::LF)
.expect("serialize private seed")
+3 -3
View File
@@ -30,7 +30,7 @@ macro_rules! mldsa_proptests {
rnd in any::<[u8; 32]>()
) {
let kp = $alg::from_seed(&seed.into());
let sk = kp.signing_key();
let sk = kp.expanded_key();
let vk = kp.verifying_key();
let sig = sk.sign_internal(&[&msg], &rnd.into());
@@ -44,7 +44,7 @@ macro_rules! mldsa_proptests {
msg in collection::vec(0u8..u8::MAX, 0..65536),
) {
let kp = $alg::from_seed(&seed.into());
let sk = kp.signing_key();
let sk = kp.expanded_key();
let vk = kp.verifying_key();
let sig = sk.sign_digest(|digest| digest.update(&msg));
@@ -60,7 +60,7 @@ macro_rules! mldsa_proptests {
msg in collection::vec(0u8..u8::MAX, 0..65536),
) {
let kp = $alg::from_seed(&seed.into());
let sk = kp.signing_key();
let sk = kp.expanded_key();
let vk = kp.verifying_key();
let mut rng = rand_core::UnwrapErr(getrandom::SysRng);
+1 -1
View File
@@ -83,7 +83,7 @@ macro_rules! mldsa_sign_seed_test {
let sig = sk.sign(&test.msg);
assert_eq!(&*sig.to_bytes(), test.sig.as_slice());
} else {
let result = sk.signing_key().sign_deterministic(&test.msg, &test.ctx);
let result = sk.expanded_key().sign_deterministic(&test.msg, &test.ctx);
match test.result {
ExpectedResult::Valid => {