1use crate::aux_functions::{byte_decode, byte_encode, expandA};
2use crate::matrix::{Matrix, Vector};
3use crate::mlkem::{H, POLY_BYTES, q};
4use crate::mlkem::{MLKEM512_PK_LEN, MLKEM512_SK_LEN, MLKEM512_k};
5use crate::mlkem::{MLKEM768_PK_LEN, MLKEM768_SK_LEN, MLKEM768_k};
6use crate::mlkem::{MLKEM1024_PK_LEN, MLKEM1024_SK_LEN, MLKEM1024_k};
7use crate::{ML_KEM_512_NAME, ML_KEM_768_NAME, ML_KEM_1024_NAME};
8use bouncycastle_core::errors::KEMError;
9use bouncycastle_core::key_material;
10use bouncycastle_core::key_material::{KeyMaterial, KeyMaterialTrait, KeyType};
11use bouncycastle_core::traits::{Hash, KEMPrivateKey, KEMPublicKey, SecurityStrength};
12use bouncycastle_sha3::SHA3_256;
13use bouncycastle_utils::secret::Secret;
14use core::fmt;
15use core::fmt::{Debug, Display, Formatter};
16
17#[allow(unused_imports)]
19use crate::mlkem::MLKEMTrait;
20#[allow(unused_imports)]
21use crate::polynomial::Polynomial;
22
23pub type MLKEM512PublicKey = MLKEMPublicKey<MLKEM512_k, MLKEM512_PK_LEN>;
27pub type MLKEM512PrivateKey =
29 MLKEMPrivateKey<MLKEM512_k, MLKEM512PublicKey, MLKEM512_SK_LEN, MLKEM512_PK_LEN>;
30pub type MLKEM768PublicKey = MLKEMPublicKey<MLKEM768_k, MLKEM768_PK_LEN>;
32pub type MLKEM768PrivateKey =
34 MLKEMPrivateKey<MLKEM768_k, MLKEM768PublicKey, MLKEM768_SK_LEN, MLKEM768_PK_LEN>;
35pub type MLKEM1024PublicKey = MLKEMPublicKey<MLKEM1024_k, MLKEM1024_PK_LEN>;
37pub type MLKEM1024PrivateKey =
39 MLKEMPrivateKey<MLKEM1024_k, MLKEM1024PublicKey, MLKEM1024_SK_LEN, MLKEM1024_PK_LEN>;
40
41pub type MLKEM512PublicKeyExpanded =
45 MLKEMPublicKeyExpanded<MLKEM512_k, MLKEM512PublicKey, MLKEM512_PK_LEN>;
46pub type MLKEM512PrivateKeyExpanded = MLKEMPrivateKeyExpanded<
48 MLKEM512_k,
49 MLKEM512PublicKey,
50 MLKEM512PrivateKey,
51 MLKEM512_SK_LEN,
52 MLKEM512_PK_LEN,
53>;
54pub type MLKEM768PublicKeyExpanded =
56 MLKEMPublicKeyExpanded<MLKEM768_k, MLKEM768PublicKey, MLKEM768_PK_LEN>;
57pub type MLKEM768PrivateKeyExpanded = MLKEMPrivateKeyExpanded<
59 MLKEM768_k,
60 MLKEM768PublicKey,
61 MLKEM768PrivateKey,
62 MLKEM768_SK_LEN,
63 MLKEM768_PK_LEN,
64>;
65pub type MLKEM1024PublicKeyExpanded =
67 MLKEMPublicKeyExpanded<MLKEM1024_k, MLKEM1024PublicKey, MLKEM1024_PK_LEN>;
68pub type MLKEM1024PrivateKeyExpanded = MLKEMPrivateKeyExpanded<
70 MLKEM1024_k,
71 MLKEM1024PublicKey,
72 MLKEM1024PrivateKey,
73 MLKEM1024_SK_LEN,
74 MLKEM1024_PK_LEN,
75>;
76
77#[derive(Clone)]
79pub struct MLKEMPublicKey<const k: usize, const PK_LEN: usize> {
80 t_hat: Vector<k>,
81 rho: [u8; 32],
82}
83
84pub trait MLKEMPublicKeyTrait<const k: usize, const PK_LEN: usize>: KEMPublicKey<PK_LEN> {
86 fn pk_decode(pk: &[u8; PK_LEN]) -> Result<Self, KEMError>;
91 fn A_hat(&self) -> Matrix<k, k>;
93 fn compute_hash(&self) -> [u8; 32];
95}
96
97pub(crate) trait MLKEMPublicKeyInternalTrait<const k: usize, const PK_LEN: usize>:
98 MLKEMPublicKeyTrait<k, PK_LEN>
99{
100 fn new(t_hat: Vector<k>, rho: [u8; 32]) -> Self;
103
104 fn t_hat(&self) -> &Vector<k>;
106}
107
108impl<const k: usize, const PK_LEN: usize> MLKEMPublicKeyTrait<k, PK_LEN>
109 for MLKEMPublicKey<k, PK_LEN>
110{
111 fn pk_decode(pk: &[u8; PK_LEN]) -> Result<Self, KEMError> {
112 let (pk_chunks, last_chunk) = pk.as_chunks::<POLY_BYTES>();
113
114 debug_assert_eq!(pk_chunks.len(), k);
116 debug_assert_eq!(last_chunk.len(), 32);
117
118 let t_hat = {
119 let mut t_hat = Vector::<k>::new();
120
121 for (t_i, pk_chunk) in t_hat.vec.iter_mut().zip(pk_chunks) {
122 t_i.coeffs.copy_from_slice(&byte_decode::<12, POLY_BYTES>(pk_chunk).coeffs);
123
124 for coeff in t_i.coeffs.iter() {
131 if *coeff < 0 || *coeff >= q {
132 return Err(KEMError::DecodingError("Invalid or corrupted key"));
133 }
134 }
135 }
136
137 t_hat
138 };
139 let rho = last_chunk.try_into().unwrap();
140
141 Ok(Self::new(t_hat, rho))
142 }
143
144 fn A_hat(&self) -> Matrix<k, k> {
145 expandA(&self.rho)
146 }
147
148 fn compute_hash(&self) -> [u8; 32] {
149 let mut out = [0u8; 32];
150 let bytes_written = H::default().hash_out(&self.encode(), &mut out);
151 debug_assert_eq!(bytes_written, 32);
152 out
153 }
154}
155
156impl<const k: usize, const PK_LEN: usize> MLKEMPublicKeyInternalTrait<k, PK_LEN>
157 for MLKEMPublicKey<k, PK_LEN>
158{
159 fn new(t_hat: Vector<k>, rho: [u8; 32]) -> Self {
160 Self { rho, t_hat }
161 }
162
163 fn t_hat(&self) -> &Vector<k> {
164 &self.t_hat
165 }
166}
167
168impl<const k: usize, const PK_LEN: usize> KEMPublicKey<PK_LEN> for MLKEMPublicKey<k, PK_LEN> {
169 fn encode(&self) -> [u8; PK_LEN] {
172 let mut pk = [0u8; PK_LEN];
173 self.encode_out(&mut pk);
174
175 pk
176 }
177 fn encode_out(&self, out: &mut [u8; PK_LEN]) -> usize {
180 debug_assert_eq!(PK_LEN, 12 * k * 32 + 32);
181 debug_assert_eq!(POLY_BYTES, 12 * 32);
182
183 out.fill(0);
184
185 let (pk_chunks, last_chunk) = out.as_chunks_mut::<POLY_BYTES>();
186
187 debug_assert_eq!(pk_chunks.len(), k);
189 debug_assert_eq!(last_chunk.len(), 32);
190
191 for (pk_chunk, t_i) in pk_chunks.into_iter().zip(&self.t_hat.vec) {
192 pk_chunk.copy_from_slice(&byte_encode::<12, POLY_BYTES>(t_i));
193 }
194 last_chunk.copy_from_slice(&self.rho);
195
196 PK_LEN
197 }
198
199 fn from_bytes(bytes: &[u8]) -> Result<Self, KEMError> {
200 if bytes.len() != PK_LEN {
201 return Err(KEMError::DecodingError("Provided key bytes are the incorrect length"));
202 }
203 let bytes_sized: [u8; PK_LEN] = bytes[..PK_LEN].try_into().unwrap();
204 Self::pk_decode(&bytes_sized)
205 }
206}
207
208impl<const k: usize, const PK_LEN: usize> Eq for MLKEMPublicKey<k, PK_LEN> {}
209
210impl<const k: usize, const PK_LEN: usize> PartialEq for MLKEMPublicKey<k, PK_LEN> {
211 fn eq(&self, other: &Self) -> bool {
212 bouncycastle_utils::ct::ct_eq_bytes(&self.encode(), &other.encode())
213 }
214}
215
216impl<const k: usize, const PK_LEN: usize> Debug for MLKEMPublicKey<k, PK_LEN> {
217 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
218 let alg = match k {
219 2 => ML_KEM_512_NAME,
220 3 => ML_KEM_768_NAME,
221 4 => ML_KEM_1024_NAME,
222 _ => panic!("Unsupported key length"),
223 };
224 let hash = SHA3_256::new().hash(&self.encode());
225 write!(f, "MLKEMPublicKey {{ alg: {}, pub_key_hash: {:x?} }}", alg, hash)
226 }
227}
228
229impl<const k: usize, const PK_LEN: usize> Display for MLKEMPublicKey<k, PK_LEN> {
230 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
231 let alg = match k {
232 2 => ML_KEM_512_NAME,
233 3 => ML_KEM_768_NAME,
234 4 => ML_KEM_1024_NAME,
235 _ => panic!("Unsupported key length"),
236 };
237 let hash = SHA3_256::new().hash(&self.encode());
238 write!(f, "MLKEMPublicKey {{ alg: {}, pub_key_hash: {:x?} }}", alg, hash)
239 }
240}
241
242#[derive(Clone)]
246pub struct MLKEMPublicKeyExpanded<
247 const k: usize,
248 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
249 const PK_LEN: usize,
250> {
251 pub(crate) ek: PK,
252 pub(crate) A_hat: Matrix<k, k>,
253}
254
255impl<const k: usize, PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>, const PK_LEN: usize>
256 MLKEMPublicKeyInternalTrait<k, PK_LEN> for MLKEMPublicKeyExpanded<k, PK, PK_LEN>
257{
258 fn new(t_hat: Vector<k>, rho: [u8; 32]) -> Self {
259 let ek = PK::new(t_hat, rho);
260 let A_hat = ek.A_hat();
261
262 Self { ek, A_hat }
263 }
264
265 fn t_hat(&self) -> &Vector<k> {
266 self.ek.t_hat()
267 }
268}
269
270impl<const k: usize, PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>, const PK_LEN: usize>
271 KEMPublicKey<PK_LEN> for MLKEMPublicKeyExpanded<k, PK, PK_LEN>
272{
273 fn encode(&self) -> [u8; PK_LEN] {
274 let mut pk = [0u8; PK_LEN];
275 self.encode_out(&mut pk);
276
277 pk
278 }
279
280 fn encode_out(&self, out: &mut [u8; PK_LEN]) -> usize {
281 out.fill(0);
282
283 self.ek.encode_out(out)
284 }
285
286 fn from_bytes(bytes: &[u8]) -> Result<Self, KEMError> {
287 if bytes.len() != PK_LEN {
288 return Err(KEMError::DecodingError("Provided key bytes are the incorrect length"));
289 }
290 let bytes_sized: [u8; PK_LEN] = bytes[..PK_LEN].try_into().unwrap();
291 Self::pk_decode(&bytes_sized)
292 }
293}
294
295impl<const k: usize, PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>, const PK_LEN: usize> PartialEq
296 for MLKEMPublicKeyExpanded<k, PK, PK_LEN>
297{
298 fn eq(&self, other: &Self) -> bool {
299 self.encode() == other.encode()
300 }
301}
302
303impl<const k: usize, PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>, const PK_LEN: usize> Eq
304 for MLKEMPublicKeyExpanded<k, PK, PK_LEN>
305{
306}
307
308impl<const k: usize, PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>, const PK_LEN: usize> Debug
309 for MLKEMPublicKeyExpanded<k, PK, PK_LEN>
310{
311 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
312 let alg = match k {
313 2 => ML_KEM_512_NAME,
314 3 => ML_KEM_768_NAME,
315 4 => ML_KEM_1024_NAME,
316 _ => panic!("Unsupported key length"),
317 };
318 let hash = SHA3_256::new().hash(&self.encode());
319 write!(f, "MLKEMPublicKeyExpanded {{ alg: {}, pub_key_hash: {:x?} }}", alg, hash)
320 }
321}
322
323impl<const k: usize, PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>, const PK_LEN: usize> Display
324 for MLKEMPublicKeyExpanded<k, PK, PK_LEN>
325{
326 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
327 let alg = match k {
328 2 => ML_KEM_512_NAME,
329 3 => ML_KEM_768_NAME,
330 4 => ML_KEM_1024_NAME,
331 _ => panic!("Unsupported key length"),
332 };
333 let hash = SHA3_256::new().hash(&self.encode());
334 write!(f, "MLKEMPublicKeyExpanded {{ alg: {}, pub_key_hash: {:x?} }}", alg, hash)
335 }
336}
337
338impl<const k: usize, PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>, const PK_LEN: usize>
339 MLKEMPublicKeyTrait<k, PK_LEN> for MLKEMPublicKeyExpanded<k, PK, PK_LEN>
340{
341 fn pk_decode(pk: &[u8; PK_LEN]) -> Result<Self, KEMError> {
342 let ek = PK::pk_decode(pk)?;
343 let A_hat = ek.A_hat();
344 Ok(Self { ek, A_hat })
345 }
346
347 fn A_hat(&self) -> Matrix<k, k> {
348 self.A_hat.clone()
349 }
350
351 fn compute_hash(&self) -> [u8; 32] {
352 self.ek.compute_hash()
353 }
354}
355
356impl<const k: usize, PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>, const PK_LEN: usize> From<&PK>
357 for MLKEMPublicKeyExpanded<k, PK, PK_LEN>
358{
359 fn from(ek: &PK) -> Self {
362 let A_hat = ek.A_hat();
363
364 Self { ek: ek.clone(), A_hat }
365 }
366}
367
368#[derive(Clone)]
372pub struct MLKEMPrivateKey<
373 const k: usize,
374 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
375 const SK_LEN: usize,
376 const PK_LEN: usize,
377> {
378 s_hat: Secret<Vector<k>>,
379 ek: PK,
380 pk_hash: [u8; 32],
381 z: Secret<[u8; 32]>,
382 seed_d: Option<Secret<[u8; 32]>>,
383}
384
385impl<
386 const k: usize,
387 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
388 const SK_LEN: usize,
389 const PK_LEN: usize,
390> MLKEMPrivateKey<k, PK, SK_LEN, PK_LEN>
391{
392 fn sk_encode_out(&self, out: &mut [u8; SK_LEN]) -> usize {
395 out.fill(0);
396
397 debug_assert_eq!(SK_LEN, 12*k*32 + PK_LEN + 32 + 32);
398
399 let mut pos = 0usize;
400
401 for i in 0..k {
404 out[i * POLY_BYTES..(i + 1) * POLY_BYTES]
405 .copy_from_slice(&byte_encode::<12, POLY_BYTES>(&self.s_hat[i]));
406 }
407 pos += k * POLY_BYTES;
408
409 debug_assert_eq!(self.ek.encode().len(), PK_LEN);
412 out[pos..pos + PK_LEN].copy_from_slice(&self.ek.encode());
413 pos += PK_LEN;
414
415 out[pos..pos + 32].copy_from_slice(&self.pk_hash);
417 pos += 32;
418
419 out[pos..pos + 32].copy_from_slice(&*self.z);
421
422 debug_assert_eq!(pos + 32, SK_LEN);
423 SK_LEN
424 }
425}
426
427pub trait MLKEMPrivateKeyTrait<
429 const k: usize,
430 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
431 const SK_LEN: usize,
432 const PK_LEN: usize,
433>: KEMPrivateKey<SK_LEN>
434{
435 fn seed(&self) -> Option<KeyMaterial<64>>;
437
438 fn pk(&self) -> &PK;
440 fn pk_hash(&self) -> &[u8; 32];
442 fn sk_decode(sk: &[u8; SK_LEN]) -> Result<Self, KEMError>;
444}
445
446pub(crate) trait MLKEMPrivateKeyInternalTrait<
447 const k: usize,
448 PK: MLKEMPublicKeyTrait<k, PK_LEN>,
449 const SK_LEN: usize,
450 const PK_LEN: usize,
451>
452{
453 fn new(
456 s_hat: Secret<Vector<k>>,
457 ek: PK,
458 h: [u8; 32],
459 z: Secret<[u8; 32]>,
460 seed_d: Option<Secret<[u8; 32]>>,
461 ) -> Self;
462
463 fn s_hat(&self) -> &Vector<k>;
465
466 fn z(&self) -> &Secret<[u8; 32]>;
467}
468
469impl<
470 const k: usize,
471 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
472 const SK_LEN: usize,
473 const PK_LEN: usize,
474> MLKEMPrivateKeyTrait<k, PK, SK_LEN, PK_LEN> for MLKEMPrivateKey<k, PK, SK_LEN, PK_LEN>
475{
476 fn seed(&self) -> Option<KeyMaterial<64>> {
477 if self.seed_d.is_none() {
478 None
479 } else {
480 let mut tmp = Secret::<[u8; 64]>::new();
481 tmp[..32].copy_from_slice(&self.seed_d.clone().unwrap().as_ref());
482 tmp[32..].copy_from_slice(&*self.z);
483 let mut seed = KeyMaterial::<64>::from_bytes_as_type(&*tmp, KeyType::Seed).unwrap();
484
485 key_material::do_hazardous_operations(&mut seed, |seed| {
486 seed.set_security_strength(match k {
487 2 => SecurityStrength::_128bit,
488 3 => SecurityStrength::_192bit,
489 4 => SecurityStrength::_256bit,
490 _ => unreachable!("Invalid mlkem param set"),
491 })
492 })
493 .unwrap();
494
495 Some(seed)
496 }
497 }
498
499 fn pk(&self) -> &PK {
500 &self.ek
501 }
502
503 fn pk_hash(&self) -> &[u8; 32] {
504 &self.pk_hash
505 }
506
507 fn sk_decode(sk: &[u8; SK_LEN]) -> Result<Self, KEMError> {
508 debug_assert_eq!(SK_LEN, 12*k*32 + PK_LEN + 32 + 32);
509
510 let mut pos = 0usize;
511
512 let mut s_hat: Secret<Vector<k>> = Secret::new();
514 for i in 0..k {
516 s_hat[i] = byte_decode::<12, POLY_BYTES>(
517 sk[i * POLY_BYTES..(i + 1) * POLY_BYTES].try_into().unwrap(),
518 );
519
520 for coeff in s_hat[i].coeffs.iter() {
527 if *coeff < 0 || *coeff >= q {
528 return Err(KEMError::DecodingError("Invalid or corrupted key"));
529 }
530 }
531 }
532 pos += k * POLY_BYTES;
533
534 let ek = PK::pk_decode(sk[pos..pos + PK_LEN].try_into().unwrap())?;
536 pos += PK_LEN;
537
538 let h_pk: [u8; 32] = sk[pos..pos + 32].try_into().unwrap();
540 pos += 32;
541
542 if h_pk != ek.compute_hash() {
546 return Err(KEMError::ConsistencyCheckFailed(
547 "Corrupted private key: computed hash of ek != h_ek stored in private key",
548 ));
549 }
550
551 let mut z = Secret::<[u8; 32]>::new();
553 z.copy_from_slice(sk[pos..pos + 32].try_into().unwrap());
554
555 Ok(Self::new(s_hat, ek, h_pk, z, None))
556 }
557}
558
559impl<
560 const k: usize,
561 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
562 const SK_LEN: usize,
563 const PK_LEN: usize,
564> MLKEMPrivateKeyInternalTrait<k, PK, SK_LEN, PK_LEN> for MLKEMPrivateKey<k, PK, SK_LEN, PK_LEN>
565{
566 fn new(
568 s_hat: Secret<Vector<k>>,
569 ek: PK,
570 pk_hash: [u8; 32],
571 z: Secret<[u8; 32]>,
572 seed_d: Option<Secret<[u8; 32]>>,
573 ) -> Self {
574 Self { s_hat, ek, pk_hash, z, seed_d: seed_d.clone() }
575 }
576
577 fn s_hat(&self) -> &Vector<k> {
578 &self.s_hat
579 }
580
581 fn z(&self) -> &Secret<[u8; 32]> {
582 &self.z
583 }
584}
585
586impl<
587 const k: usize,
588 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
589 const SK_LEN: usize,
590 const PK_LEN: usize,
591> KEMPrivateKey<SK_LEN> for MLKEMPrivateKey<k, PK, SK_LEN, PK_LEN>
592{
593 fn encode(&self) -> [u8; SK_LEN] {
594 let mut out = [0u8; SK_LEN];
595 self.encode_out(&mut out);
596
597 out
598 }
599
600 fn encode_out(&self, out: &mut [u8; SK_LEN]) -> usize {
601 out.fill(0);
602
603 self.sk_encode_out(out)
604 }
605
606 fn from_bytes(bytes: &[u8]) -> Result<Self, KEMError> {
607 if bytes.len() != SK_LEN {
608 return Err(KEMError::DecodingError("Provided key bytes are the incorrect length"));
609 }
610 if bytes.len() != SK_LEN {
611 return Err(KEMError::DecodingError("Provided key bytes are the incorrect length"));
612 }
613 let bytes_sized: [u8; SK_LEN] = bytes[..SK_LEN].try_into().unwrap();
614
615 Self::sk_decode(&bytes_sized)
616 }
617}
618
619impl<
620 const k: usize,
621 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
622 const SK_LEN: usize,
623 const PK_LEN: usize,
624> Eq for MLKEMPrivateKey<k, PK, SK_LEN, PK_LEN>
625{
626}
627
628impl<
629 const k: usize,
630 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
631 const SK_LEN: usize,
632 const PK_LEN: usize,
633> PartialEq for MLKEMPrivateKey<k, PK, SK_LEN, PK_LEN>
634{
635 fn eq(&self, other: &Self) -> bool {
636 let self_encoded = self.encode();
637 let other_encoded = other.encode();
638 bouncycastle_utils::ct::ct_eq_bytes(self_encoded.as_ref(), other_encoded.as_ref())
639 }
640}
641
642impl<
644 const k: usize,
645 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
646 const SK_LEN: usize,
647 const PK_LEN: usize,
648> fmt::Debug for MLKEMPrivateKey<k, PK, SK_LEN, PK_LEN>
649{
650 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
651 let alg = match k {
652 2 => ML_KEM_512_NAME,
653 3 => ML_KEM_768_NAME,
654 4 => ML_KEM_1024_NAME,
655 _ => panic!("Unsupported key length"),
656 };
657 write!(
658 f,
659 "MLKEMPrivateKey {{ alg: {}, pub_key_hash: {:x?}, has_seed: {} }}",
660 alg,
661 self.pk_hash,
662 self.seed_d.is_some(),
663 )
664 }
665}
666
667impl<
669 const k: usize,
670 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
671 const SK_LEN: usize,
672 const PK_LEN: usize,
673> Display for MLKEMPrivateKey<k, PK, SK_LEN, PK_LEN>
674{
675 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
676 let alg = match k {
677 2 => ML_KEM_512_NAME,
678 3 => ML_KEM_768_NAME,
679 4 => ML_KEM_1024_NAME,
680 _ => panic!("Unsupported key length"),
681 };
682 write!(
683 f,
684 "MLKEMPrivateKey {{ alg: {}, pub_key_hash: {:x?}, has_seed: {} }}",
685 alg,
686 self.pk_hash,
687 self.seed_d.is_some(),
688 )
689 }
690}
691
692#[derive(Clone)]
696pub struct MLKEMPrivateKeyExpanded<
697 const k: usize,
698 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
699 SK: MLKEMPrivateKeyTrait<k, PK, SK_LEN, PK_LEN>
700 + MLKEMPrivateKeyInternalTrait<k, PK, SK_LEN, PK_LEN>,
701 const SK_LEN: usize,
702 const PK_LEN: usize,
703> {
704 _phantom: core::marker::PhantomData<PK>,
705 pub(crate) dk: SK,
706 pub(crate) A_hat: Matrix<k, k>,
707}
708
709impl<
710 const k: usize,
711 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
712 SK: MLKEMPrivateKeyTrait<k, PK, SK_LEN, PK_LEN>
713 + MLKEMPrivateKeyInternalTrait<k, PK, SK_LEN, PK_LEN>,
714 const SK_LEN: usize,
715 const PK_LEN: usize,
716> From<&SK> for MLKEMPrivateKeyExpanded<k, PK, SK, SK_LEN, PK_LEN>
717{
718 fn from(dk: &SK) -> Self {
721 let A_hat = dk.pk().A_hat();
722
723 Self { _phantom: core::marker::PhantomData, dk: dk.clone(), A_hat }
724 }
725}
726
727impl<
728 const k: usize,
729 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
730 SK: MLKEMPrivateKeyTrait<k, PK, SK_LEN, PK_LEN>
731 + MLKEMPrivateKeyInternalTrait<k, PK, SK_LEN, PK_LEN>,
732 const SK_LEN: usize,
733 const PK_LEN: usize,
734> KEMPrivateKey<SK_LEN> for MLKEMPrivateKeyExpanded<k, PK, SK, SK_LEN, PK_LEN>
735{
736 fn encode(&self) -> [u8; SK_LEN] {
737 self.dk.encode()
738 }
739
740 fn encode_out(&self, out: &mut [u8; SK_LEN]) -> usize {
741 out.fill(0);
742
743 self.dk.encode_out(out)
744 }
745
746 fn from_bytes(bytes: &[u8]) -> Result<Self, KEMError> {
747 Ok(Self::from(&SK::from_bytes(bytes)?))
748 }
749}
750
751impl<
752 const k: usize,
753 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
754 SK: MLKEMPrivateKeyTrait<k, PK, SK_LEN, PK_LEN>
755 + MLKEMPrivateKeyInternalTrait<k, PK, SK_LEN, PK_LEN>,
756 const SK_LEN: usize,
757 const PK_LEN: usize,
758> PartialEq for MLKEMPrivateKeyExpanded<k, PK, SK, SK_LEN, PK_LEN>
759{
760 fn eq(&self, other: &Self) -> bool {
761 self.dk.eq(&other.dk)
762 }
763}
764
765impl<
766 const k: usize,
767 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
768 SK: MLKEMPrivateKeyTrait<k, PK, SK_LEN, PK_LEN>
769 + MLKEMPrivateKeyInternalTrait<k, PK, SK_LEN, PK_LEN>,
770 const SK_LEN: usize,
771 const PK_LEN: usize,
772> Eq for MLKEMPrivateKeyExpanded<k, PK, SK, SK_LEN, PK_LEN>
773{
774}
775
776impl<
777 const k: usize,
778 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
779 SK: MLKEMPrivateKeyTrait<k, PK, SK_LEN, PK_LEN>
780 + MLKEMPrivateKeyInternalTrait<k, PK, SK_LEN, PK_LEN>,
781 const SK_LEN: usize,
782 const PK_LEN: usize,
783> Debug for MLKEMPrivateKeyExpanded<k, PK, SK, SK_LEN, PK_LEN>
784{
785 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
786 let alg = match k {
787 2 => ML_KEM_512_NAME,
788 3 => ML_KEM_768_NAME,
789 4 => ML_KEM_1024_NAME,
790 _ => panic!("Unsupported key length"),
791 };
792 write!(
793 f,
794 "MLKEMPrivateKeyExpanded {{ alg: {}, pub_key_hash: {:x?}, has_seed: {} }}",
795 alg,
796 self.dk.pk().compute_hash(),
797 self.dk.seed().is_some(),
798 )
799 }
800}
801
802impl<
803 const k: usize,
804 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
805 SK: MLKEMPrivateKeyTrait<k, PK, SK_LEN, PK_LEN>
806 + MLKEMPrivateKeyInternalTrait<k, PK, SK_LEN, PK_LEN>,
807 const SK_LEN: usize,
808 const PK_LEN: usize,
809> Display for MLKEMPrivateKeyExpanded<k, PK, SK, SK_LEN, PK_LEN>
810{
811 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
812 let alg = match k {
813 2 => ML_KEM_512_NAME,
814 3 => ML_KEM_768_NAME,
815 4 => ML_KEM_1024_NAME,
816 _ => panic!("Unsupported key length"),
817 };
818 write!(
819 f,
820 "MLKEMPrivateKeyExpanded {{ alg: {}, pub_key_hash: {:x?}, has_seed: {} }}",
821 alg,
822 self.dk.pk().compute_hash(),
823 self.dk.seed().is_some(),
824 )
825 }
826}
827
828impl<
829 const k: usize,
830 PK: MLKEMPublicKeyInternalTrait<k, PK_LEN>,
831 SK: MLKEMPrivateKeyTrait<k, PK, SK_LEN, PK_LEN>
832 + MLKEMPrivateKeyInternalTrait<k, PK, SK_LEN, PK_LEN>,
833 const SK_LEN: usize,
834 const PK_LEN: usize,
835> MLKEMPrivateKeyTrait<k, PK, SK_LEN, PK_LEN>
836 for MLKEMPrivateKeyExpanded<k, PK, SK, SK_LEN, PK_LEN>
837{
838 fn seed(&self) -> Option<KeyMaterial<64>> {
839 self.dk.seed()
840 }
841
842 fn pk(&self) -> &PK {
843 self.dk.pk()
844 }
845
846 fn pk_hash(&self) -> &[u8; 32] {
847 &self.dk.pk_hash()
848 }
849
850 fn sk_decode(sk: &[u8; SK_LEN]) -> Result<Self, KEMError> {
851 let dk = SK::sk_decode(sk)?;
852 let A_hat = dk.pk().A_hat();
853
854 Ok(Self { _phantom: core::marker::PhantomData, dk: dk.clone(), A_hat })
855 }
856}