1use alloc::vec::Vec;
2use core::cmp::Ordering;
3use core::fmt;
4use core::hash::{Hash, Hasher};
5
6use crypto_bigint::{
7 modular::{BoxedMontyForm, BoxedMontyParams},
8 BoxedUint, ConcatenatingMul, Integer, NonZero, Odd, Resize,
9};
10use rand_core::CryptoRng;
11use zeroize::{Zeroize, ZeroizeOnDrop};
12#[cfg(feature = "serde")]
13use {
14 pkcs8::{DecodePrivateKey, EncodePrivateKey},
15 serdect::serde::{de, ser, Deserialize, Serialize},
16 spki::{DecodePublicKey, EncodePublicKey},
17};
18
19use crate::algorithms::generate::generate_multi_prime_key_with_exp;
20use crate::algorithms::rsa::{
21 compute_modulus, compute_private_exponent_carmicheal, compute_private_exponent_euler_totient,
22 recover_primes,
23};
24
25use crate::dummy_rng::DummyRng;
26use crate::errors::{Error, Result};
27use crate::traits::keys::{CrtValue, PrivateKeyParts, PublicKeyParts};
28use crate::traits::{PaddingScheme, SignatureScheme};
29
30#[derive(Debug, Clone)]
32pub struct RsaPublicKey {
33 n: NonZero<BoxedUint>,
35 e: BoxedUint,
40
41 n_params: BoxedMontyParams,
42}
43
44impl Eq for RsaPublicKey {}
45
46impl PartialEq for RsaPublicKey {
47 #[inline]
48 fn eq(&self, other: &RsaPublicKey) -> bool {
49 self.n == other.n && self.e == other.e
50 }
51}
52
53impl Hash for RsaPublicKey {
54 fn hash<H: Hasher>(&self, state: &mut H) {
55 state.write(b"RsaPublicKey");
57 Hash::hash(&self.n.as_limbs(), state);
59 Hash::hash(&self.e.as_limbs(), state);
60 }
61}
62
63#[derive(Clone)]
65pub struct RsaPrivateKey {
66 pubkey_components: RsaPublicKey,
68 pub(crate) d: BoxedUint,
70 pub(crate) primes: Vec<BoxedUint>,
72 pub(crate) precomputed: Option<PrecomputedValues>,
74}
75
76impl fmt::Debug for RsaPrivateKey {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 let precomputed = if self.precomputed.is_some() {
79 "Some(...)"
80 } else {
81 "None"
82 };
83 f.debug_struct("RsaPrivateKey")
84 .field("pubkey_components", &self.pubkey_components)
85 .field("d", &"...")
86 .field("primes", &"&[...]")
87 .field("precomputed", &precomputed)
88 .finish()
89 }
90}
91
92impl Eq for RsaPrivateKey {}
93impl PartialEq for RsaPrivateKey {
94 #[inline]
95 fn eq(&self, other: &RsaPrivateKey) -> bool {
96 self.pubkey_components == other.pubkey_components
97 && self.d == other.d
98 && self.primes == other.primes
99 }
100}
101
102impl AsRef<RsaPublicKey> for RsaPrivateKey {
103 fn as_ref(&self) -> &RsaPublicKey {
104 &self.pubkey_components
105 }
106}
107
108impl Hash for RsaPrivateKey {
109 fn hash<H: Hasher>(&self, state: &mut H) {
110 state.write(b"RsaPrivateKey");
112 Hash::hash(&self.pubkey_components, state);
113 }
114}
115
116impl Drop for RsaPrivateKey {
117 fn drop(&mut self) {
118 self.d.zeroize();
119 self.primes.zeroize();
120 self.precomputed.zeroize();
121 }
122}
123
124impl ZeroizeOnDrop for RsaPrivateKey {}
125
126#[derive(Clone)]
127pub(crate) struct PrecomputedValues {
128 pub(crate) dp: BoxedUint,
130 pub(crate) dq: BoxedUint,
132 pub(crate) qinv: BoxedMontyForm,
134
135 pub(crate) p_params: BoxedMontyParams,
137 pub(crate) q_params: BoxedMontyParams,
139}
140
141impl ZeroizeOnDrop for PrecomputedValues {}
142
143impl Zeroize for PrecomputedValues {
144 fn zeroize(&mut self) {
145 self.dp.zeroize();
146 self.dq.zeroize();
147 }
151}
152
153impl Drop for PrecomputedValues {
154 fn drop(&mut self) {
155 self.zeroize();
156 }
157}
158
159impl From<RsaPrivateKey> for RsaPublicKey {
160 fn from(private_key: RsaPrivateKey) -> Self {
161 (&private_key).into()
162 }
163}
164
165impl From<&RsaPrivateKey> for RsaPublicKey {
166 fn from(private_key: &RsaPrivateKey) -> Self {
167 let n = PublicKeyParts::n(private_key);
168 let e = PublicKeyParts::e(private_key);
169 let n_params = PublicKeyParts::n_params(private_key);
170 RsaPublicKey {
171 n: n.clone(),
172 e: e.clone(),
173 n_params: n_params.clone(),
174 }
175 }
176}
177
178impl PublicKeyParts for RsaPublicKey {
179 fn n(&self) -> &NonZero<BoxedUint> {
180 &self.n
181 }
182
183 fn e(&self) -> &BoxedUint {
184 &self.e
185 }
186
187 fn n_params(&self) -> &BoxedMontyParams {
188 &self.n_params
189 }
190}
191
192impl RsaPublicKey {
193 pub fn encrypt<R: CryptoRng + ?Sized, P: PaddingScheme>(
195 &self,
196 rng: &mut R,
197 padding: P,
198 msg: &[u8],
199 ) -> Result<Vec<u8>> {
200 padding.encrypt(rng, self, msg)
201 }
202
203 pub fn verify<S: SignatureScheme>(&self, scheme: S, hashed: &[u8], sig: &[u8]) -> Result<()> {
210 scheme.verify(self, hashed, sig)
211 }
212}
213
214impl RsaPublicKey {
215 pub const MIN_PUB_EXPONENT: u64 = 2;
217
218 pub const MAX_PUB_EXPONENT: u64 = (1 << 33) - 1;
235
236 pub const MAX_SIZE: usize = 8192;
238
239 pub fn new(n: BoxedUint, e: BoxedUint) -> Result<Self> {
244 Self::new_with_max_size(n, e, Self::MAX_SIZE)
245 }
246
247 pub fn new_with_max_size(n: BoxedUint, e: BoxedUint, max_size: usize) -> Result<Self> {
249 check_public_with_max_size(&n, &e, Some(max_size))?;
250
251 let n_odd = Odd::new(n.clone())
252 .into_option()
253 .ok_or(Error::InvalidModulus)?;
254 let n_params = BoxedMontyParams::new(n_odd);
255 let n = NonZero::new(n).expect("checked above");
256
257 Ok(Self { n, e, n_params })
258 }
259
260 pub fn new_unchecked(n: BoxedUint, e: BoxedUint) -> Self {
267 let n_odd = Odd::new(n.clone()).expect("n must be odd");
268 let n_params = BoxedMontyParams::new(n_odd);
269 let n = NonZero::new(n).expect("odd numbers are non zero");
270
271 Self { n, e, n_params }
272 }
273}
274
275impl PublicKeyParts for RsaPrivateKey {
276 fn n(&self) -> &NonZero<BoxedUint> {
277 &self.pubkey_components.n
278 }
279
280 fn e(&self) -> &BoxedUint {
281 &self.pubkey_components.e
282 }
283
284 fn n_params(&self) -> &BoxedMontyParams {
285 &self.pubkey_components.n_params
286 }
287}
288
289impl RsaPrivateKey {
290 const EXP: u64 = 65537;
292
293 const MIN_SIZE: u32 = 1024;
295
296 pub fn new<R: CryptoRng + ?Sized>(rng: &mut R, bit_size: usize) -> Result<Self> {
301 Self::new_with_exp(rng, bit_size, Self::EXP.into())
302 }
303
304 #[cfg(feature = "hazmat")]
310 pub fn new_unchecked<R: CryptoRng + ?Sized>(rng: &mut R, bit_size: usize) -> Result<Self> {
311 Self::new_with_exp_unchecked(rng, bit_size, Self::EXP.into())
312 }
313
314 pub fn new_with_exp<R: CryptoRng + ?Sized>(
319 rng: &mut R,
320 bit_size: usize,
321 exp: BoxedUint,
322 ) -> Result<RsaPrivateKey> {
323 if bit_size < Self::MIN_SIZE as usize {
324 return Err(Error::ModulusTooSmall);
325 }
326
327 let components = generate_multi_prime_key_with_exp(rng, 2, bit_size, exp)?;
328 RsaPrivateKey::from_components(
329 components.n.get(),
330 components.e,
331 components.d,
332 components.primes,
333 )
334 }
335
336 #[cfg(feature = "hazmat")]
345 pub fn new_with_exp_unchecked<R: CryptoRng + ?Sized>(
346 rng: &mut R,
347 bit_size: usize,
348 exp: BoxedUint,
349 ) -> Result<RsaPrivateKey> {
350 let components = generate_multi_prime_key_with_exp(rng, 2, bit_size, exp)?;
351 RsaPrivateKey::from_components(
352 components.n.get(),
353 components.e,
354 components.d,
355 components.primes,
356 )
357 }
358
359 fn from_components_inner(
369 n: BoxedUint,
370 e: BoxedUint,
371 d: BoxedUint,
372 mut primes: Vec<BoxedUint>,
373 ) -> Result<RsaPrivateKey> {
374 let n = Odd::new(n).into_option().ok_or(Error::InvalidModulus)?;
375
376 let n_bits = n.bits_vartime();
379 let n = n.resize_unchecked(n_bits);
380
381 let n_params = BoxedMontyParams::new(n.clone());
382 let n_c = NonZero::new(n.get())
383 .into_option()
384 .ok_or(Error::InvalidModulus)?;
385
386 match primes.len() {
387 0 => {
388 let (p, q) = recover_primes(&n_c, &e, &d)?;
391 primes.push(p);
392 primes.push(q);
393 }
394 1 => return Err(Error::NprimesTooSmall),
395 _ => {
396 if primes
400 .iter()
401 .fold(BoxedUint::one(), |acc, p| acc.concatenating_mul(&p))
402 != n_c.as_ref()
403 {
404 return Err(Error::InvalidModulus);
405 }
406 }
407 }
408
409 let primes = primes
411 .into_iter()
412 .map(|p| {
413 let p_bits = p.bits();
414 p.resize_unchecked(p_bits)
415 })
416 .collect();
417
418 let k = RsaPrivateKey {
419 pubkey_components: RsaPublicKey {
420 n: n_c,
421 e,
422 n_params,
423 },
424 d,
425 primes,
426 precomputed: None,
427 };
428
429 Ok(k)
430 }
431
432 #[cfg(feature = "hazmat")]
450 pub fn from_components_with_large_exponent(
451 n: BoxedUint,
452 e: BoxedUint,
453 d: BoxedUint,
454 primes: Vec<BoxedUint>,
455 ) -> Result<RsaPrivateKey> {
456 let mut k = Self::from_components_inner(n, e, d, primes)?;
457
458 validate_skip_exponent_size(&k)?;
460
461 k.precompute().ok();
463
464 Ok(k)
465 }
466
467 pub fn from_components(
481 n: BoxedUint,
482 e: BoxedUint,
483 d: BoxedUint,
484 primes: Vec<BoxedUint>,
485 ) -> Result<RsaPrivateKey> {
486 let mut k = Self::from_components_inner(n, e, d, primes)?;
487
488 k.validate()?;
490
491 k.precompute().ok();
493
494 Ok(k)
495 }
496
497 pub fn from_p_q(
504 p: BoxedUint,
505 q: BoxedUint,
506 public_exponent: BoxedUint,
507 ) -> Result<RsaPrivateKey> {
508 if p == q {
509 return Err(Error::InvalidPrime);
510 }
511
512 let d = compute_private_exponent_carmicheal(&p, &q, &public_exponent)?;
513 let primes = vec![p, q];
514 let n = compute_modulus(&primes);
515
516 Self::from_components(n.get(), public_exponent, d, primes)
517 }
518
519 pub fn from_primes(
523 primes: Vec<BoxedUint>,
524 public_exponent: BoxedUint,
525 ) -> Result<RsaPrivateKey> {
526 if primes.len() < 2 {
527 return Err(Error::NprimesTooSmall);
528 }
529
530 for (i, prime1) in primes.iter().enumerate() {
532 for prime2 in primes.iter().take(i) {
533 if prime1 == prime2 {
534 return Err(Error::InvalidPrime);
535 }
536 }
537 }
538
539 let n = compute_modulus(&primes);
540 let d = compute_private_exponent_euler_totient(&primes, &public_exponent)?;
541
542 Self::from_components(n.get(), public_exponent, d, primes)
543 }
544
545 pub fn as_public_key(&self) -> &RsaPublicKey {
549 &self.pubkey_components
550 }
551
552 pub fn to_public_key(&self) -> RsaPublicKey {
557 self.pubkey_components.clone()
558 }
559
560 pub fn precompute(&mut self) -> Result<()> {
562 if self.precomputed.is_some() {
563 return Ok(());
564 }
565
566 let d = &self.d;
567 let p = self.primes[0].clone();
568 let q = self.primes[1].clone();
569
570 let p_odd = Odd::new(p.clone())
571 .into_option()
572 .ok_or(Error::InvalidPrime)?;
573 let p_params = BoxedMontyParams::new(p_odd);
574 let q_odd = Odd::new(q.clone())
575 .into_option()
576 .ok_or(Error::InvalidPrime)?;
577 let q_params = BoxedMontyParams::new(q_odd);
578
579 let x = NonZero::new(p.wrapping_sub(BoxedUint::one()))
580 .into_option()
581 .ok_or(Error::InvalidPrime)?;
582 let dp = d.rem_vartime(&x);
583
584 let x = NonZero::new(q.wrapping_sub(BoxedUint::one()))
585 .into_option()
586 .ok_or(Error::InvalidPrime)?;
587 let dq = d.rem_vartime(&x);
588
589 let q_mod_p = match p.bits_precision().cmp(&q.bits_precision()) {
592 Ordering::Less => (&q
593 % NonZero::new(p.clone())
594 .expect("`p` is non-zero")
595 .resize_unchecked(q.bits_precision()))
596 .resize_unchecked(p.bits_precision()),
597 Ordering::Greater => {
598 (&q).resize_unchecked(p.bits_precision())
599 % &NonZero::new(p.clone()).expect("`p` is non-zero")
600 }
601 Ordering::Equal => &q % NonZero::new(p.clone()).expect("`p` is non-zero"),
602 };
603
604 let q_mod_p = BoxedMontyForm::new(q_mod_p, &p_params);
605 let qinv = q_mod_p.invert().into_option().ok_or(Error::InvalidPrime)?;
606
607 debug_assert_eq!(dp.bits_precision(), p.bits_precision());
608 debug_assert_eq!(dq.bits_precision(), q.bits_precision());
609 debug_assert_eq!(qinv.bits_precision(), p.bits_precision());
610 debug_assert_eq!(p_params.bits_precision(), p.bits_precision());
611 debug_assert_eq!(q_params.bits_precision(), q.bits_precision());
612
613 self.precomputed = Some(PrecomputedValues {
614 dp,
615 dq,
616 qinv,
617 p_params,
618 q_params,
619 });
620
621 Ok(())
622 }
623
624 pub fn clear_precomputed(&mut self) {
626 self.precomputed = None;
627 }
628
629 pub fn crt_coefficient(&self) -> Option<BoxedUint> {
631 let p = &self.primes[0];
632 let q = &self.primes[1];
633 Option::from(q.invert_mod(&NonZero::new(p.clone()).expect("prime")))
635 }
636
637 pub fn validate(&self) -> Result<()> {
640 check_public(self)?;
641 validate_private_key_parts(self)?;
642 Ok(())
643 }
644
645 pub fn decrypt<P: PaddingScheme>(&self, padding: P, ciphertext: &[u8]) -> Result<Vec<u8>> {
647 padding.decrypt(Option::<&mut DummyRng>::None, self, ciphertext)
648 }
649
650 pub fn decrypt_blinded<R: CryptoRng + ?Sized, P: PaddingScheme>(
654 &self,
655 rng: &mut R,
656 padding: P,
657 ciphertext: &[u8],
658 ) -> Result<Vec<u8>> {
659 padding.decrypt(Some(rng), self, ciphertext)
660 }
661
662 pub fn sign<S: SignatureScheme>(&self, padding: S, digest_in: &[u8]) -> Result<Vec<u8>> {
664 padding.sign(Option::<&mut DummyRng>::None, self, digest_in)
665 }
666
667 pub fn sign_with_rng<R: CryptoRng + ?Sized, S: SignatureScheme>(
678 &self,
679 rng: &mut R,
680 padding: S,
681 digest_in: &[u8],
682 ) -> Result<Vec<u8>> {
683 padding.sign(Some(rng), self, digest_in)
684 }
685}
686
687impl PrivateKeyParts for RsaPrivateKey {
688 fn d(&self) -> &BoxedUint {
689 &self.d
690 }
691
692 fn primes(&self) -> &[BoxedUint] {
693 &self.primes
694 }
695
696 fn dp(&self) -> Option<&BoxedUint> {
697 self.precomputed.as_ref().map(|p| &p.dp)
698 }
699
700 fn dq(&self) -> Option<&BoxedUint> {
701 self.precomputed.as_ref().map(|p| &p.dq)
702 }
703
704 fn qinv(&self) -> Option<&BoxedMontyForm> {
705 self.precomputed.as_ref().map(|p| &p.qinv)
706 }
707
708 fn crt_values(&self) -> Option<&[CrtValue]> {
709 None
710 }
711
712 fn p_params(&self) -> Option<&BoxedMontyParams> {
713 self.precomputed.as_ref().map(|p| &p.p_params)
714 }
715
716 fn q_params(&self) -> Option<&BoxedMontyParams> {
717 self.precomputed.as_ref().map(|p| &p.q_params)
718 }
719}
720
721#[inline]
723pub fn check_public(public_key: &impl PublicKeyParts) -> Result<()> {
724 check_public_with_max_size(public_key.n(), public_key.e(), None)
725}
726
727#[inline]
729fn check_public_with_max_size(n: &BoxedUint, e: &BoxedUint, max_size: Option<usize>) -> Result<()> {
730 if let Some(max_size) = max_size {
731 if n.bits_vartime() as usize > max_size {
732 return Err(Error::ModulusTooLarge);
733 }
734 }
735
736 check_public_skip_exponent_size(n, e)?;
737
738 if e < &BoxedUint::from(RsaPublicKey::MIN_PUB_EXPONENT) {
739 return Err(Error::PublicExponentTooSmall);
740 }
741
742 if e > &BoxedUint::from(RsaPublicKey::MAX_PUB_EXPONENT) {
743 return Err(Error::PublicExponentTooLarge);
744 }
745
746 Ok(())
747}
748
749#[inline]
753fn check_public_skip_exponent_size(n: &BoxedUint, e: &BoxedUint) -> Result<()> {
754 if e >= n || n.is_even().into() || n.is_zero().into() {
755 return Err(Error::InvalidModulus);
756 }
757
758 if e.is_even().into() {
759 return Err(Error::InvalidExponent);
760 }
761
762 Ok(())
764}
765
766fn validate_private_key_parts(key: &RsaPrivateKey) -> Result<()> {
771 let mut m = BoxedUint::one_with_precision(key.pubkey_components.n.bits_precision());
773 let one = BoxedUint::one();
774 for prime in &key.primes {
775 if prime <= &one {
777 return Err(Error::InvalidPrime);
778 }
779 m = m.wrapping_mul(prime);
780 }
781 if m != *key.pubkey_components.n {
782 return Err(Error::InvalidModulus);
783 }
784
785 let de = key.d.concatenating_mul(&key.pubkey_components.e);
791
792 for prime in &key.primes {
793 let x = NonZero::new(prime.wrapping_sub(BoxedUint::one())).unwrap();
794 let congruence = de.rem_vartime(&x);
795 if !bool::from(congruence.is_one()) {
796 return Err(Error::InvalidExponent);
797 }
798 }
799
800 Ok(())
801}
802
803#[cfg(feature = "hazmat")]
809fn validate_skip_exponent_size(key: &RsaPrivateKey) -> Result<()> {
810 check_public_skip_exponent_size(key.pubkey_components.n.as_ref(), &key.pubkey_components.e)?;
812
813 validate_private_key_parts(key)?;
815
816 Ok(())
817}
818
819#[cfg(feature = "serde")]
820impl Serialize for RsaPublicKey {
821 fn serialize<S>(&self, serializer: S) -> core::prelude::v1::Result<S::Ok, S::Error>
822 where
823 S: serdect::serde::Serializer,
824 {
825 let der = self.to_public_key_der().map_err(ser::Error::custom)?;
826 serdect::slice::serialize_hex_lower_or_bin(&der, serializer)
827 }
828}
829
830#[cfg(feature = "serde")]
831impl<'de> Deserialize<'de> for RsaPublicKey {
832 fn deserialize<D>(deserializer: D) -> core::prelude::v1::Result<Self, D::Error>
833 where
834 D: serdect::serde::Deserializer<'de>,
835 {
836 let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?;
837 Self::from_public_key_der(&der_bytes).map_err(de::Error::custom)
838 }
839}
840
841#[cfg(feature = "serde")]
842impl Serialize for RsaPrivateKey {
843 fn serialize<S>(&self, serializer: S) -> core::prelude::v1::Result<S::Ok, S::Error>
844 where
845 S: ser::Serializer,
846 {
847 let der = self.to_pkcs8_der().map_err(ser::Error::custom)?;
848 serdect::slice::serialize_hex_lower_or_bin(&der.as_bytes(), serializer)
849 }
850}
851
852#[cfg(feature = "serde")]
853impl<'de> Deserialize<'de> for RsaPrivateKey {
854 fn deserialize<D>(deserializer: D) -> core::prelude::v1::Result<Self, D::Error>
855 where
856 D: de::Deserializer<'de>,
857 {
858 let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?;
859 Self::from_pkcs8_der(&der_bytes).map_err(de::Error::custom)
860 }
861}
862
863#[cfg(test)]
864mod tests {
865 use super::*;
866 use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt};
867 use crate::traits::{PrivateKeyParts, PublicKeyParts};
868
869 use hex_literal::hex;
870 use rand::rngs::ChaCha8Rng;
871 use rand_core::SeedableRng;
872
873 #[cfg(feature = "encoding")]
874 use pkcs8::DecodePrivateKey;
875
876 #[test]
877 fn test_from_into() {
878 let raw_n = BoxedUint::from(101u64);
879 let n_odd = Odd::new(raw_n.clone()).unwrap();
880 let private_key = RsaPrivateKey {
881 pubkey_components: RsaPublicKey {
882 n: NonZero::new(raw_n.clone()).unwrap(),
883 e: BoxedUint::from(200u64),
884 n_params: BoxedMontyParams::new(n_odd),
885 },
886 d: BoxedUint::from(123u64),
887 primes: vec![],
888 precomputed: None,
889 };
890 let public_key: RsaPublicKey = private_key.into();
891
892 let n_limbs: &[u64] = PublicKeyParts::n(&public_key).as_ref().as_ref();
893 assert_eq!(n_limbs, &[101u64]);
894 assert_eq!(PublicKeyParts::e(&public_key), &BoxedUint::from(200u64));
895 assert_eq!(PublicKeyParts::e_bytes(&public_key), [200].into());
896 assert_eq!(PublicKeyParts::n_bytes(&public_key), [101].into());
897 }
898
899 fn test_key_basics(private_key: &RsaPrivateKey) {
900 private_key.validate().expect("invalid private key");
901
902 assert!(
903 PrivateKeyParts::d(private_key) < PublicKeyParts::n(private_key).as_ref(),
904 "private exponent too large"
905 );
906
907 let pub_key: RsaPublicKey = private_key.clone().into();
908 let m = BoxedUint::from(42u64);
909 let c = rsa_encrypt(&pub_key, &m).expect("encryption successful");
910
911 let m2 = rsa_decrypt_and_check::<ChaCha8Rng>(private_key, None, &c)
912 .expect("unable to decrypt without blinding");
913 assert_eq!(m, m2);
914 let mut rng = ChaCha8Rng::from_seed([42; 32]);
915 let m3 = rsa_decrypt_and_check(private_key, Some(&mut rng), &c)
916 .expect("unable to decrypt with blinding");
917 assert_eq!(m, m3);
918 }
919
920 macro_rules! key_generation {
921 ($name:ident, $multi:expr, $size:expr) => {
922 #[test]
923 fn $name() {
924 let mut rng = ChaCha8Rng::from_seed([42; 32]);
925 let exp = BoxedUint::from(RsaPrivateKey::EXP);
926
927 for _ in 0..10 {
928 let components =
929 generate_multi_prime_key_with_exp(&mut rng, $multi, $size, exp.clone())
930 .unwrap();
931 let private_key = RsaPrivateKey::from_components(
932 components.n.get(),
933 components.e,
934 components.d,
935 components.primes,
936 )
937 .unwrap();
938 assert_eq!(PublicKeyParts::n(&private_key).bits(), $size);
939
940 test_key_basics(&private_key);
941 }
942 }
943 };
944 }
945
946 key_generation!(key_generation_128, 2, 128);
947 key_generation!(key_generation_1024, 2, 1024);
948
949 key_generation!(key_generation_multi_3_256, 3, 256);
950
951 key_generation!(key_generation_multi_4_64, 4, 64);
952
953 key_generation!(key_generation_multi_5_64, 5, 64);
954 key_generation!(key_generation_multi_8_576, 8, 576);
955 key_generation!(key_generation_multi_16_1024, 16, 1024);
956
957 #[test]
958 fn test_negative_decryption_value() {
959 let bits = 128;
960 let private_key = RsaPrivateKey::from_components(
961 BoxedUint::from_le_slice(
962 &[
963 99, 192, 208, 179, 0, 220, 7, 29, 49, 151, 75, 107, 75, 73, 200, 180,
964 ],
965 bits,
966 )
967 .unwrap(),
968 BoxedUint::from_le_slice(&[1, 0, 1, 0, 0, 0, 0, 0], 64).unwrap(),
969 BoxedUint::from_le_slice(
970 &[
971 81, 163, 254, 144, 171, 159, 144, 42, 244, 133, 51, 249, 28, 12, 63, 65,
972 ],
973 bits,
974 )
975 .unwrap(),
976 vec![
977 BoxedUint::from_le_slice(&[105, 101, 60, 173, 19, 153, 3, 192], bits / 2).unwrap(),
978 BoxedUint::from_le_slice(&[235, 65, 160, 134, 32, 136, 6, 241], bits / 2).unwrap(),
979 ],
980 )
981 .unwrap();
982
983 for _ in 0..1000 {
984 test_key_basics(&private_key);
985 }
986 }
987
988 #[test]
989 #[cfg(all(feature = "hazmat", feature = "serde"))]
990 fn test_serde() {
991 use rand::rngs::ChaCha8Rng;
992 use rand_core::SeedableRng;
993 use serde_test::{assert_tokens, Configure, Token};
994
995 let mut rng = ChaCha8Rng::from_seed([42; 32]);
996 let priv_key = RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");
997
998 let priv_tokens = [Token::Str(concat!(
999 "3056020100300d06092a864886f70d010101050004423040020100020900a",
1000 "b240c3361d02e370203010001020811e54a15259d22f9020500ceff5cf302",
1001 "0500d3a7aaad020500ccaddf17020500cb529d3d020500bb526d6f"
1002 ))];
1003 assert_tokens(&priv_key.clone().readable(), &priv_tokens);
1004
1005 let priv_tokens = [Token::Str(
1006 "3024300d06092a864886f70d01010105000313003010020900ab240c3361d02e370203010001",
1007 )];
1008 assert_tokens(
1009 &RsaPublicKey::from(priv_key.clone()).readable(),
1010 &priv_tokens,
1011 );
1012 }
1013
1014 #[test]
1015 fn invalid_coeff_private_key_regression() {
1016 use base64ct::{Base64, Encoding};
1017
1018 let n = Base64::decode_vec(
1019 "wC8GyQvTCZOK+iiBR5fGQCmzRCTWX9TQ3aRG5gGFk0wB6EFoLMAyEEqeG3gS8xhA\
1020 m2rSWYx9kKufvNat3iWlbSRVqkcbpVAYlj2vTrpqDpJl+6u+zxFYoUEBevlJJkAh\
1021 l8EuCccOA30fVpcfRvXPTtvRd3yFT9E9EwZljtgSI02w7gZwg7VIxaGeajh5Euz6\
1022 ZVQZ+qNRKgXrRC7gPRqVyI6Dt0Jc+Su5KBGNn0QcPDzOahWha1ieaeMkFisZ9mdp\
1023 sJoZ4tw5eicLaUomKzALHXQVt+/rcZSrCd6/7uUo11B/CYBM4UfSpwXaL88J9AE6\
1024 A5++no9hmJzaF2LLp+Qwx4yY3j9TDutxSAjsraxxJOGZ3XyA9nG++Ybt3cxZ5fP7\
1025 ROjxCfROBmVv5dYn0O9OBIqYeCH6QraNpZMadlLNIhyMv8Y+P3r5l/PaK4VJaEi5\
1026 pPosnEPawp0W0yZDzmjk2z1LthaRx0aZVrAjlH0Rb/6goLUQ9qu1xsDtQVVpN4A8\
1027 9ZUmtTWORnnJr0+595eHHxssd2gpzqf4bPjNITdAEuOCCtpvyi4ls23zwuzryUYj\
1028 cUOEnsXNQ+DrZpLKxdtsD/qNV/j1hfeyBoPllC3cV+6bcGOFcVGbjYqb+Kw1b0+j\
1029 L69RSKQqgmS+qYqr8c48nDRxyq3QXhR8qtzUwBFSLVk=",
1030 )
1031 .unwrap();
1032 let e = Base64::decode_vec("AQAB").unwrap();
1033 let d = Base64::decode_vec(
1034 "qQazSQ+FRN7nVK1bRsROMRB8AmsDwLVEHivlz1V3Td2Dr+oW3YUMgxedhztML1Id\
1035 QJPq/ad6qErJ6yRFNySVIjDaxzBTOEoB1eHa1btOnBJWb8rVvvjaorixvJ6Tn3i4\
1036 EuhsvVy9DoR1k4rGj3qSIiFjUVvLRDAbLyhpGgEfsr0Z577yJmTC5E8JLRMOKX8T\
1037 mxsk3jPVpsgd65Hu1s8S/ZmabwuHCf9SkdMeY/1bd/9i7BqqJeeDLE4B5x1xcC3z\
1038 3scqDUTzqGO+vZPhjgprPDRlBamVwgenhr7KwCn8iaLamFinRVwOAag8BeBqOJj7\
1039 lURiOsKQa9FIX1kdFUS1QMQxgtPycLjkbvCJjriqT7zWKsmJ7l8YLs6Wmm9/+QJR\
1040 wNCEVdMTXKfCP1cJjudaiskEQThfUldtgu8gUDNYbQ/Filb2eKfiX4h1TiMxZqUZ\
1041 HVZyb9nShbQoXJ3vj/MGVF0QM8TxhXM8r2Lv9gDYU5t9nQlUMLhs0jVjai48jHAB\
1042 bFNyH3sEcOmJOIwJrCXw1dzG7AotwyaEVUHOmL04TffmwCFfnyrLjbFgnyOeoyII\
1043 BYjcY7QFRm/9nupXMTH5hZ2qrHfCJIp0KK4tNBdQqmnHapFl5l6Le1s4qBS5bEIz\
1044 jitobLvAFm9abPlDGfxmY6mlrMK4+nytwF9Ct7wc1AE=",
1045 )
1046 .unwrap();
1047 let primes = [
1048 Base64::decode_vec(
1049 "9kQWEAzsbzOcdPa+s5wFfw4XDd7bB1q9foZ31b1+TNjGNxbSBCFlDF1q98vwpV6n\
1050 M8bWDh/wtbNoETSQDgpEnYOQ26LWEw6YY1+q1Q2GGEFceYUf+Myk8/vTc8TN6Zw0\
1051 bKZBWy10Qo8h7xk4JpzuI7NcxvjJYTkS9aErFxi3vVH0aiZC0tmfaCqr8a2rJxyV\
1052 wqreRpOjwAWrotMsf2wGsF4ofx5ScoFy5GB5fJkkdOrW1LyTvZAUCX3cstPr19+T\
1053 NC5zZOk7WzZatnCkN5H5WzalWtZuu0oVL205KPOa3R8V2yv5e6fm0v5fTmqSuvjm\
1054 aMJLXCN4QJkmIzojO99ckQ==",
1055 )
1056 .unwrap(),
1057 Base64::decode_vec(
1058 "x8exdMjVA2CiI+Thx7loHtVcevoeE2sZ7btRVAvmBqo+lkHwxb7FHRnWvuj6eJSl\
1059 D2f0T50EewIhhiW3R9BmktCk7hXjbSCnC1u9Oxc1IAUm/7azRqyfCMx43XhLxpD+\
1060 xkBCpWkKDLxGczsRwTuaP3lKS3bSdBrNlGmdblubvVBIq4YZ2vXVlnYtza0cS+dg\
1061 CK7BGTqUsrCUd/ZbIvwcwZkZtpkhj1KQfto9X/0OMurBzAqbkeq1cyRHXHkOfN/q\
1062 bUIIRqr9Ii7Eswf9Vk8xp2O1Nt8nzcYS9PFD12M5eyaeFEkEYfpNMNGuTzp/31oq\
1063 VjbpoCxS6vuWAZyADxhISQ==",
1064 )
1065 .unwrap(),
1066 Base64::decode_vec(
1067 "is7d0LY4HoXszlC2NO7gejkq7XqL4p1W6hZJPYTNx+r37t1CC2n3Vvzg6kNdpRix\
1068 DhIpXVTLjN9O7UO/XuqSumYKJIKoP52eb4Tg+a3hw5Iz2Zsb5lUTNSLgkQSBPAf7\
1069 1LHxbL82JL4g1nBUog8ae60BwnVArThKY4EwlJguGNw09BAU4lwf6csDl/nX2vfV\
1070 wiAloYpeZkHL+L8m+bueGZM5KE2jEz+7ztZCI+T+E5i69rZEYDjx0lfLKlEhQlCW\
1071 3HbCPELqXgNJJkRfi6MP9kXa9lSfnZmoT081RMvqonB/FUa4HOcKyCrw9XZEtnbN\
1072 CIdbitfDVEX+pSSD7596wQ==",
1073 )
1074 .unwrap(),
1075 Base64::decode_vec(
1076 "GPs0injugfycacaeIP5jMa/WX55VEnKLDHom4k6WlfDF4L4gIGoJdekcPEUfxOI5\
1077 faKvHyFwRP1wObkPoRBDM0qZxRfBl4zEtpvjHrd5MibSyJkM8+J0BIKk/nSjbRIG\
1078 eb3hV5O56PvGB3S0dKhCUnuVObiC+ne7izplsD4OTG70l1Yud33UFntyoMxrxGYL\
1079 USqhBMmZfHquJg4NOWOzKNY/K+EcHDLj1Kjvkcgv9Vf7ocsVxvpFdD9uGPceQ6kw\
1080 RDdEl6mb+6FDgWuXVyqR9+904oanEIkbJ7vfkthagLbEf57dyG6nJlqh5FBZWxGI\
1081 R72YGypPuAh7qnnqXXjY2Q==",
1082 )
1083 .unwrap(),
1084 Base64::decode_vec(
1085 "CUWC+hRWOT421kwRllgVjy6FYv6jQUcgDNHeAiYZnf5HjS9iK2ki7v8G5dL/0f+Y\
1086 f+NhE/4q8w4m8go51hACrVpP1p8GJDjiT09+RsOzITsHwl+ceEKoe56ZW6iDHBLl\
1087 rNw5/MtcYhKpjNU9KJ2udm5J/c9iislcjgckrZG2IB8ADgXHMEByZ5DgaMl4AKZ1\
1088 Gx8/q6KftTvmOT5rNTMLi76VN5KWQcDWK/DqXiOiZHM7Nr4dX4me3XeRgABJyNR8\
1089 Fqxj3N1+HrYLe/zs7LOaK0++F9Ul3tLelhrhsvLxei3oCZkF9A/foD3on3luYA+1\
1090 cRcxWpSY3h2J4/22+yo4+Q==",
1091 )
1092 .unwrap(),
1093 ];
1094
1095 let e = BoxedUint::from_be_slice(&e, 64).unwrap();
1096
1097 let bits = 4096;
1098 let n = BoxedUint::from_be_slice(&n, bits).unwrap();
1099 let d = BoxedUint::from_be_slice(&d, bits).unwrap();
1100 let primes = primes
1101 .iter()
1102 .map(|p| BoxedUint::from_be_slice(p, bits / 2).unwrap())
1103 .collect();
1104 let res = RsaPrivateKey::from_components(n, e, d, primes);
1105 assert_eq!(res, Err(Error::InvalidModulus));
1106 }
1107
1108 #[test]
1109 fn reject_oversized_private_key() {
1110 let n = BoxedUint::from_be_slice(
1137 &hex!(
1138 "a909fa3bba5df62a102443b04b6b219c3d9b337f8f68ba2fae8f8e28e13db7b8
1139 f1ae9f9bf57abcd68793eb3379bb9c8f7b06be574f19b0025011b17d0f900c51
1140 990765cfec5bf5c022d0bc0a88d0847a0241f8ce5d9a4e3661ac4319d224d830
1141 2d5e530d52940296d020fcc89bdc83c0ebe5d725c8ca969120d1f3b61cf7eb2b
1142 0799a1e5355659438d011d590e89477ec2ced6f54f6f1cdd1071a4870bc94750
1143 4a9bfc8c9bd054a666cfaa6e6e0d5f2688f74a25a0015fb4e9edf1515b1df4ff
1144 4d74b45703327ac73116cbaf72e4eb5f1f0461cf53b894e15b6db004014e2ba4
1145 a97ed82d67a8b8589aa4d05f09ad3c19dd3ca1ccab0f4707bc29e366b66a98a1
1146 a1a23e3f6550e73ddbc4333b24c44d577ca55ed4a6768e7bd4385872f44269d7
1147 9fad690aee2aa682ee2bc8c1f883bbc627d16478f73cc7ec8c9bab678305e7b2
1148 e0a52ac8eb47a460d875a3a5625ce0c742ecc6c734da1779ffec62130c14170d
1149 14e51ae407efb87293116a3dc951188d30c4408f29ab31a738e189a4ee6bd7a2
1150 a4a79d5c1fa8e57172a2c9c3b7f5f8620ab18ffab6ff5f0b3ee42014ba96473b
1151 077784dd550ca2abdc429b32281948c03f3d50f1c8c85d1a549e9dab6508c448
1152 22de4e37b0ac635b8d2303521745e4cd8e0519a7ed0f171c7094c53f5f63f059
1153 7b275e139e0abc47449289b191b5e884728499b59e11d869efc874e3fc56dfae
1154 29d4dbbd638f70ee0b4efbd9e6c0a729349ab7d8ce906f4776750df0274a0823
1155 d9a5fa7fc34e76be208c306c8f14385108e0a650cd96aa98dbf74f31a6a67a1c
1156 1caede33212d014790654206acf9ab1501262999fdae482bff61f0f13db4abb7
1157 b4944eb922cebdbd33f6c179b5ec1e7328562c91ae358c9a19ea32296cc3adb9
1158 53d95774a8198337f59e00c7725a1991342ff750ea524985d154002148417c0d
1159 5aacddeecae7bdbca6e212eaa0fb8c863914b5372fe98383124ecb07614b0dcc
1160 a6987ff308bdf0e154a2e3e1f2659d7780cec2cfc5a6917e07fa378bd3e25a43
1161 21b50b3a95fc703bf2f52926ffdb6ff275f97d62ff51e5b4b7938ed798e2b061
1162 553d5cc41a1504641a0b08a7740b3e163729fbc7002beff7a4c42086792b187c
1163 ebc7d6086283865ece2f4083069e061a4daeda5c069fb787d68e0e047928ddad
1164 9c2aaab3cdb94704ba77853fd44f7df8fc7f7be486a0858285417d533ba27b6e
1165 d9dda746efe18409204f5dd473af0974cda2981bc7028e830d4b7a9ac58200c3
1166 8011762e3bb680fa7dde7adb6706ab440a8400a0225d08709e6e32299683015c
1167 c2d7cac786b4b2bd6ab238f210ef7314a57fbff5964041e8b80d426409efddb9
1168 4c38a989840867addfe1de59d890a95b4bd4930ceb1f888f6f6872f9305048ec
1169 3592f8cbc86fe51d68f30d06bad31c555bdbb9f43c50b9e1ec34430750e443d6
1170 8157bc52defc0965"
1171 ),
1172 8256,
1173 )
1174 .unwrap();
1175
1176 let e = BoxedUint::from(65_537u64);
1177
1178 assert_eq!(
1179 RsaPublicKey::new(n, e).err().unwrap(),
1180 Error::ModulusTooLarge
1181 );
1182 }
1183
1184 #[test]
1185 #[cfg(feature = "encoding")]
1186 fn build_key_from_primes() {
1187 const RSA_2048_PRIV_DER: &[u8] = include_bytes!("../tests/examples/pkcs8/rsa2048-priv.der");
1188 let ref_key = RsaPrivateKey::from_pkcs8_der(RSA_2048_PRIV_DER).unwrap();
1189 assert_eq!(ref_key.validate(), Ok(()));
1190
1191 let primes = PrivateKeyParts::primes(&ref_key).to_vec();
1192
1193 let exp = PublicKeyParts::e(&ref_key);
1194 let key = RsaPrivateKey::from_primes(primes, exp.clone())
1195 .expect("failed to import key from primes");
1196 assert_eq!(key.validate(), Ok(()));
1197
1198 assert_eq!(PublicKeyParts::n(&key), PublicKeyParts::n(&ref_key));
1199
1200 assert_eq!(PrivateKeyParts::dp(&key), PrivateKeyParts::dp(&ref_key));
1201 assert_eq!(PrivateKeyParts::dq(&key), PrivateKeyParts::dq(&ref_key));
1202
1203 assert_eq!(PrivateKeyParts::d(&key), PrivateKeyParts::d(&ref_key));
1204 }
1205
1206 #[test]
1207 #[cfg(feature = "encoding")]
1208 fn build_key_from_p_q() {
1209 const RSA_2048_SP800_PRIV_DER: &[u8] =
1210 include_bytes!("../tests/examples/pkcs8/rsa2048-sp800-56b-priv.der");
1211 let ref_key = RsaPrivateKey::from_pkcs8_der(RSA_2048_SP800_PRIV_DER).unwrap();
1212 assert_eq!(ref_key.validate(), Ok(()));
1213
1214 let primes = PrivateKeyParts::primes(&ref_key).to_vec();
1215 let exp = PublicKeyParts::e(&ref_key);
1216
1217 let key = RsaPrivateKey::from_p_q(primes[0].clone(), primes[1].clone(), exp.clone())
1218 .expect("failed to import key from primes");
1219 assert_eq!(key.validate(), Ok(()));
1220
1221 assert_eq!(PublicKeyParts::n(&key), PublicKeyParts::n(&ref_key));
1222
1223 assert_eq!(PrivateKeyParts::dp(&key), PrivateKeyParts::dp(&ref_key));
1224 assert_eq!(PrivateKeyParts::dq(&key), PrivateKeyParts::dq(&ref_key));
1225
1226 assert_eq!(PrivateKeyParts::d(&key), PrivateKeyParts::d(&ref_key));
1227 }
1228
1229 #[test]
1230 #[cfg(feature = "hazmat")]
1231 fn test_from_components_with_large_exponent() {
1232 use rand::rngs::ChaCha8Rng;
1236 use rand_core::SeedableRng;
1237
1238 let mut rng = ChaCha8Rng::from_seed([42; 32]);
1239
1240 let large_e = BoxedUint::from((1u64 << 34) + 1); let components =
1245 generate_multi_prime_key_with_exp(&mut rng, 2, 1024, large_e.clone()).unwrap();
1246
1247 let n = components.n.get().clone();
1249 let d = components.d;
1250 let primes = components.primes;
1251
1252 let result =
1254 RsaPrivateKey::from_components(n.clone(), large_e.clone(), d.clone(), primes.clone());
1255 assert!(result.is_err());
1256 assert_eq!(result.unwrap_err(), Error::PublicExponentTooLarge);
1257
1258 let key_with_large_exp = RsaPrivateKey::from_components_with_large_exponent(
1260 n.clone(),
1261 large_e.clone(),
1262 d.clone(),
1263 primes.clone(),
1264 );
1265 assert!(key_with_large_exp.is_ok());
1266
1267 let key_with_large_exp = key_with_large_exp.unwrap();
1268 assert_eq!(PublicKeyParts::e(&key_with_large_exp), &large_e);
1269 assert_eq!(PublicKeyParts::n(&key_with_large_exp).as_ref(), &n);
1270 assert_eq!(PrivateKeyParts::d(&key_with_large_exp), &d);
1271
1272 assert!(validate_skip_exponent_size(&key_with_large_exp).is_ok());
1275 }
1276
1277 #[test]
1278 #[cfg(feature = "hazmat")]
1279 fn test_from_components_with_small_exponent() {
1280 use rand::rngs::ChaCha8Rng;
1284 use rand_core::SeedableRng;
1285
1286 let mut rng = ChaCha8Rng::from_seed([43; 32]);
1287
1288 let small_e = BoxedUint::from(1u64); let components =
1293 generate_multi_prime_key_with_exp(&mut rng, 2, 1024, small_e.clone()).unwrap();
1294
1295 let n = components.n.get().clone();
1297 let d = components.d;
1298 let primes = components.primes;
1299
1300 let result =
1302 RsaPrivateKey::from_components(n.clone(), small_e.clone(), d.clone(), primes.clone());
1303 assert!(result.is_err());
1304
1305 let key_with_small_exp = RsaPrivateKey::from_components_with_large_exponent(
1307 n.clone(),
1308 small_e.clone(),
1309 d.clone(),
1310 primes,
1311 );
1312 assert!(key_with_small_exp.is_ok());
1313
1314 let key_with_small_exp = key_with_small_exp.unwrap();
1315 assert_eq!(PublicKeyParts::e(&key_with_small_exp), &small_e);
1316
1317 assert!(validate_skip_exponent_size(&key_with_small_exp).is_ok());
1319 }
1320
1321 #[test]
1333 #[cfg(feature = "hazmat")]
1334 fn test_key_invalid_primes() {
1335 let e = RsaPrivateKey::from_components_with_large_exponent(
1336 BoxedUint::from(239u64),
1337 BoxedUint::from(185u64),
1338 BoxedUint::from(0u64),
1339 vec![BoxedUint::from(1u64), BoxedUint::from(239u64)],
1340 )
1341 .unwrap_err();
1342 assert_eq!(e, Error::InvalidPrime);
1343 }
1344}