Skip to content

Commit c4ca7b7

Browse files
committed
API consistency
1 parent b978fd0 commit c4ca7b7

3 files changed

Lines changed: 47 additions & 24 deletions

File tree

boring/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ edition = { workspace = true }
1313
rust-version = { workspace = true }
1414

1515
[package.metadata.docs.rs]
16-
features = ["rpk", "underscore-wildcards"]
16+
features = ["rpk", "underscore-wildcards", "mlkem", "mldsa"]
1717
rustdoc-args = ["--cfg", "docsrs"]
1818

1919
[features]

boring/src/mldsa.rs

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ use crate::ffi;
2323
use crate::ffi::cbs_init;
2424

2525
/// Seed size (32 bytes, shared across all ML-DSA parameter sets).
26-
pub const SEED_BYTES: usize = ffi::MLDSA_SEED_BYTES as usize;
26+
pub const PRIVATE_KEY_SEED_BYTES: usize = ffi::MLDSA_SEED_BYTES as usize;
2727

2828
/// Raw bytes of a private key seed ([`SEED_BYTES`] long).
29-
pub type MlDsaSeed = [u8; SEED_BYTES];
29+
pub type MlDsaPrivateKeySeed = [u8; PRIVATE_KEY_SEED_BYTES];
3030

3131
/// ML-DSA parameter set selection.
3232
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -62,11 +62,13 @@ impl Algorithm {
6262
}
6363

6464
/// An ML-DSA public key (any parameter set).
65+
#[derive(Clone)]
6566
pub struct MlDsaPublicKey {
6667
algorithm: Algorithm,
6768
inner: PublicKeyInner,
6869
}
6970

