Skip to content

Commit 4825a53

Browse files
committed
xdsa: simplify some duplicated code
1 parent 77fe074 commit 4825a53

File tree

1 file changed

+24
-33
lines changed

1 file changed

+24
-33
lines changed

src/xdsa/mod.rs

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ const SIGNATURE_PREFIX: &[u8] = b"CompositeAlgorithmSignatures2025";
2424
/// Label is the signature label for ML-DSA-65-Ed25519-SHA512.
2525
const SIGNATURE_DOMAIN: &[u8] = b"COMPSIG-MLDSA65-Ed25519-SHA512";
2626

27+
/// OID is the ASN.1 object identifier for MLDSA65-Ed25519-SHA512.
28+
const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.6.1.5.5.7.6.48");
29+
2730
/// SecretKey is an ML-DSA-65 private key paired with an Ed25519 private key for
2831
/// creating and verifying quantum resistant digital signatures.
2932
#[derive(Clone)]
@@ -68,22 +71,17 @@ impl SecretKey {
6871
// Parse the DER encoded container
6972
let info = pkcs8::PrivateKeyInfo::from_der(der)?;
7073

71-
// Ensure the algorithm OID matches MLDSA65-Ed25519-SHA512 (1.3.6.1.5.5.7.6.48)
72-
if info.algorithm.oid.to_string() != "1.3.6.1.5.5.7.6.48" {
74+
// Ensure the algorithm OID matches MLDSA65-Ed25519-SHA512
75+
if info.algorithm.oid != OID {
7376
return Err("not a composite ML-DSA-65-Ed25519-SHA512 private key".into());
7477
}
7578
// Private key is ML-DSA seed (32) || Ed25519 seed (32) = 64 bytes
76-
let key_bytes = info.private_key;
77-
if key_bytes.len() != 64 {
78-
return Err("composite private key must be 64 bytes".into());
79-
}
80-
let ml_seed: [u8; 32] = key_bytes[..32].try_into()?;
81-
let ed_seed: [u8; 32] = key_bytes[32..64].try_into()?;
82-
83-
let ml_key = mldsa::SecretKey::from_seed(&ml_seed);
84-
let ed_key = eddsa::SecretKey::from_bytes(&ed_seed);
79+
let seed: [u8; 64] = info
80+
.private_key
81+
.try_into()
82+
.map_err(|_| "composite private key must be 64 bytes")?;
8583

86-
Ok(Self { ml_key, ed_key })
84+
Ok(Self::from_seed(&seed))
8785
}
8886

8987
/// from_pem parses a PEM string into a private key.
@@ -118,13 +116,11 @@ impl SecretKey {
118116
// Create the MLDSA65-Ed25519-SHA512 algorithm identifier; parameters
119117
// MUST be absent
120118
let alg = pkcs8::AlgorithmIdentifierRef {
121-
oid: ObjectIdentifier::new_unwrap("1.3.6.1.5.5.7.6.48"),
119+
oid: OID,
122120
parameters: None,
123121
};
124122
// The private key is ML-DSA seed (32) || Ed25519 seed (32) = 64 bytes
125-
let mut key_bytes = Vec::with_capacity(64);
126-
key_bytes.extend_from_slice(&self.ml_key.to_seed());
127-
key_bytes.extend_from_slice(&self.ed_key.to_bytes());
123+
let key_bytes = self.to_seed();
128124

129125
let info = pkcs8::PrivateKeyInfo {
130126
algorithm: alg,
@@ -209,22 +205,19 @@ impl PublicKey {
209205
let info: SubjectPublicKeyInfo<AlgorithmIdentifier<AnyRef>, BitStringRef> =
210206
SubjectPublicKeyInfo::from_der(der)?;
211207

212-
// Ensure the algorithm OID matches MLDSA65-Ed25519-SHA512 (1.3.6.1.5.5.7.6.48)
213-
if info.algorithm.oid.to_string() != "1.3.6.1.5.5.7.6.48" {
208+
// Ensure the algorithm OID matches MLDSA65-Ed25519-SHA512
209+
if info.algorithm.oid != OID {
214210
return Err("not a composite ML-DSA-65-Ed25519-SHA512 public key".into());
215211
}
216212
// Public key is ML-DSA-65 (1952 bytes) || Ed25519 (32 bytes) = 1984 bytes
217-
let key_bytes = info.subject_public_key.as_bytes().unwrap();
218-
if key_bytes.len() != 1984 {
219-
return Err("composite public key must be 1984 bytes".into());
220-
}
221-
let ml_bytes: [u8; 1952] = key_bytes[..1952].try_into()?;
222-
let ed_bytes: [u8; 32] = key_bytes[1952..].try_into()?;
223-
224-
let ml_key = mldsa::PublicKey::from_bytes(&ml_bytes);
225-
let ed_key = eddsa::PublicKey::from_bytes(&ed_bytes)?;
226-
227-
Ok(Self { ml_key, ed_key })
213+
let key_bytes: [u8; 1984] = info
214+
.subject_public_key
215+
.as_bytes()
216+
.ok_or("invalid public key bit string")?
217+
.try_into()
218+
.map_err(|_| "composite public key must be 1984 bytes")?;
219+
220+
Self::from_bytes(&key_bytes)
228221
}
229222

230223
/// from_pem parses a PEM string into a public key.
@@ -251,13 +244,11 @@ impl PublicKey {
251244
// Create the MLDSA65-Ed25519-SHA512 algorithm identifier; parameters
252245
// MUST be absent
253246
let alg = spki::AlgorithmIdentifierRef {
254-
oid: ObjectIdentifier::new_unwrap("1.3.6.1.5.5.7.6.48"),
247+
oid: OID,
255248
parameters: None,
256249
};
257250
// The public key info is the BITSTRING of the two keys concatenated
258-
let mut key_bytes = Vec::with_capacity(1984);
259-
key_bytes.extend_from_slice(&self.ml_key.to_bytes());
260-
key_bytes.extend_from_slice(&self.ed_key.to_bytes());
251+
let key_bytes = self.to_bytes();
261252

262253
let info = SubjectPublicKeyInfo::<AnyRef, BitStringRef> {
263254
algorithm: alg,

0 commit comments

Comments
 (0)