1use core::hash::{Hash, Hasher};
2use num_integer::Integer;
3use num_traits::{FromPrimitive, One, ToPrimitive};
4use rand_core::CryptoRngCore;
5use zeroize::{Zeroize, ZeroizeOnDrop};
6#[cfg(feature = "serde")]
7use {
8 serdect::serde::{de, ser, Deserialize, Serialize},
9};
10
11
12use crate::traits::{modular::MontyParams, UnsignedModularInt, modular::MontyForm};
13
14use crate::algorithms::rsa::{
15 compute_modulus, compute_private_exponent_carmicheal, compute_private_exponent_euler_totient,
16 recover_primes,
17};
18
19use crate::dummy_rng::DummyRng;
20use crate::errors::{Error, Result};
21use crate::traits::keys::{CrtValue, PrivateKeyParts, PublicKeyParts};
22use crate::traits::{PaddingScheme, SignatureScheme};
23
24#[derive(Debug, Clone)]
26pub struct RsaPublicKey<T>
27where
28 T: UnsignedModularInt,
29{
30 n: T,
32 e: T,
37
38 n_params: MontyParams<T>,
39}
40
41impl<T: UnsignedModularInt> Eq for RsaPublicKey<T> {}
42
43impl<T: UnsignedModularInt> PartialEq for RsaPublicKey<T> {
44 #[inline]
45 fn eq(&self, other: &RsaPublicKey<T>) -> bool {
46 self.n == other.n && self.e == other.e
47 }
48}
49
50impl<T: UnsignedModularInt> Hash for RsaPublicKey<T> {
51 fn hash<H: Hasher>(&self, state: &mut H) {
52 state.write(b"RsaPublicKey");
54 todo!()
55 }
56}
57
58#[derive(Debug, Clone)]
60pub struct RsaPrivateKey<T>
61where
62 T: UnsignedModularInt,
63{
64 pubkey_components: RsaPublicKey<T>,
66 pub(crate) d: T,
68 pub(crate) primes: [T; 4],
70 pub(crate) precomputed: Option<PrecomputedValues<T>>,
72}
73
74impl<T: UnsignedModularInt> Eq for RsaPrivateKey<T> {}
75impl<T: UnsignedModularInt> PartialEq for RsaPrivateKey<T> {
76 #[inline]
77 fn eq(&self, other: &Self) -> bool {
78 self.pubkey_components == other.pubkey_components
79 && self.d == other.d
80 && self.primes == other.primes
81 }
82}
83
84impl<T: UnsignedModularInt> AsRef<RsaPublicKey<T>> for RsaPrivateKey<T> {
85 fn as_ref(&self) -> &RsaPublicKey<T> {
86 &self.pubkey_components
87 }
88}
89
90impl<T: UnsignedModularInt> Hash for RsaPrivateKey<T> {
91 fn hash<H: Hasher>(&self, state: &mut H) {
92 state.write(b"RsaPrivateKey");
94 Hash::hash(&self.pubkey_components, state);
95 }
96}
97
98impl<T: UnsignedModularInt> Drop for RsaPrivateKey<T> {
99 fn drop(&mut self) {
100 self.d.zeroize();
101 self.primes.zeroize();
102 self.precomputed.zeroize();
103 }
104}
105
106impl<T: UnsignedModularInt> ZeroizeOnDrop for RsaPrivateKey<T> {}
107
108#[derive(Debug, Clone)]
109pub(crate) struct PrecomputedValues<T: Zeroize + UnsignedModularInt> {
110 pub(crate) dp: T,
112 pub(crate) dq: T,
114 pub(crate) qinv: MontyForm<T>,
116
117 pub(crate) p_params: MontyParams<T>,
119 pub(crate) q_params: MontyParams<T>,
121}
122
123impl<T: Zeroize + UnsignedModularInt> ZeroizeOnDrop for PrecomputedValues<T> {}
124
125impl<T: Zeroize + UnsignedModularInt> Zeroize for PrecomputedValues<T> {
126 fn zeroize(&mut self) {
127 self.dp.zeroize();
128 self.dq.zeroize();
129 }
133}
134
135impl<T: UnsignedModularInt> Drop for PrecomputedValues<T> {
136 fn drop(&mut self) {
137 self.zeroize();
138 }
139}
140
141impl<T: UnsignedModularInt> From<RsaPrivateKey<T>> for RsaPublicKey<T> {
142 fn from(private_key: RsaPrivateKey<T>) -> Self {
143 todo!()
144 }
145}
146
147impl<T: UnsignedModularInt> From<&RsaPrivateKey<T>> for RsaPublicKey<T> {
148 fn from(private_key: &RsaPrivateKey<T>) -> Self {
149 let n = PublicKeyParts::n(private_key);
150 let e = PublicKeyParts::e(private_key);
151 let n_params = PublicKeyParts::n_params(private_key);
152 RsaPublicKey {
153 n: n.clone(),
154 e: e.clone(),
155 n_params: n_params.clone(),
156 }
157 }
158}
159
160impl<T: UnsignedModularInt> PublicKeyParts<T> for RsaPublicKey<T> {
161 fn n(&self) -> &T {
162 &self.n
163 }
164
165 fn e(&self) -> &T {
166 &self.e
167 }
168 fn n_params(&self) -> &MontyParams<T> {
169 todo!()
170 }
171}
172
173impl<T: UnsignedModularInt + Clone> RsaPublicKey<T> {
174 pub fn encrypt<R: CryptoRngCore, P: PaddingScheme<T>>(
176 &self,
177 rng: &mut R,
178 padding: P,
179 msg: &[u8],
180 storage: &mut [u8],
181 ) -> Result<()> {
182 padding.encrypt(rng, self, msg, storage).map(|_| ())
183 }
184
185 pub fn verify<S: SignatureScheme<T>>(
192 &self,
193 scheme: S,
194 hashed: &[u8],
195 sig: &[u8],
196 ) -> Result<()> {
197 scheme.verify(self, hashed, sig)
198 }
199}
200
201impl<T: UnsignedModularInt> RsaPublicKey<T> {
202 pub const MIN_PUB_EXPONENT: u64 = 2;
204
205 pub const MAX_PUB_EXPONENT: u64 = (1 << 33) - 1;
207
208 pub const MAX_SIZE: usize = 4096;
210
211 pub fn new(n: T, e: T) -> Result<Self> {
216 Self::new_with_max_size(n, e, Self::MAX_SIZE)
217 }
218
219 pub fn new_with_max_size(n: T, e: T, max_size: usize) -> Result<Self> {
221 check_public_with_max_size(&n, &e, max_size)?;
222
223 let n_odd = n.clone();
224 let n_params = MontyParams::new(n_odd);
225
226 Ok(Self { n, e, n_params })
227 }
228
229 pub fn new_unchecked(n: T, e: T) -> Self {
236 todo!()
237 }
238}
239
240impl<T: UnsignedModularInt> PublicKeyParts<T> for RsaPrivateKey<T> {
241 fn n(&self) -> &T {
242 &self.pubkey_components.n
243 }
244
245 fn e(&self) -> &T {
246 &self.pubkey_components.e
247 }
248
249 fn n_params(&self) -> &MontyParams<T> {
250 todo!()
251 }
252}
253
254impl<T: UnsignedModularInt> RsaPrivateKey<T> {
255 const EXP: u64 = 65537;
257
258 pub fn new<R: CryptoRngCore>(rng: &mut R, bit_size: usize) -> Result<RsaPrivateKey<T>> {
260 todo!()
261 }
262
263 pub fn new_with_exp<R: CryptoRngCore>(
268 rng: &mut R,
269 bit_size: usize,
270 exp: T,
271 ) -> Result<RsaPrivateKey<T>> {
272 todo!()
273 }
274
275 pub fn from_components(n: T, e: T, d: T, mut primes: [T; 4]) -> Result<Self> {
289 todo!("")
290 }
291
292 pub fn from_p_q(p: T, q: T, public_exponent: T) -> Result<Self> {
299 if p == q {
300 return Err(Error::InvalidPrime);
301 }
302 todo!()
303 }
304
305 pub fn from_primes(primes: [T; 4], public_exponent: T) -> Result<Self> {
309 if primes.len() < 2 {
310 return Err(Error::NprimesTooSmall);
311 }
312
313 for (i, prime1) in primes.iter().enumerate() {
315 for prime2 in primes.iter().take(i) {
316 if prime1 == prime2 {
317 return Err(Error::InvalidPrime);
318 }
319 }
320 }
321 todo!()
322 }
323
324 pub fn to_public_key(&self) -> RsaPublicKey<T> {
329 self.pubkey_components.clone()
330 }
331
332 pub fn precompute(&mut self) -> Result<()> {
334 if self.precomputed.is_some() {
335 return Ok(());
336 }
337 todo!()
338 }
339
340 pub fn clear_precomputed(&mut self) {
342 self.precomputed = None;
343 }
344
345 pub fn crt_coefficient(&self) -> Option<T> {
347 todo!()
348 }
349
350 pub fn validate(&self) -> Result<()> {
353 check_public(self)?;
354
355 let mut m = T::one();
357 for prime in &self.primes {
358 if *prime < T::one() {
360 return Err(Error::InvalidPrime);
361 }
362 m = m * *prime;
363 }
364 if m != self.pubkey_components.n {
365 return Err(Error::InvalidModulus);
366 }
367
368 let mut de = *self.e();
374 de = de * self.d;
375 for prime in &self.primes {
376 let congruence: T = de % (*prime - T::one());
377 if !congruence.is_one() {
378 return Err(Error::InvalidExponent);
379 }
380 }
381
382 Ok(())
383 }
384
385 pub fn decrypt<P: PaddingScheme<T>>(&self, padding: P, ciphertext: &[u8], storage: &mut [u8]) -> Result<&[u8]> {
387 todo!()
388 }
389
390 pub fn decrypt_blinded<R: CryptoRngCore, P: PaddingScheme<T>>(
394 &self,
395 rng: &mut R,
396 padding: P,
397 ciphertext: &[u8],
398 storage: &mut [u8],
399 ) -> Result<&[u8]> {
400 todo!()
401 }
402
403 pub fn sign<S: SignatureScheme<T>>(&self, padding: S, digest_in: &[u8], storage: &mut [u8]) -> Result<&[u8]> {
405 todo!()
406 }
407
408 pub fn sign_with_rng<R: CryptoRngCore, S: SignatureScheme<T>>(
419 &self,
420 rng: &mut R,
421 padding: S,
422 digest_in: &[u8],
423 storage: &mut [u8],
424 ) -> Result<&[u8]> {
425 todo!()
426 }
427}
428
429impl<T: UnsignedModularInt> PrivateKeyParts<T> for RsaPrivateKey<T> {
430 fn d(&self) -> &T {
431 &self.d
432 }
433
434 fn primes(&self) -> &[T] {
435 &self.primes
436 }
437
438 fn dp(&self) -> Option<&T> {
439 self.precomputed.as_ref().map(|p| &p.dp)
440 }
441
442 fn dq(&self) -> Option<&T> {
443 self.precomputed.as_ref().map(|p| &p.dq)
444 }
445
446 fn qinv(&self) -> Option<&MontyForm<T>> {
447 todo!()
448 }
449
450 fn crt_values(&self) -> Option<&[CrtValue<T>]> {
451 if let Some(p) = &self.precomputed {
453 todo!()
454 } else {
455 None
456 }
457 }
458
459 fn p_params(&self) -> Option<&MontyParams<T>> {
460 todo!()
461 }
462
463 fn q_params(&self) -> Option<&MontyParams<T>> {
464 todo!()
465 }
466
467}
468
469#[inline]
471pub fn check_public<T>(public_key: &impl PublicKeyParts<T>) -> Result<()>
472where
473 T: UnsignedModularInt,
474{
475 check_public_with_max_size(public_key.n(), public_key.e(), RsaPublicKey::<T>::MAX_SIZE)
476}
477
478#[inline]
480fn check_public_with_max_size<T>(n: &T, e: &T, max_size: usize) -> Result<()>
481where
482 T: UnsignedModularInt,
483{
484 if n.bits_precision() as usize > max_size {
485 return Err(Error::ModulusTooLarge);
486 }
487
488 if e >= n || n.is_even().into() || n.is_zero().into() {
489 return Err(Error::InvalidModulus);
490 }
491
492 if e.is_even().into() {
493 return Err(Error::InvalidExponent);
494 }
495
496 if e < &T::from(RsaPublicKey::<T>::MIN_PUB_EXPONENT).unwrap() {
499 return Err(Error::PublicExponentTooSmall);
500 }
501
502 if e > &T::from(RsaPublicKey::<T>::MAX_PUB_EXPONENT).unwrap() {
503 return Err(Error::PublicExponentTooLarge);
504 }
505
506 Ok(())
507}
508
509#[cfg(feature = "serde")]
510impl<T> Serialize for RsaPublicKey<T>
511where
512 T: UnsignedModularInt,
513{
514 fn serialize<S>(&self, serializer: S) -> core::prelude::v1::Result<S::Ok, S::Error>
515 where
516 S: serdect::serde::Serializer,
517 {
518 todo!()
519 }
520}
521
522#[cfg(feature = "serde")]
523impl<'de, T> Deserialize<'de> for RsaPublicKey<T>
524where
525 T: UnsignedModularInt,
526{
527 fn deserialize<D>(deserializer: D) -> core::prelude::v1::Result<Self, D::Error>
528 where
529 D: serdect::serde::Deserializer<'de>,
530 {
531 todo!()
532 }
533}
534
535#[cfg(feature = "serde")]
536impl<T> Serialize for RsaPrivateKey<T>
537where
538 T: UnsignedModularInt,
539{
540 fn serialize<S>(&self, serializer: S) -> core::prelude::v1::Result<S::Ok, S::Error>
541 where
542 S: ser::Serializer,
543 {
544 todo!()
545 }
546}
547
548#[cfg(feature = "serde")]
549impl<'de, T> Deserialize<'de> for RsaPrivateKey<T>
550where
551 T: UnsignedModularInt,
552{
553 fn deserialize<D>(deserializer: D) -> core::prelude::v1::Result<Self, D::Error>
554 where
555 D: de::Deserializer<'de>,
556 {
557 todo!()
558 }
559}
560
561#[cfg(test)]
562mod tests {
563 use super::*;
564 use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt};
565 use crate::traits::{PrivateKeyParts, PublicKeyParts};
566
567 use hex_literal::hex;
568 use num_traits::{FromPrimitive, ToPrimitive};
569 use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
570
571 #[test]
572 #[ignore]
573 fn test_from_into() {
574 todo!()
575 }
576
577 fn test_key_basics<T>(private_key: &RsaPrivateKey<T>)
578 where
579 T: UnsignedModularInt,
580 {
581 private_key.validate().expect("invalid private key");
582
583 assert!(
584 PrivateKeyParts::d(private_key) < PublicKeyParts::n(private_key),
585 "private exponent too large"
586 );
587
588 todo!()
589 }
590
591 macro_rules! key_generation {
592 ($name:ident, $multi:expr, $size:expr) => {
593 #[test]
594 #[ignore]
595 fn $name() {
596 todo!()
597 }
598 };
599 }
600
601 key_generation!(key_generation_128, 2, 128);
602 key_generation!(key_generation_1024, 2, 1024);
603
604 key_generation!(key_generation_multi_3_256, 3, 256);
605
606 key_generation!(key_generation_multi_4_64, 4, 64);
607
608 key_generation!(key_generation_multi_5_64, 5, 64);
609 key_generation!(key_generation_multi_8_576, 8, 576);
610 #[test]
614 #[ignore]
615 fn test_negative_decryption_value() {
616 todo!()
617 }
618
619 #[test]
620 #[cfg(feature = "serde")]
621 fn test_serde() {
622 use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
623 use serde_test::{assert_tokens, Configure, Token};
624
625 let mut rng = ChaCha8Rng::from_seed([42; 32]);
626 }
643
644 #[test]
645 #[ignore]
646 fn invalid_coeff_private_key_regression() {
647 use base64ct::{Base64, Encoding};
648
649 let n = Base64::decode_vec(
650 "wC8GyQvTCZOK+iiBR5fGQCmzRCTWX9TQ3aRG5gGFk0wB6EFoLMAyEEqeG3gS8xhA\
651 m2rSWYx9kKufvNat3iWlbSRVqkcbpVAYlj2vTrpqDpJl+6u+zxFYoUEBevlJJkAh\
652 l8EuCccOA30fVpcfRvXPTtvRd3yFT9E9EwZljtgSI02w7gZwg7VIxaGeajh5Euz6\
653 ZVQZ+qNRKgXrRC7gPRqVyI6Dt0Jc+Su5KBGNn0QcPDzOahWha1ieaeMkFisZ9mdp\
654 sJoZ4tw5eicLaUomKzALHXQVt+/rcZSrCd6/7uUo11B/CYBM4UfSpwXaL88J9AE6\
655 A5++no9hmJzaF2LLp+Qwx4yY3j9TDutxSAjsraxxJOGZ3XyA9nG++Ybt3cxZ5fP7\
656 ROjxCfROBmVv5dYn0O9OBIqYeCH6QraNpZMadlLNIhyMv8Y+P3r5l/PaK4VJaEi5\
657 pPosnEPawp0W0yZDzmjk2z1LthaRx0aZVrAjlH0Rb/6goLUQ9qu1xsDtQVVpN4A8\
658 9ZUmtTWORnnJr0+595eHHxssd2gpzqf4bPjNITdAEuOCCtpvyi4ls23zwuzryUYj\
659 cUOEnsXNQ+DrZpLKxdtsD/qNV/j1hfeyBoPllC3cV+6bcGOFcVGbjYqb+Kw1b0+j\
660 L69RSKQqgmS+qYqr8c48nDRxyq3QXhR8qtzUwBFSLVk=",
661 )
662 .unwrap();
663 let e = Base64::decode_vec("AQAB").unwrap();
664 let d = Base64::decode_vec(
665 "qQazSQ+FRN7nVK1bRsROMRB8AmsDwLVEHivlz1V3Td2Dr+oW3YUMgxedhztML1Id\
666 QJPq/ad6qErJ6yRFNySVIjDaxzBTOEoB1eHa1btOnBJWb8rVvvjaorixvJ6Tn3i4\
667 EuhsvVy9DoR1k4rGj3qSIiFjUVvLRDAbLyhpGgEfsr0Z577yJmTC5E8JLRMOKX8T\
668 mxsk3jPVpsgd65Hu1s8S/ZmabwuHCf9SkdMeY/1bd/9i7BqqJeeDLE4B5x1xcC3z\
669 3scqDUTzqGO+vZPhjgprPDRlBamVwgenhr7KwCn8iaLamFinRVwOAag8BeBqOJj7\
670 lURiOsKQa9FIX1kdFUS1QMQxgtPycLjkbvCJjriqT7zWKsmJ7l8YLs6Wmm9/+QJR\
671 wNCEVdMTXKfCP1cJjudaiskEQThfUldtgu8gUDNYbQ/Filb2eKfiX4h1TiMxZqUZ\
672 HVZyb9nShbQoXJ3vj/MGVF0QM8TxhXM8r2Lv9gDYU5t9nQlUMLhs0jVjai48jHAB\
673 bFNyH3sEcOmJOIwJrCXw1dzG7AotwyaEVUHOmL04TffmwCFfnyrLjbFgnyOeoyII\
674 BYjcY7QFRm/9nupXMTH5hZ2qrHfCJIp0KK4tNBdQqmnHapFl5l6Le1s4qBS5bEIz\
675 jitobLvAFm9abPlDGfxmY6mlrMK4+nytwF9Ct7wc1AE=",
676 )
677 .unwrap();
678 let primes = [
679 Base64::decode_vec(
680 "9kQWEAzsbzOcdPa+s5wFfw4XDd7bB1q9foZ31b1+TNjGNxbSBCFlDF1q98vwpV6n\
681 M8bWDh/wtbNoETSQDgpEnYOQ26LWEw6YY1+q1Q2GGEFceYUf+Myk8/vTc8TN6Zw0\
682 bKZBWy10Qo8h7xk4JpzuI7NcxvjJYTkS9aErFxi3vVH0aiZC0tmfaCqr8a2rJxyV\
683 wqreRpOjwAWrotMsf2wGsF4ofx5ScoFy5GB5fJkkdOrW1LyTvZAUCX3cstPr19+T\
684 NC5zZOk7WzZatnCkN5H5WzalWtZuu0oVL205KPOa3R8V2yv5e6fm0v5fTmqSuvjm\
685 aMJLXCN4QJkmIzojO99ckQ==",
686 )
687 .unwrap(),
688 Base64::decode_vec(
689 "x8exdMjVA2CiI+Thx7loHtVcevoeE2sZ7btRVAvmBqo+lkHwxb7FHRnWvuj6eJSl\
690 D2f0T50EewIhhiW3R9BmktCk7hXjbSCnC1u9Oxc1IAUm/7azRqyfCMx43XhLxpD+\
691 xkBCpWkKDLxGczsRwTuaP3lKS3bSdBrNlGmdblubvVBIq4YZ2vXVlnYtza0cS+dg\
692 CK7BGTqUsrCUd/ZbIvwcwZkZtpkhj1KQfto9X/0OMurBzAqbkeq1cyRHXHkOfN/q\
693 bUIIRqr9Ii7Eswf9Vk8xp2O1Nt8nzcYS9PFD12M5eyaeFEkEYfpNMNGuTzp/31oq\
694 VjbpoCxS6vuWAZyADxhISQ==",
695 )
696 .unwrap(),
697 Base64::decode_vec(
698 "is7d0LY4HoXszlC2NO7gejkq7XqL4p1W6hZJPYTNx+r37t1CC2n3Vvzg6kNdpRix\
699 DhIpXVTLjN9O7UO/XuqSumYKJIKoP52eb4Tg+a3hw5Iz2Zsb5lUTNSLgkQSBPAf7\
700 1LHxbL82JL4g1nBUog8ae60BwnVArThKY4EwlJguGNw09BAU4lwf6csDl/nX2vfV\
701 wiAloYpeZkHL+L8m+bueGZM5KE2jEz+7ztZCI+T+E5i69rZEYDjx0lfLKlEhQlCW\
702 3HbCPELqXgNJJkRfi6MP9kXa9lSfnZmoT081RMvqonB/FUa4HOcKyCrw9XZEtnbN\
703 CIdbitfDVEX+pSSD7596wQ==",
704 )
705 .unwrap(),
706 Base64::decode_vec(
707 "GPs0injugfycacaeIP5jMa/WX55VEnKLDHom4k6WlfDF4L4gIGoJdekcPEUfxOI5\
708 faKvHyFwRP1wObkPoRBDM0qZxRfBl4zEtpvjHrd5MibSyJkM8+J0BIKk/nSjbRIG\
709 eb3hV5O56PvGB3S0dKhCUnuVObiC+ne7izplsD4OTG70l1Yud33UFntyoMxrxGYL\
710 USqhBMmZfHquJg4NOWOzKNY/K+EcHDLj1Kjvkcgv9Vf7ocsVxvpFdD9uGPceQ6kw\
711 RDdEl6mb+6FDgWuXVyqR9+904oanEIkbJ7vfkthagLbEf57dyG6nJlqh5FBZWxGI\
712 R72YGypPuAh7qnnqXXjY2Q==",
713 )
714 .unwrap(),
715 Base64::decode_vec(
716 "CUWC+hRWOT421kwRllgVjy6FYv6jQUcgDNHeAiYZnf5HjS9iK2ki7v8G5dL/0f+Y\
717 f+NhE/4q8w4m8go51hACrVpP1p8GJDjiT09+RsOzITsHwl+ceEKoe56ZW6iDHBLl\
718 rNw5/MtcYhKpjNU9KJ2udm5J/c9iislcjgckrZG2IB8ADgXHMEByZ5DgaMl4AKZ1\
719 Gx8/q6KftTvmOT5rNTMLi76VN5KWQcDWK/DqXiOiZHM7Nr4dX4me3XeRgABJyNR8\
720 Fqxj3N1+HrYLe/zs7LOaK0++F9Ul3tLelhrhsvLxei3oCZkF9A/foD3on3luYA+1\
721 cRcxWpSY3h2J4/22+yo4+Q==",
722 )
723 .unwrap(),
724 ];
725
726 todo!()
727 }
728
729 #[test]
730 #[ignore]
731 fn reject_oversized_private_key() {
732 let n = hex!(
759 "
760 90c06207caac3555c0b0947a5e8b681f5af6aed665ff1cd42b6b487f2f7d68f1
761 38f3dbbee6d2f10908507fe6bcf75e7cbd20e9af6ff1c202bcc3dbb45e9bb69b
762 b5d12a354c4b463a50820d16879373ceeb5574fdd9272be3b90d55c1a64855de
763 cf80520e94be2caa56c1737ed0042ef9c99c7ddb6cc76f3ada211ba90beae0fc
764 0a19024e74e474ca5747f0ee327892bf6eebc83974478dbfbebed40d0ffc626c
765 518071df5626abda386eed72585b676efb99b3ba111fb2f4b8fb0323bccb0c9b
766 5aa35e1da54f1cccac3e14fb1d4588d7b9b9f62d4ea6e570c049efcc34101147
767 fd7798549a42d86f9a90cee7fa0dd9f1ff4e10242280824872afd09782757abc
768 46773cab6989c08747193b7aa4c49a0065830a87e6f7e54455758b2c10317267
769 b9187358e41a5e5fef6fcbf81c8bc5e136ad1192aa7f3a5bc9270b22261b3c40
770 211d729d64c776cd8f219126e27227de3c0a40666b8da40c71243673a6187baf
771 8943eadf0c3d3fd150076dad97e286a68185db8523a61e548cba7a6834e4ce98
772 5af954c9eafb9d819a3d14b526a0f8d2fef13ad99ee48f10c3a00f8853d7853a
773 812b7a1c72bed38066f75779690bc12af9eb0d1eb8e2f7c4757c84e415725629
774 d15c4d68c18213f18a86d4ccc08552b3c80c97165de073ac0440af253e8578c4
775 8857f396e5eba6cd01ed1250feb2c32d77939f8be8bd47874151daed87e8c963
776 32f697ea7950bee7a2c12bb484200bcbd08de5aeae6f22ff9922e38075b56026
777 2472f039de08e9362cfdd19c0f0cd0749ebd85bddc3882fb887f9789ed8e388e
778 7e2eb2455399f166d5c9767ff378f8ebea465a0be2d2e3326fe6ed80e5e3050b
779 fb6c6a9dc8731ce4baa4e5b17b131113c79d6f290318095e37e7571a4ba697ab
780 5ea56190131e06d300310064776ba0330907e1cc41acdef4eeaa53964ef30c71
781 023c3cf71af2d1d9e83900ffc80e07ec2442a3dbd50e957686a22f1d8f512364
782 fb71e936f24990a4abcdbef2bea2f98cd77f1d1ca5625942c79347c146dee6e3
783 043eb622f63e627f4ebf20d6056133a4bd0f55dd13dcf429e0e73830969f543c
784 b31d86d9a878ca79d841444359cc0e31c0283fa6dd27b702b7ee05dad12c30f7
785 f84bf1309678efb8da108efcedc423da8587bd127ca082d417c8726f7889fb80
786 326c3fa6fddd507ac7841b2f2e5c8780d486a0d68229ee2957a8ec24e00e4ab4
787 de3fc811a4b5047c2b7920d071e9f2f9b61638dc15fb84cca46cad28e1ef539d
788 bcf249876f2647757b9a5e4f0b2ea6e7aabdf47dae826e9e259428bdb07e5a2a
789 68b98f141f5537be7a590cb3ba15b0bb15824652e8da8f70eb847240058a336a
790 1b6db7f88268aaf89f0b33b905d72c25338b13e61a51873c2d427021a3f29207
791 179ad32f423793f0c090dda025ce41df0e94afbc80ab5eda9b1a268aa2553a99"
792 );
793
794 todo!()
795 }
796
797 #[test]
798 #[ignore]
799 fn build_key_from_primes() {
800 const RSA_2048_PRIV_DER: &[u8] = include_bytes!("../tests/examples/pkcs8/rsa2048-priv.der");
801 todo!()
802 }
803
804 #[test]
805 #[ignore]
806 fn build_key_from_p_q() {
807 const RSA_2048_SP800_PRIV_DER: &[u8] =
808 include_bytes!("../tests/examples/pkcs8/rsa2048-sp800-56b-priv.der");
809 todo!()
810 }
811}