71+
#[derive(Clone)]
7072
enum PublicKeyInner {
7173
MlDsa44(Box<ffi::MLDSA44_public_key>),
7274
MlDsa65(Box<ffi::MLDSA65_public_key>),
@@ -76,7 +78,7 @@ enum PublicKeyInner {
7678
/// An ML-DSA private key (any parameter set).
7779
pub struct MlDsaPrivateKey {
7880
algorithm: Algorithm,
79-
seed: MlDsaSeed,
81+
seed: MlDsaPrivateKeySeed,
8082
inner: PrivateKeyInner,
8183
}
8284

@@ -86,6 +88,12 @@ enum PrivateKeyInner {
8688
MlDsa87(Box<ffi::MLDSA87_private_key>),
8789
}
8890

91+
impl Clone for MlDsaPrivateKey {
92+
fn clone(&self) -> Self {
93+
Self::from_seed(self.algorithm, &self.seed).unwrap()
94+
}
95+
}
96+
8997
impl MlDsaPrivateKey {
9098
/// Generates a random ML-DSA key pair.
9199
///
@@ -96,14 +104,14 @@ impl MlDsaPrivateKey {
96104
match algorithm {
97105
Algorithm::MlDsa44 => {
98106
let mut pub_bytes = [0u8; ffi::MLDSA44_PUBLIC_KEY_BYTES as usize];
99-
let mut seed = [0u8; SEED_BYTES];
107+
let mut seed = [0u8; PRIVATE_KEY_SEED_BYTES];
100108
let mut priv_key: MaybeUninit<ffi::MLDSA44_private_key> = MaybeUninit::uninit();
101109
cvt(ffi::MLDSA44_generate_key(
102110
pub_bytes.as_mut_ptr(),
103111
seed.as_mut_ptr(),
104112
priv_key.as_mut_ptr(),
105113
))?;
106-
let public_key = MlDsaPublicKey::from_bytes(algorithm, &pub_bytes)?;
114+
let public_key = MlDsaPublicKey::from_slice(algorithm, &pub_bytes)?;
107115
Ok((
108116
public_key,
109117
MlDsaPrivateKey {
@@ -115,14 +123,14 @@ impl MlDsaPrivateKey {
115123
}
116124
Algorithm::MlDsa65 => {
117125
let mut pub_bytes = [0u8; ffi::MLDSA65_PUBLIC_KEY_BYTES as usize];
118-
let mut seed = [0u8; SEED_BYTES];
126+
let mut seed = [0u8; PRIVATE_KEY_SEED_BYTES];
119127
let mut priv_key: MaybeUninit<ffi::MLDSA65_private_key> = MaybeUninit::uninit();
120128
cvt(ffi::MLDSA65_generate_key(
121129
pub_bytes.as_mut_ptr(),
122130
seed.as_mut_ptr(),
123131
priv_key.as_mut_ptr(),
124132
))?;
125-
let public_key = MlDsaPublicKey::from_bytes(algorithm, &pub_bytes)?;
133+
let public_key = MlDsaPublicKey::from_slice(algorithm, &pub_bytes)?;
126134
Ok((
127135
public_key,
128136
MlDsaPrivateKey {
@@ -134,14 +142,14 @@ impl MlDsaPrivateKey {
134142
}
135143
Algorithm::MlDsa87 => {
136144
let mut pub_bytes = [0u8; ffi::MLDSA87_PUBLIC_KEY_BYTES as usize];
137-
let mut seed = [0u8; SEED_BYTES];
145+
let mut seed = [0u8; PRIVATE_KEY_SEED_BYTES];
138146
let mut priv_key: MaybeUninit<ffi::MLDSA87_private_key> = MaybeUninit::uninit();
139147
cvt(ffi::MLDSA87_generate_key(
140148
pub_bytes.as_mut_ptr(),
141149
seed.as_mut_ptr(),
142150
priv_key.as_mut_ptr(),
143151
))?;
144-
let public_key = MlDsaPublicKey::from_bytes(algorithm, &pub_bytes)?;
152+
let public_key = MlDsaPublicKey::from_slice(algorithm, &pub_bytes)?;
145153
Ok((
146154
public_key,
147155
MlDsaPrivateKey {
@@ -156,7 +164,7 @@ impl MlDsaPrivateKey {
156164
}
157165

158166
/// Regenerates a private key from a seed value.
159-
pub fn from_seed(algorithm: Algorithm, seed: &MlDsaSeed) -> Result<Self, ErrorStack> {
167+
pub fn from_seed(algorithm: Algorithm, seed: &MlDsaPrivateKeySeed) -> Result<Self, ErrorStack> {
160168
unsafe {
161169
ffi::init();
162170
match algorithm {
@@ -209,7 +217,7 @@ impl MlDsaPrivateKey {
209217
}
210218

211219
/// Returns the seed bytes for this private key.
212-
pub fn seed(&self) -> &MlDsaSeed {
220+
pub fn seed_bytes(&self) -> &MlDsaPrivateKeySeed {
213221
&self.seed
214222
}
215223

@@ -261,12 +269,20 @@ impl MlDsaPrivateKey {
261269

262270
impl MlDsaPublicKey {
263271
/// Parses a public key from its serialized form.
264-
pub fn from_bytes(algorithm: Algorithm, bytes: &[u8]) -> Result<Self, ErrorStack> {
272+
pub fn from_slice(
273+
algorithm: Algorithm,
274+
serialized_public_key: &[u8],
275+
) -> Result<Self, ErrorStack> {
276+
ffi::init();
277+
278+
if serialized_public_key.len() != algorithm.public_key_bytes() {
279+
return Err(ErrorStack::internal_error_str("invalid public key length"));
280+
}
281+
let mut cbs = cbs_init(serialized_public_key);
282+
265283
unsafe {
266-
ffi::init();
267284
match algorithm {
268285
Algorithm::MlDsa44 => {
269-
let mut cbs = cbs_init(bytes);
270286
let mut key: MaybeUninit<ffi::MLDSA44_public_key> = MaybeUninit::uninit();
271287
cvt(ffi::MLDSA44_parse_public_key(key.as_mut_ptr(), &mut cbs))?;
272288
if cbs.len != 0 {
@@ -280,7 +296,6 @@ impl MlDsaPublicKey {
280296
})
281297
}
282298
Algorithm::MlDsa65 => {
283-
let mut cbs = cbs_init(bytes);
284299
let mut key: MaybeUninit<ffi::MLDSA65_public_key> = MaybeUninit::uninit();
285300
cvt(ffi::MLDSA65_parse_public_key(key.as_mut_ptr(), &mut cbs))?;
286301
if cbs.len != 0 {
@@ -294,7 +309,6 @@ impl MlDsaPublicKey {
294309
})
295310
}
296311
Algorithm::MlDsa87 => {
297-
let mut cbs = cbs_init(bytes);
298312
let mut key: MaybeUninit<ffi::MLDSA87_public_key> = MaybeUninit::uninit();
299313
cvt(ffi::MLDSA87_parse_public_key(key.as_mut_ptr(), &mut cbs))?;
300314
if cbs.len != 0 {
@@ -398,9 +412,12 @@ mod tests {
398412
fn sign_and_verify() {
399413
let (pk, sk) = MlDsaPrivateKey::generate($alg).unwrap();
400414
let msg = b"test message";
401-
let sig = sk.sign(msg).unwrap();
402-
assert_eq!(sig.len(), $alg.signature_bytes());
403-
assert!(pk.verify(msg, &sig).is_ok());
415+
let sig1 = sk.sign(msg).unwrap();
416+
let sig2 = sk.clone().sign(msg).unwrap();
417+
assert_eq!(sig1.len(), $alg.signature_bytes());
418+
assert!(pk.verify(msg, &sig1).is_ok());
419+
assert!(pk.verify(msg, &sig2).is_ok());
420+
assert!(pk.clone().verify(msg, &sig1).is_ok());
404421
}
405422

406423
#[test]
@@ -422,18 +439,20 @@ mod tests {
422439
#[test]
423440
fn seed_roundtrip() {
424441
let (pk, sk) = MlDsaPrivateKey::generate($alg).unwrap();
425-
let sk2 = MlDsaPrivateKey::from_seed($alg, sk.seed()).unwrap();
442+
let sk2 = MlDsaPrivateKey::from_seed($alg, sk.seed_bytes()).unwrap();
426443
let msg = b"seed roundtrip";
427-
let sig = sk2.sign(msg).unwrap();
428-
assert!(pk.verify(msg, &sig).is_ok());
444+
let sig1 = sk2.sign(msg).unwrap();
445+
let sig2 = sk2.clone().sign(msg).unwrap();
446+
assert!(pk.verify(msg, &sig1).is_ok());
447+
assert!(pk.verify(msg, &sig2).is_ok());
429448
}
430449

431450
#[test]
432451
fn debug_redacts_seed() {
433452
let (_, sk) = MlDsaPrivateKey::generate($alg).unwrap();
434453
let dbg = format!("{:?}", sk);
435454
assert!(dbg.contains("redacted"));
436-
assert!(!dbg.contains(&format!("{:?}", sk.seed())));
455+
assert!(!dbg.contains(&format!("{:?}", sk.seed_bytes())));
437456
}
438457
}
439458
};

boring/src/mlkem.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,11 @@ mod tests {
688688
let (pk, sk) = MlKemPrivateKey::generate($algorithm).unwrap();
689689
let (ct, ss1) = pk.encapsulate().unwrap();
690690
let ss2 = sk.decapsulate(&ct).unwrap();
691+
let ss3 = sk.clone().decapsulate(&ct).unwrap();
692+
let ss4 = sk.decapsulate(&ct.clone()).unwrap();
691693
assert_eq!(ss1, ss2);
694+
assert_eq!(ss1, ss3);
695+
assert_eq!(ss1, ss4);
692696
}
693697

694698
#[test]

0 commit comments

Comments
 (0)