Skip to content

Commit b024fc5

Browse files
committed
all: type alias fingerprint to support embedding and encoding
1 parent a0dd63b commit b024fc5

File tree

7 files changed

+128
-27
lines changed

7 files changed

+128
-27
lines changed

examples/demo.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ fn main() {
3232
let root_public = root_secret.public_key();
3333
println!(
3434
" Root fingerprint: {}",
35-
hex::encode(&root_public.fingerprint())
35+
hex::encode(root_public.fingerprint().to_bytes())
3636
);
3737

3838
// =========================================================================
@@ -56,7 +56,7 @@ fn main() {
5656
.unwrap();
5757
println!(
5858
" Alice xDSA fingerprint: {}",
59-
hex::encode(&alice_xdsa_public.fingerprint())
59+
hex::encode(alice_xdsa_public.fingerprint().to_bytes())
6060
);
6161

6262
// =========================================================================
@@ -80,7 +80,7 @@ fn main() {
8080
.unwrap();
8181
println!(
8282
" Bob xDSA fingerprint: {}",
83-
hex::encode(&bob_xdsa_public.fingerprint())
83+
hex::encode(bob_xdsa_public.fingerprint().to_bytes())
8484
);
8585

8686
// =========================================================================
@@ -104,7 +104,7 @@ fn main() {
104104
.unwrap();
105105
println!(
106106
" Alice xHPKE fingerprint: {}",
107-
hex::encode(&alice_xhpke_public.fingerprint())
107+
hex::encode(alice_xhpke_public.fingerprint().to_bytes())
108108
);
109109

110110
// =========================================================================
@@ -128,7 +128,7 @@ fn main() {
128128
.unwrap();
129129
println!(
130130
" Bob xHPKE fingerprint: {}",
131-
hex::encode(&bob_xhpke_public.fingerprint())
131+
hex::encode(bob_xhpke_public.fingerprint().to_bytes())
132132
);
133133

134134
// =========================================================================

src/cose/mod.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ pub fn sign_at(
125125
) -> Vec<u8> {
126126
let protected = cbor::encode(&SigProtectedHeader {
127127
algorithm: ALGORITHM_ID_XDSA,
128-
kid: signer.fingerprint(),
128+
kid: signer.fingerprint().to_bytes(),
129129
timestamp,
130130
});
131131

@@ -335,7 +335,7 @@ pub fn seal_at(
335335
// Build protected header with recipient's fingerprint
336336
let protected = cbor::encode(&EncProtectedHeader {
337337
algorithm: ALGORITHM_ID_XHPKE,
338-
kid: recipient.fingerprint(),
338+
kid: recipient.fingerprint().to_bytes(),
339339
});
340340

341341
// Build and seal Enc_structure
@@ -455,8 +455,11 @@ fn verify_sig_protected_header(
455455
if header.algorithm != exp_algo {
456456
return Err(Error::UnexpectedAlgorithm(header.algorithm, exp_algo));
457457
}
458-
if header.kid != verifier.fingerprint() {
459-
return Err(Error::UnexpectedKey(header.kid, verifier.fingerprint()));
458+
if header.kid != verifier.fingerprint().to_bytes() {
459+
return Err(Error::UnexpectedKey(
460+
header.kid,
461+
verifier.fingerprint().to_bytes(),
462+
));
460463
}
461464
Ok(header)
462465
}
@@ -472,8 +475,11 @@ fn verify_enc_protected_header(
472475
if header.algorithm != exp_algo {
473476
return Err(Error::UnexpectedAlgorithm(header.algorithm, exp_algo));
474477
}
475-
if header.kid != recipient.fingerprint() {
476-
return Err(Error::UnexpectedKey(header.kid, recipient.fingerprint()));
478+
if header.kid != recipient.fingerprint().to_bytes() {
479+
return Err(Error::UnexpectedKey(
480+
header.kid,
481+
recipient.fingerprint().to_bytes(),
482+
));
477483
}
478484
Ok(header)
479485
}

src/eddsa/mod.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ pub const PUBLIC_KEY_SIZE: usize = 32;
3232
/// Size of a signature in bytes.
3333
pub const SIGNATURE_SIZE: usize = 64;
3434

35+
/// Size of a fingerprint in bytes.
36+
pub const FINGERPRINT_SIZE: usize = 32;
37+
3538
/// SecretKey contains an Ed25519 private key usable for signing.
3639
#[derive(Clone)]
3740
pub struct SecretKey {
@@ -110,7 +113,7 @@ impl SecretKey {
110113

111114
/// fingerprint returns a 256bit unique identified for this key. For HPKE,
112115
/// that is the SHA256 hash of the raw public key.
113-
pub fn fingerprint(&self) -> [u8; 32] {
116+
pub fn fingerprint(&self) -> Fingerprint {
114117
self.public_key().fingerprint()
115118
}
116119

@@ -165,10 +168,10 @@ impl PublicKey {
165168

166169
/// fingerprint returns a 256bit unique identified for this key. For Ed25519,
167170
/// that is the SHA256 hash of the raw public key.
168-
pub fn fingerprint(&self) -> [u8; 32] {
171+
pub fn fingerprint(&self) -> Fingerprint {
169172
let mut hasher = sha2::Sha256::new();
170173
hasher.update(self.to_bytes());
171-
hasher.finalize().into()
174+
Fingerprint(hasher.finalize().into())
172175
}
173176

174177
/// verify verifies a digital signature.
@@ -194,6 +197,22 @@ impl Signature {
194197
}
195198
}
196199

200+
/// Fingerprint contains an Ed25519 key fingerprint.
201+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
202+
pub struct Fingerprint([u8; FINGERPRINT_SIZE]);
203+
204+
impl Fingerprint {
205+
/// from_bytes converts a 32-byte array into a fingerprint.
206+
pub fn from_bytes(bytes: &[u8; FINGERPRINT_SIZE]) -> Self {
207+
Self(*bytes)
208+
}
209+
210+
/// to_bytes converts a fingerprint into a 32-byte array.
211+
pub fn to_bytes(&self) -> [u8; FINGERPRINT_SIZE] {
212+
self.0
213+
}
214+
}
215+
197216
#[cfg(test)]
198217
mod tests {
199218
use super::*;

src/mldsa/mod.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ pub const PUBLIC_KEY_SIZE: usize = 1952;
3434
/// Size of a signature in bytes.
3535
pub const SIGNATURE_SIZE: usize = 3309;
3636

37+
/// Size of a fingerprint in bytes.
38+
pub const FINGERPRINT_SIZE: usize = 32;
39+
3740
/// ML-DSA-65 private key inner structure.
3841
#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
3942
struct MlDsa65PrivateKeyInner {
@@ -159,7 +162,7 @@ impl SecretKey {
159162

160163
/// fingerprint returns a 256bit unique identified for this key. For ML-DSA,
161164
/// that is the SHA256 hash of the raw public key.
162-
pub fn fingerprint(&self) -> [u8; 32] {
165+
pub fn fingerprint(&self) -> Fingerprint {
163166
self.public_key().fingerprint()
164167
}
165168

@@ -244,10 +247,10 @@ impl PublicKey {
244247

245248
/// fingerprint returns a 256bit unique identified for this key. For ML-DSA,
246249
/// that is the SHA256 hash of the raw public key.
247-
pub fn fingerprint(&self) -> [u8; 32] {
250+
pub fn fingerprint(&self) -> Fingerprint {
248251
let mut hasher = sha2::Sha256::new();
249252
hasher.update(self.inner.encode().as_slice());
250-
hasher.finalize().into()
253+
Fingerprint(hasher.finalize().into())
251254
}
252255

253256
/// verify verifies a digital signature with an optional context string.
@@ -282,6 +285,22 @@ impl Signature {
282285
}
283286
}
284287

288+
/// Fingerprint contains a 32-byte unique identifier for an ML-DSA-65 key.
289+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
290+
pub struct Fingerprint([u8; FINGERPRINT_SIZE]);
291+
292+
impl Fingerprint {
293+
/// from_bytes converts a 32-byte array into a fingerprint.
294+
pub fn from_bytes(bytes: &[u8; FINGERPRINT_SIZE]) -> Self {
295+
Self(*bytes)
296+
}
297+
298+
/// to_bytes converts a fingerprint into a 32-byte array.
299+
pub fn to_bytes(&self) -> [u8; FINGERPRINT_SIZE] {
300+
self.0
301+
}
302+
}
303+
285304
#[cfg(test)]
286305
mod tests {
287306
use super::*;

src/rsa/mod.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ pub const PUBLIC_KEY_SIZE: usize = 264;
2828
/// Size of an RSA-2048 signature.
2929
pub const SIGNATURE_SIZE: usize = 256;
3030

31+
/// Size of an RSA key fingerprint (SHA256 hash).
32+
pub const FINGERPRINT_SIZE: usize = 32;
33+
3134
/// SecretKey contains a 2048-bit RSA private key usable for signing, with SHA256
3235
/// as the underlying hash algorithm. Whilst RSA could also be used for encryption,
3336
/// that is not exposed on the API as it's not required by the project.
@@ -155,7 +158,7 @@ impl SecretKey {
155158

156159
/// fingerprint returns a 256bit unique identified for this key. For RSA, that
157160
/// is the SHA256 hash of the raw (le modulus || le exponent) public key.
158-
pub fn fingerprint(&self) -> [u8; 32] {
161+
pub fn fingerprint(&self) -> Fingerprint {
159162
self.public_key().fingerprint()
160163
}
161164

@@ -259,7 +262,7 @@ impl PublicKey {
259262

260263
/// fingerprint returns a 256bit unique identified for this key. For RSA, that
261264
/// is the SHA256 hash of the raw (le modulus || le exponent) public key.
262-
pub fn fingerprint(&self) -> [u8; 32] {
265+
pub fn fingerprint(&self) -> Fingerprint {
263266
let pubkey: RsaPublicKey = self.inner.as_ref().clone();
264267

265268
let mut mod_le = pubkey.n().to_bytes_le();
@@ -270,7 +273,7 @@ impl PublicKey {
270273
let mut hasher = Sha256::new();
271274
hasher.update(&mod_le);
272275
hasher.update(&exp_le);
273-
hasher.finalize().into()
276+
Fingerprint(hasher.finalize().into())
274277
}
275278

276279
/// verify verifies a digital signature.
@@ -310,6 +313,22 @@ impl Signature {
310313
}
311314
}
312315

316+
/// Fingerprint contains an RSA key fingerprint (SHA256 hash).
317+
#[derive(Debug, Clone, PartialEq, Eq)]
318+
pub struct Fingerprint([u8; FINGERPRINT_SIZE]);
319+
320+
impl Fingerprint {
321+
/// from_bytes converts a 32-byte array into a fingerprint.
322+
pub fn from_bytes(bytes: &[u8; FINGERPRINT_SIZE]) -> Self {
323+
Self(*bytes)
324+
}
325+
326+
/// to_bytes converts a fingerprint into a 32-byte array.
327+
pub fn to_bytes(&self) -> [u8; FINGERPRINT_SIZE] {
328+
self.0
329+
}
330+
}
331+
313332
#[cfg(test)]
314333
mod tests {
315334
use super::*;
@@ -557,7 +576,7 @@ fQIDAQAB
557576
-----END PUBLIC KEY-----",
558577
)
559578
.unwrap();
560-
assert_eq!(hex::encode(key.fingerprint()), input);
579+
assert_eq!(hex::encode(key.fingerprint().to_bytes()), input);
561580
}
562581

563582
// Tests signing and verifying messages. Note, this test is not meant to test

src/xdsa/mod.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ pub const PUBLIC_KEY_SIZE: usize = 1984;
4040
/// Format: ML-DSA (3309 bytes) || Ed25519 (64 bytes)
4141
pub const SIGNATURE_SIZE: usize = 3373;
4242

43+
/// Size of a key fingerprint in bytes.
44+
pub const FINGERPRINT_SIZE: usize = 32;
45+
4346
/// SecretKey is an ML-DSA-65 private key paired with an Ed25519 private key for
4447
/// creating and verifying quantum resistant digital signatures.
4548
#[derive(Clone)]
@@ -150,7 +153,7 @@ impl SecretKey {
150153
}
151154

152155
/// fingerprint returns a 256bit unique identifier for this key.
153-
pub fn fingerprint(&self) -> [u8; 32] {
156+
pub fn fingerprint(&self) -> Fingerprint {
154157
self.public_key().fingerprint()
155158
}
156159

@@ -273,11 +276,11 @@ impl PublicKey {
273276
}
274277

275278
/// fingerprint returns a 256bit unique identifier for this key.
276-
pub fn fingerprint(&self) -> [u8; 32] {
279+
pub fn fingerprint(&self) -> Fingerprint {
277280
let mut hasher = sha2::Sha256::new();
278281
hasher.update(self.ml_key.to_bytes());
279282
hasher.update(self.ed_key.to_bytes());
280-
hasher.finalize().into()
283+
Fingerprint(hasher.finalize().into())
281284
}
282285

283286
/// verify verifies a digital signature.
@@ -345,6 +348,22 @@ impl Signature {
345348
}
346349
}
347350

351+
/// Fingerprint contains a 256-bit unique identifier for a composite ML-DSA-65-Ed25519-SHA512 key.
352+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
353+
pub struct Fingerprint([u8; FINGERPRINT_SIZE]);
354+
355+
impl Fingerprint {
356+
/// from_bytes creates a fingerprint from a 32-byte array.
357+
pub fn from_bytes(bytes: &[u8; FINGERPRINT_SIZE]) -> Self {
358+
Self(*bytes)
359+
}
360+
361+
/// to_bytes converts a fingerprint into a 32-byte array.
362+
pub fn to_bytes(&self) -> [u8; FINGERPRINT_SIZE] {
363+
self.0
364+
}
365+
}
366+
348367
#[cfg(test)]
349368
mod tests {
350369
use super::*;

src/xhpke/mod.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ pub const PUBLIC_KEY_SIZE: usize = 1216;
5454
/// Size of the encapsulated key in bytes.
5555
pub const ENCAP_KEY_SIZE: usize = 1120;
5656

57+
/// Size of the fingerprint in bytes.
58+
pub const FINGERPRINT_SIZE: usize = 32;
59+
5760
/// SecretKey contains a private key of the type bound to the configured crypto.
5861
#[derive(Clone, PartialEq, Eq)]
5962
pub struct SecretKey {
@@ -136,7 +139,7 @@ impl SecretKey {
136139

137140
/// fingerprint returns a 256bit unique identifier for this key. For HPKE,
138141
/// that is the SHA256 hash of the raw public key.
139-
pub fn fingerprint(&self) -> [u8; 32] {
142+
pub fn fingerprint(&self) -> Fingerprint {
140143
self.public_key().fingerprint()
141144
}
142145

@@ -251,10 +254,10 @@ impl PublicKey {
251254

252255
/// fingerprint returns a 256bit unique identifier for this key. For HPKE,
253256
/// that is the SHA256 hash of the raw public key.
254-
pub fn fingerprint(&self) -> [u8; 32] {
257+
pub fn fingerprint(&self) -> Fingerprint {
255258
let mut hasher = sha2::Sha256::new();
256259
hasher.update(self.to_bytes());
257-
hasher.finalize().into()
260+
Fingerprint(hasher.finalize().into())
258261
}
259262

260263
/// seal creates a standalone cryptographic construct encrypted to this public
@@ -298,6 +301,22 @@ impl PublicKey {
298301
}
299302
}
300303

304+
/// Fingerprint contains a 256-bit unique identifier for an HPKE key.
305+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
306+
pub struct Fingerprint([u8; FINGERPRINT_SIZE]);
307+
308+
impl Fingerprint {
309+
/// from_bytes converts a 32-byte array into a fingerprint.
310+
pub fn from_bytes(bytes: &[u8; FINGERPRINT_SIZE]) -> Self {
311+
Self(*bytes)
312+
}
313+
314+
/// to_bytes converts a fingerprint into a 32-byte array.
315+
pub fn to_bytes(&self) -> [u8; FINGERPRINT_SIZE] {
316+
self.0
317+
}
318+
}
319+
301320
/// Validates an ML-KEM-768 encapsulation key by checking that all polynomial
302321
/// coefficients are in the valid range [0, 3329).
303322
///

0 commit comments

Comments
 (0)