1#[cfg(feature = "alloc")]
2use alloc::vec::Vec;
3use core::cmp::Ordering;
4use core::fmt;
5use core::hash::{Hash, Hasher};
6
7#[cfg(feature = "alloc")]
8use crypto_bigint::Resize as _;
9#[cfg(feature = "alloc")]
10use crypto_bigint::{
11 modular::{BoxedMontyForm, BoxedMontyParams},
12 BoxedUint, ConcatenatingMul, Integer,
13};
14#[cfg(feature = "alloc")]
15use crypto_bigint::{NonZero as CryptoNonZero, Odd as CryptoOdd};
16
17use rand_core::CryptoRng;
18use zeroize::{Zeroize, ZeroizeOnDrop};
19#[cfg(feature = "serde")]
20use {
21 pkcs8::{DecodePrivateKey, EncodePrivateKey},
22 serdect::serde::{de, ser, Deserialize, Serialize},
23 spki::{DecodePublicKey, EncodePublicKey},
24};
25
26#[cfg(feature = "keygen")]
27use crate::algorithms::generate::generate_multi_prime_key_with_exp;
28#[cfg(feature = "alloc")]
29use crate::algorithms::rsa::{
30 compute_modulus, compute_private_exponent_carmicheal, compute_private_exponent_euler_totient,
31 recover_primes,
32};
33
34#[cfg(feature = "alloc")]
35use crate::dummy_rng::DummyRng;
36use crate::errors::{Error, Result};
37use crate::traits::keys::PublicKeyParts;
38use crate::traits::keys::{PrivateKeyParts, RawPrivateKeyConstructible};
39use crate::traits::{
40 modular::ModulusParams, NonZero, PaddingScheme, SignatureScheme, UnsignedModularInt,
41};
42
43#[derive(Debug, Clone)]
45pub struct GenericRsaPublicKey<T, M>
46where
47 T: UnsignedModularInt,
48 M: ModulusParams<Modulus = T>,
49{
50 n: NonZero<T>,
52 e: T,
57
58 n_params: M,
59}
60
61#[cfg(feature = "alloc")]
64pub type RsaPublicKey = GenericRsaPublicKey<BoxedUint, BoxedMontyParams>;
65
66impl<T, M> Eq for GenericRsaPublicKey<T, M>
67where
68 T: UnsignedModularInt + Eq,
69 M: ModulusParams<Modulus = T>,
70{
71}
72
73impl<T, M> PartialEq for GenericRsaPublicKey<T, M>
74where
75 T: UnsignedModularInt + PartialEq,
76 M: ModulusParams<Modulus = T>,
77{
78 #[inline]
79 fn eq(&self, other: &GenericRsaPublicKey<T, M>) -> bool {
80 self.n == other.n && self.e == other.e
81 }
82}
83
84impl<T, M> Hash for GenericRsaPublicKey<T, M>
85where
86 T: UnsignedModularInt,
87 M: ModulusParams<Modulus = T>,
88{
89 fn hash<H: Hasher>(&self, state: &mut H) {
90 state.write(b"RsaPublicKey");
92 state.write(self.n.as_ref().to_be_bytes().as_ref());
94 state.write(self.e.to_be_bytes().as_ref());
95 }
96}
97
98pub struct GenericRsaPrivateKey<T, M>
104where
105 T: UnsignedModularInt + Zeroize,
106 M: ModulusParams<Modulus = T>,
107{
108 pubkey_components: GenericRsaPublicKey<T, M>,
110 d: T,
112 #[cfg(feature = "alloc")]
115 pub(crate) primes: alloc::vec::Vec<T>,
116 #[cfg(feature = "alloc")]
118 pub(crate) precomputed: Option<PrecomputedValues<T, M>>,
119}
120
121#[cfg(feature = "alloc")]
126impl<T, M> Clone for GenericRsaPrivateKey<T, M>
127where
128 T: UnsignedModularInt + Zeroize + Clone,
129 M: ModulusParams<Modulus = T> + Clone,
130 M::MontgomeryForm: Clone,
131{
132 fn clone(&self) -> Self {
133 Self {
134 pubkey_components: self.pubkey_components.clone(),
135 d: self.d.clone(),
136 primes: self.primes.clone(),
137 precomputed: self.precomputed.clone(),
138 }
139 }
140}
141
142#[cfg(not(feature = "alloc"))]
143impl<T, M> Clone for GenericRsaPrivateKey<T, M>
144where
145 T: UnsignedModularInt + Zeroize + Clone,
146 M: ModulusParams<Modulus = T> + Clone,
147{
148 fn clone(&self) -> Self {
149 Self {
150 pubkey_components: self.pubkey_components.clone(),
151 d: self.d.clone(),
152 }
153 }
154}
155
156impl<T, M> fmt::Debug for GenericRsaPrivateKey<T, M>
158where
159 T: UnsignedModularInt + Zeroize,
160 M: ModulusParams<Modulus = T>,
161 GenericRsaPublicKey<T, M>: fmt::Debug,
162{
163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164 f.debug_struct("GenericRsaPrivateKey")
165 .field("pubkey_components", &self.pubkey_components)
166 .field("d", &"...")
167 .finish()
168 }
169}
170
171impl<T, M> GenericRsaPrivateKey<T, M>
177where
178 T: UnsignedModularInt + Zeroize + RawPrivateKeyConstructible,
179 M: ModulusParams<Modulus = T>,
180{
181 pub fn from_public_and_d(pubkey_components: GenericRsaPublicKey<T, M>, d: T) -> Self {
186 Self {
187 pubkey_components,
188 d,
189 #[cfg(feature = "alloc")]
190 primes: alloc::vec::Vec::new(),
191 #[cfg(feature = "alloc")]
192 precomputed: None,
193 }
194 }
195}
196
197impl<T, M> GenericRsaPrivateKey<T, M>
198where
199 T: UnsignedModularInt + Zeroize,
200 M: ModulusParams<Modulus = T>,
201{
202 pub fn as_public(&self) -> &GenericRsaPublicKey<T, M> {
204 &self.pubkey_components
205 }
206}
207
208impl<T, M> PublicKeyParts<T> for GenericRsaPrivateKey<T, M>
209where
210 T: UnsignedModularInt + Zeroize,
211 M: ModulusParams<Modulus = T>,
212{
213 type MontyParams = M;
214
215 fn n(&self) -> &NonZero<T> {
216 self.pubkey_components.n()
217 }
218
219 fn e(&self) -> &T {
220 self.pubkey_components.e()
221 }
222
223 fn n_params(&self) -> &Self::MontyParams {
224 self.pubkey_components.n_params()
225 }
226}
227
228impl<T, M> PrivateKeyParts<T> for GenericRsaPrivateKey<T, M>
229where
230 T: UnsignedModularInt + Zeroize,
231 M: ModulusParams<Modulus = T>,
232{
233 fn d(&self) -> &T {
234 &self.d
235 }
236
237 #[cfg(feature = "alloc")]
238 fn primes(&self) -> &[T] {
239 &self.primes
240 }
241
242 #[cfg(feature = "alloc")]
243 fn dp(&self) -> Option<&T> {
244 self.precomputed.as_ref().map(|p| &p.dp)
245 }
246
247 #[cfg(feature = "alloc")]
248 fn dq(&self) -> Option<&T> {
249 self.precomputed.as_ref().map(|p| &p.dq)
250 }
251
252 #[cfg(feature = "alloc")]
253 fn qinv(&self) -> Option<&<Self::MontyParams as ModulusParams>::MontgomeryForm> {
254 self.precomputed.as_ref().map(|p| &p.qinv)
255 }
256
257 #[cfg(feature = "alloc")]
258 fn p_params(&self) -> Option<&Self::MontyParams> {
259 self.precomputed.as_ref().map(|p| &p.p_params)
260 }
261
262 #[cfg(feature = "alloc")]
263 fn q_params(&self) -> Option<&Self::MontyParams> {
264 self.precomputed.as_ref().map(|p| &p.q_params)
265 }
266}
267
268impl<T, M> Zeroize for GenericRsaPrivateKey<T, M>
271where
272 T: UnsignedModularInt + Zeroize,
273 M: ModulusParams<Modulus = T>,
274{
275 fn zeroize(&mut self) {
276 self.d.zeroize();
277 #[cfg(feature = "alloc")]
278 self.primes.zeroize();
279 #[cfg(feature = "alloc")]
280 self.precomputed.zeroize();
281 }
282}
283
284impl<T, M> Drop for GenericRsaPrivateKey<T, M>
285where
286 T: UnsignedModularInt + Zeroize,
287 M: ModulusParams<Modulus = T>,
288{
289 fn drop(&mut self) {
290 self.zeroize();
291 }
292}
293
294impl<T, M> ZeroizeOnDrop for GenericRsaPrivateKey<T, M>
295where
296 T: UnsignedModularInt + Zeroize,
297 M: ModulusParams<Modulus = T>,
298{
299}
300
301#[cfg(feature = "alloc")]
313pub type RsaPrivateKey = GenericRsaPrivateKey<BoxedUint, BoxedMontyParams>;
314
315#[cfg(feature = "alloc")]
316impl Eq for RsaPrivateKey {}
317#[cfg(feature = "alloc")]
318impl PartialEq for RsaPrivateKey {
319 #[inline]
320 fn eq(&self, other: &RsaPrivateKey) -> bool {
321 self.pubkey_components == other.pubkey_components
322 && self.d == other.d
323 && self.primes == other.primes
324 }
325}
326
327#[cfg(feature = "alloc")]
328impl AsRef<RsaPublicKey> for RsaPrivateKey {
329 fn as_ref(&self) -> &RsaPublicKey {
330 &self.pubkey_components
331 }
332}
333
334#[cfg(feature = "alloc")]
335impl Hash for RsaPrivateKey {
336 fn hash<H: Hasher>(&self, state: &mut H) {
337 state.write(b"RsaPrivateKey");
339 Hash::hash(&self.pubkey_components, state);
340 }
341}
342
343#[cfg(feature = "alloc")]
344pub(crate) struct PrecomputedValues<T, M>
345where
346 T: UnsignedModularInt,
347 M: ModulusParams<Modulus = T>,
348{
349 pub(crate) dp: T,
351 pub(crate) dq: T,
353 pub(crate) qinv: M::MontgomeryForm,
355
356 pub(crate) p_params: M,
358 pub(crate) q_params: M,
360}
361
362#[cfg(feature = "alloc")]
365impl<T, M> Clone for PrecomputedValues<T, M>
366where
367 T: UnsignedModularInt + Clone,
368 M: ModulusParams<Modulus = T> + Clone,
369 M::MontgomeryForm: Clone,
370{
371 fn clone(&self) -> Self {
372 Self {
373 dp: self.dp.clone(),
374 dq: self.dq.clone(),
375 qinv: self.qinv.clone(),
376 p_params: self.p_params.clone(),
377 q_params: self.q_params.clone(),
378 }
379 }
380}
381
382#[cfg(feature = "alloc")]
383impl<T, M> ZeroizeOnDrop for PrecomputedValues<T, M>
384where
385 T: UnsignedModularInt,
386 M: ModulusParams<Modulus = T>,
387{
388}
389
390#[cfg(feature = "alloc")]
391impl<T, M> Zeroize for PrecomputedValues<T, M>
392where
393 T: UnsignedModularInt + Zeroize,
394 M: ModulusParams<Modulus = T>,
395{
396 fn zeroize(&mut self) {
397 self.dp.zeroize();
398 self.dq.zeroize();
399 }
406}
407
408#[cfg(feature = "alloc")]
412impl<T, M> Drop for PrecomputedValues<T, M>
413where
414 T: UnsignedModularInt,
415 M: ModulusParams<Modulus = T>,
416{
417 fn drop(&mut self) {
418 self.zeroize();
419 }
420}
421
422#[cfg(feature = "alloc")]
423impl From<RsaPrivateKey> for GenericRsaPublicKey<BoxedUint, BoxedMontyParams> {
424 fn from(private_key: RsaPrivateKey) -> Self {
425 (&private_key).into()
426 }
427}
428
429#[cfg(feature = "alloc")]
430impl From<&RsaPrivateKey> for GenericRsaPublicKey<BoxedUint, BoxedMontyParams> {
431 fn from(private_key: &RsaPrivateKey) -> Self {
432 let public_key: &dyn PublicKeyParts<BoxedUint, MontyParams = BoxedMontyParams> =
433 private_key;
434 GenericRsaPublicKey {
435 n: public_key.n().clone(),
436 e: public_key.e().clone(),
437 n_params: public_key.n_params().clone(),
438 }
439 }
440}
441
442impl<T, M> PublicKeyParts<T> for GenericRsaPublicKey<T, M>
443where
444 T: UnsignedModularInt,
445 M: ModulusParams<Modulus = T>,
446{
447 type MontyParams = M;
448
449 fn n(&self) -> &NonZero<T> {
450 &self.n
451 }
452
453 fn e(&self) -> &T {
454 &self.e
455 }
456
457 fn n_params(&self) -> &M {
458 &self.n_params
459 }
460}
461
462impl<T, M> GenericRsaPublicKey<T, M>
463where
464 T: UnsignedModularInt,
465 M: ModulusParams<Modulus = T>,
466{
467 pub fn from_components(n: T, e: T, n_params: M) -> Result<Self> {
472 let n = NonZero::new(n).ok_or(Error::InvalidModulus)?;
473 Ok(Self { n, e, n_params })
474 }
475}
476
477impl<T, M> GenericRsaPublicKey<T, M>
478where
479 T: UnsignedModularInt,
480 M: ModulusParams<Modulus = T>,
481{
482 #[cfg(feature = "alloc")]
484 pub fn encrypt<R: CryptoRng + ?Sized, P: PaddingScheme>(
485 &self,
486 rng: &mut R,
487 padding: P,
488 msg: &[u8],
489 ) -> Result<Vec<u8>>
490 where
491 M: crate::traits::modular::CtModulusParams,
492 {
493 padding.encrypt(rng, self, msg)
494 }
495
496 pub fn verify<S: SignatureScheme>(&self, scheme: S, hashed: &[u8], sig: &[u8]) -> Result<()> {
503 scheme.verify(self, hashed, sig)
504 }
505}
506
507#[cfg(feature = "alloc")]
508impl GenericRsaPublicKey<BoxedUint, BoxedMontyParams> {
509 pub const MIN_PUB_EXPONENT: u64 = 2;
511
512 pub const MAX_PUB_EXPONENT: u64 = (1 << 33) - 1;
529
530 pub const MAX_SIZE: usize = 8192;
532
533 pub fn new(n: BoxedUint, e: BoxedUint) -> Result<Self> {
538 Self::new_with_max_size(n, e, Self::MAX_SIZE)
539 }
540
541 pub fn new_with_max_size(n: BoxedUint, e: BoxedUint, max_size: usize) -> Result<Self> {
543 check_public_with_max_size(&n, &e, Some(max_size))?;
544
545 let n_odd = CryptoOdd::new(n.clone())
546 .into_option()
547 .ok_or(Error::InvalidModulus)?;
548 let n_params = BoxedMontyParams::new(n_odd);
549 let n = NonZero::new(n).expect("checked above");
550
551 Ok(Self { n, e, n_params })
552 }
553
554 pub fn new_unchecked(n: BoxedUint, e: BoxedUint) -> Self {
561 let n_odd = CryptoOdd::new(n.clone()).expect("n must be odd");
562 let n_params = BoxedMontyParams::new(n_odd);
563 let n = NonZero::new(n).expect("odd numbers are non zero");
564
565 Self { n, e, n_params }
566 }
567}
568
569#[cfg(feature = "alloc")]
570impl GenericRsaPrivateKey<BoxedUint, BoxedMontyParams> {
571 const EXP: u64 = 65537;
573
574 const MIN_SIZE: u32 = 1024;
576
577 #[cfg(feature = "keygen")]
582 pub fn new<R: CryptoRng + ?Sized>(rng: &mut R, bit_size: usize) -> Result<Self> {
583 Self::new_with_exp(rng, bit_size, Self::EXP.into())
584 }
585
586 #[cfg(all(feature = "hazmat", feature = "keygen"))]
592 pub fn new_unchecked<R: CryptoRng + ?Sized>(rng: &mut R, bit_size: usize) -> Result<Self> {
593 Self::new_with_exp_unchecked(rng, bit_size, Self::EXP.into())
594 }
595
596 #[cfg(feature = "keygen")]
601 pub fn new_with_exp<R: CryptoRng + ?Sized>(
602 rng: &mut R,
603 bit_size: usize,
604 exp: BoxedUint,
605 ) -> Result<RsaPrivateKey> {
606 if bit_size < Self::MIN_SIZE as usize {
607 return Err(Error::ModulusTooSmall);
608 }
609
610 let components = generate_multi_prime_key_with_exp(rng, 2, bit_size, exp)?;
611 RsaPrivateKey::from_components(
612 components.n.get(),
613 components.e,
614 components.d,
615 components.primes,
616 )
617 }
618
619 #[cfg(all(feature = "hazmat", feature = "keygen"))]
628 pub fn new_with_exp_unchecked<R: CryptoRng + ?Sized>(
629 rng: &mut R,
630 bit_size: usize,
631 exp: BoxedUint,
632 ) -> Result<RsaPrivateKey> {
633 let components = generate_multi_prime_key_with_exp(rng, 2, bit_size, exp)?;
634 RsaPrivateKey::from_components(
635 components.n.get(),
636 components.e,
637 components.d,
638 components.primes,
639 )
640 }
641
642 fn from_components_inner(
652 n: BoxedUint,
653 e: BoxedUint,
654 d: BoxedUint,
655 mut primes: Vec<BoxedUint>,
656 ) -> Result<RsaPrivateKey> {
657 let n = CryptoOdd::new(n)
658 .into_option()
659 .ok_or(Error::InvalidModulus)?;
660
661 let n_bits = n.bits_vartime();
664 let n = n.resize_unchecked(n_bits);
665
666 let n_params = BoxedMontyParams::new(n.clone());
667 let n_c = NonZero::new(n.get()).ok_or(Error::InvalidModulus)?;
668
669 match primes.len() {
670 0 => {
671 let n_for_recovery =
674 CryptoNonZero::new(n_c.as_ref().clone()).expect("modulus is non-zero");
675 let (p, q) = recover_primes(&n_for_recovery, &e, &d)?;
676 primes.push(p);
677 primes.push(q);
678 }
679 1 => return Err(Error::NprimesTooSmall),
680 _ => {
681 if primes
685 .iter()
686 .fold(BoxedUint::one(), |acc, p| acc.concatenating_mul(&p))
687 != n_c.as_ref()
688 {
689 return Err(Error::InvalidModulus);
690 }
691 }
692 }
693
694 let primes = primes
696 .into_iter()
697 .map(|p| {
698 let p_bits = p.bits();
699 p.resize_unchecked(p_bits)
700 })
701 .collect();
702
703 let k = RsaPrivateKey {
704 pubkey_components: RsaPublicKey {
705 n: n_c,
706 e,
707 n_params,
708 },
709 d,
710 primes,
711 precomputed: None,
712 };
713
714 Ok(k)
715 }
716
717 #[cfg(all(feature = "hazmat", feature = "alloc"))]
735 pub fn from_components_with_large_exponent(
736 n: BoxedUint,
737 e: BoxedUint,
738 d: BoxedUint,
739 primes: Vec<BoxedUint>,
740 ) -> Result<RsaPrivateKey> {
741 let mut k = Self::from_components_inner(n, e, d, primes)?;
742
743 validate_skip_exponent_size(&k)?;
745
746 k.precompute().ok();
748
749 Ok(k)
750 }
751
752 pub fn from_components(
766 n: BoxedUint,
767 e: BoxedUint,
768 d: BoxedUint,
769 primes: Vec<BoxedUint>,
770 ) -> Result<RsaPrivateKey> {
771 let mut k = Self::from_components_inner(n, e, d, primes)?;
772
773 k.validate()?;
775
776 k.precompute().ok();
778
779 Ok(k)
780 }
781
782 pub fn from_p_q(
789 p: BoxedUint,
790 q: BoxedUint,
791 public_exponent: BoxedUint,
792 ) -> Result<RsaPrivateKey> {
793 if p == q {
794 return Err(Error::InvalidPrime);
795 }
796
797 let d = compute_private_exponent_carmicheal(&p, &q, &public_exponent)?;
798 let primes = vec![p, q];
799 let n = compute_modulus(&primes);
800
801 Self::from_components(n.get(), public_exponent, d, primes)
802 }
803
804 pub fn from_primes(
808 primes: Vec<BoxedUint>,
809 public_exponent: BoxedUint,
810 ) -> Result<RsaPrivateKey> {
811 if primes.len() < 2 {
812 return Err(Error::NprimesTooSmall);
813 }
814
815 for (i, prime1) in primes.iter().enumerate() {
817 for prime2 in primes.iter().take(i) {
818 if prime1 == prime2 {
819 return Err(Error::InvalidPrime);
820 }
821 }
822 }
823
824 let n = compute_modulus(&primes);
825 let d = compute_private_exponent_euler_totient(&primes, &public_exponent)?;
826
827 Self::from_components(n.get(), public_exponent, d, primes)
828 }
829
830 pub fn as_public_key(&self) -> &RsaPublicKey {
834 &self.pubkey_components
835 }
836
837 pub fn to_public_key(&self) -> RsaPublicKey {
842 self.pubkey_components.clone()
843 }
844
845 pub fn precompute(&mut self) -> Result<()> {
847 if self.precomputed.is_some() {
848 return Ok(());
849 }
850
851 let d = &self.d;
852 let p = self.primes[0].clone();
853 let q = self.primes[1].clone();
854
855 let p_odd = CryptoOdd::new(p.clone())
856 .into_option()
857 .ok_or(Error::InvalidPrime)?;
858 let p_params = BoxedMontyParams::new(p_odd);
859 let q_odd = CryptoOdd::new(q.clone())
860 .into_option()
861 .ok_or(Error::InvalidPrime)?;
862 let q_params = BoxedMontyParams::new(q_odd);
863
864 let x = CryptoNonZero::new(p.wrapping_sub(BoxedUint::one()))
865 .into_option()
866 .ok_or(Error::InvalidPrime)?;
867 let dp = d.rem_vartime(&x);
868
869 let x = CryptoNonZero::new(q.wrapping_sub(BoxedUint::one()))
870 .into_option()
871 .ok_or(Error::InvalidPrime)?;
872 let dq = d.rem_vartime(&x);
873
874 let q_mod_p = match p.bits_precision().cmp(&q.bits_precision()) {
877 Ordering::Less => {
878 let p_wide = CryptoNonZero::new(p.clone())
879 .expect("`p` is non-zero")
880 .resize_unchecked(q.bits_precision());
881 (&q % p_wide).resize_unchecked(p.bits_precision())
882 }
883 Ordering::Greater => {
884 (&q).resize_unchecked(p.bits_precision())
885 % &CryptoNonZero::new(p.clone()).expect("`p` is non-zero")
886 }
887 Ordering::Equal => &q % CryptoNonZero::new(p.clone()).expect("`p` is non-zero"),
888 };
889
890 let q_mod_p = BoxedMontyForm::new(q_mod_p, &p_params);
891 let qinv = q_mod_p.invert().into_option().ok_or(Error::InvalidPrime)?;
892
893 debug_assert_eq!(dp.bits_precision(), p.bits_precision());
894 debug_assert_eq!(dq.bits_precision(), q.bits_precision());
895 debug_assert_eq!(qinv.bits_precision(), p.bits_precision());
896 debug_assert_eq!(p_params.bits_precision(), p.bits_precision());
897 debug_assert_eq!(q_params.bits_precision(), q.bits_precision());
898
899 self.precomputed = Some(PrecomputedValues {
900 dp,
901 dq,
902 qinv,
903 p_params,
904 q_params,
905 });
906
907 Ok(())
908 }
909
910 pub fn clear_precomputed(&mut self) {
912 self.precomputed = None;
913 }
914
915 pub fn crt_coefficient(&self) -> Option<BoxedUint> {
917 let p = &self.primes[0];
918 let q = &self.primes[1];
919 Option::from(q.invert_mod(&CryptoNonZero::new(p.clone()).expect("prime")))
921 }
922
923 pub fn validate(&self) -> Result<()> {
926 check_public(self)?;
927 validate_private_key_parts(self)?;
928 Ok(())
929 }
930
931 pub fn decrypt<P: PaddingScheme>(&self, padding: P, ciphertext: &[u8]) -> Result<Vec<u8>> {
933 padding.decrypt(Option::<&mut DummyRng>::None, self, ciphertext)
934 }
935
936 pub fn decrypt_blinded<R: CryptoRng + ?Sized, P: PaddingScheme>(
940 &self,
941 rng: &mut R,
942 padding: P,
943 ciphertext: &[u8],
944 ) -> Result<Vec<u8>> {
945 padding.decrypt(Some(rng), self, ciphertext)
946 }
947
948 pub fn sign<S: SignatureScheme>(&self, padding: S, digest_in: &[u8]) -> Result<Vec<u8>> {
950 padding.sign(Option::<&mut DummyRng>::None, self, digest_in)
951 }
952
953 pub fn sign_with_rng<R: CryptoRng + ?Sized, S: SignatureScheme>(
964 &self,
965 rng: &mut R,
966 padding: S,
967 digest_in: &[u8],
968 ) -> Result<Vec<u8>> {
969 padding.sign(Some(rng), self, digest_in)
970 }
971}
972
973#[inline]
975#[cfg(feature = "alloc")]
976pub fn check_public(public_key: &impl PublicKeyParts<BoxedUint>) -> Result<()> {
977 check_public_with_max_size(public_key.n().as_ref(), public_key.e(), None)
978}
979
980#[inline]
982#[cfg(feature = "alloc")]
983fn check_public_with_max_size(n: &BoxedUint, e: &BoxedUint, max_size: Option<usize>) -> Result<()> {
984 if let Some(max_size) = max_size {
985 if n.bits_vartime() as usize > max_size {
986 return Err(Error::ModulusTooLarge);
987 }
988 }
989
990 check_public_skip_exponent_size(n, e)?;
991
992 if e < &BoxedUint::from(RsaPublicKey::MIN_PUB_EXPONENT) {
993 return Err(Error::PublicExponentTooSmall);
994 }
995
996 if e > &BoxedUint::from(RsaPublicKey::MAX_PUB_EXPONENT) {
997 return Err(Error::PublicExponentTooLarge);
998 }
999
1000 Ok(())
1001}
1002
1003#[inline]
1007#[cfg(feature = "alloc")]
1008fn check_public_skip_exponent_size(n: &BoxedUint, e: &BoxedUint) -> Result<()> {
1009 if e >= n || n.is_even().into() || n.is_zero().into() {
1010 return Err(Error::InvalidModulus);
1011 }
1012
1013 if e.is_even().into() {
1014 return Err(Error::InvalidExponent);
1015 }
1016
1017 Ok(())
1019}
1020
1021#[cfg(feature = "alloc")]
1026fn validate_private_key_parts(key: &RsaPrivateKey) -> Result<()> {
1027 let mut m = BoxedUint::one_with_precision(key.pubkey_components.n.bits_precision());
1029 let one = BoxedUint::one();
1030 for prime in &key.primes {
1031 if prime <= &one {
1033 return Err(Error::InvalidPrime);
1034 }
1035 m = m.wrapping_mul(prime);
1036 }
1037 if m != *key.pubkey_components.n.as_ref() {
1038 return Err(Error::InvalidModulus);
1039 }
1040
1041 let de = key.d.concatenating_mul(&key.pubkey_components.e);
1047
1048 for prime in &key.primes {
1049 let x = CryptoNonZero::new(prime.wrapping_sub(BoxedUint::one())).unwrap();
1050 let congruence = de.rem_vartime(&x);
1051 if !bool::from(congruence.is_one()) {
1052 return Err(Error::InvalidExponent);
1053 }
1054 }
1055
1056 Ok(())
1057}
1058
1059#[cfg(all(feature = "hazmat", feature = "alloc"))]
1065fn validate_skip_exponent_size(key: &RsaPrivateKey) -> Result<()> {
1066 check_public_skip_exponent_size(key.pubkey_components.n.as_ref(), &key.pubkey_components.e)?;
1068
1069 validate_private_key_parts(key)?;
1071
1072 Ok(())
1073}
1074
1075#[cfg(feature = "serde")]
1076impl Serialize for RsaPublicKey {
1077 fn serialize<S>(&self, serializer: S) -> core::prelude::v1::Result<S::Ok, S::Error>
1078 where
1079 S: serdect::serde::Serializer,
1080 {
1081 let der = self.to_public_key_der().map_err(ser::Error::custom)?;
1082 serdect::slice::serialize_hex_lower_or_bin(&der, serializer)
1083 }
1084}
1085
1086#[cfg(feature = "serde")]
1087impl<'de> Deserialize<'de> for RsaPublicKey {
1088 fn deserialize<D>(deserializer: D) -> core::prelude::v1::Result<Self, D::Error>
1089 where
1090 D: serdect::serde::Deserializer<'de>,
1091 {
1092 let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?;
1093 Self::from_public_key_der(&der_bytes).map_err(de::Error::custom)
1094 }
1095}
1096
1097#[cfg(feature = "serde")]
1098impl Serialize for RsaPrivateKey {
1099 fn serialize<S>(&self, serializer: S) -> core::prelude::v1::Result<S::Ok, S::Error>
1100 where
1101 S: ser::Serializer,
1102 {
1103 let der = self.to_pkcs8_der().map_err(ser::Error::custom)?;
1104 serdect::slice::serialize_hex_lower_or_bin(&der.as_bytes(), serializer)
1105 }
1106}
1107
1108#[cfg(feature = "serde")]
1109impl<'de> Deserialize<'de> for RsaPrivateKey {
1110 fn deserialize<D>(deserializer: D) -> core::prelude::v1::Result<Self, D::Error>
1111 where
1112 D: de::Deserializer<'de>,
1113 {
1114 let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?;
1115 Self::from_pkcs8_der(&der_bytes).map_err(de::Error::custom)
1116 }
1117}
1118
1119#[cfg(test)]
1120#[cfg(feature = "alloc")]
1121mod tests {
1122 use super::*;
1123 use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt};
1124 use crate::traits::{PrivateKeyParts, PublicKeyParts};
1125
1126 use hex_literal::hex;
1127 use rand::rngs::ChaCha8Rng;
1128 use rand_core::SeedableRng;
1129
1130 #[cfg(feature = "encoding")]
1131 use pkcs8::DecodePrivateKey;
1132
1133 #[test]
1134 fn test_from_into() {
1135 let raw_n = BoxedUint::from(101u64);
1136 let n_odd = CryptoOdd::new(raw_n.clone()).unwrap();
1137 let private_key = RsaPrivateKey {
1138 pubkey_components: RsaPublicKey {
1139 n: NonZero::new(raw_n.clone()).unwrap(),
1140 e: BoxedUint::from(200u64),
1141 n_params: BoxedMontyParams::new(n_odd),
1142 },
1143 d: BoxedUint::from(123u64),
1144 primes: vec![],
1145 precomputed: None,
1146 };
1147 let public_key: RsaPublicKey = private_key.into();
1148
1149 let n_limbs: &[u64] = PublicKeyParts::n(&public_key).as_ref().as_ref();
1150 assert_eq!(n_limbs, &[101u64]);
1151 assert_eq!(PublicKeyParts::e(&public_key), &BoxedUint::from(200u64));
1152 assert_eq!(PublicKeyParts::e_bytes(&public_key), [200].into());
1153 assert_eq!(PublicKeyParts::n_bytes(&public_key), [101].into());
1154 }
1155
1156 fn test_key_basics(private_key: &RsaPrivateKey) {
1157 private_key.validate().expect("invalid private key");
1158
1159 assert!(
1160 PrivateKeyParts::d(private_key) < PublicKeyParts::n(private_key).as_ref(),
1161 "private exponent too large"
1162 );
1163
1164 let pub_key: RsaPublicKey = private_key.clone().into();
1165 let m = BoxedUint::from(42u64);
1166 let c = rsa_encrypt(&pub_key, &m).expect("encryption successful");
1167
1168 let m2 = rsa_decrypt_and_check::<ChaCha8Rng>(private_key, None, &c)
1169 .expect("unable to decrypt without blinding");
1170 assert_eq!(m, m2);
1171 let mut rng = ChaCha8Rng::from_seed([42; 32]);
1172 let m3 = rsa_decrypt_and_check(private_key, Some(&mut rng), &c)
1173 .expect("unable to decrypt with blinding");
1174 assert_eq!(m, m3);
1175 }
1176
1177 macro_rules! key_generation {
1178 ($name:ident, $multi:expr, $size:expr) => {
1179 #[cfg(feature = "keygen")]
1180 #[test]
1181 fn $name() {
1182 let mut rng = ChaCha8Rng::from_seed([42; 32]);
1183 let exp = BoxedUint::from(RsaPrivateKey::EXP);
1184
1185 for _ in 0..10 {
1186 let components =
1187 generate_multi_prime_key_with_exp(&mut rng, $multi, $size, exp.clone())
1188 .unwrap();
1189 let private_key = RsaPrivateKey::from_components(
1190 components.n.get(),
1191 components.e,
1192 components.d,
1193 components.primes,
1194 )
1195 .unwrap();
1196 assert_eq!(PublicKeyParts::n(&private_key).bits(), $size);
1197
1198 test_key_basics(&private_key);
1199 }
1200 }
1201 };
1202 }
1203
1204 key_generation!(key_generation_128, 2, 128);
1205 key_generation!(key_generation_1024, 2, 1024);
1206
1207 key_generation!(key_generation_multi_3_256, 3, 256);
1208
1209 key_generation!(key_generation_multi_4_64, 4, 64);
1210
1211 key_generation!(key_generation_multi_5_64, 5, 64);
1212 key_generation!(key_generation_multi_8_576, 8, 576);
1213 key_generation!(key_generation_multi_16_1024, 16, 1024);
1214
1215 #[test]
1216 fn test_negative_decryption_value() {
1217 let bits = 128;
1218 let private_key = RsaPrivateKey::from_components(
1219 BoxedUint::from_le_slice(
1220 &[
1221 99, 192, 208, 179, 0, 220, 7, 29, 49, 151, 75, 107, 75, 73, 200, 180,
1222 ],
1223 bits,
1224 )
1225 .unwrap(),
1226 BoxedUint::from_le_slice(&[1, 0, 1, 0, 0, 0, 0, 0], 64).unwrap(),
1227 BoxedUint::from_le_slice(
1228 &[
1229 81, 163, 254, 144, 171, 159, 144, 42, 244, 133, 51, 249, 28, 12, 63, 65,
1230 ],
1231 bits,
1232 )
1233 .unwrap(),
1234 vec![
1235 BoxedUint::from_le_slice(&[105, 101, 60, 173, 19, 153, 3, 192], bits / 2).unwrap(),
1236 BoxedUint::from_le_slice(&[235, 65, 160, 134, 32, 136, 6, 241], bits / 2).unwrap(),
1237 ],
1238 )
1239 .unwrap();
1240
1241 for _ in 0..1000 {
1242 test_key_basics(&private_key);
1243 }
1244 }
1245
1246 #[test]
1247 #[cfg(all(feature = "hazmat", feature = "serde", feature = "keygen"))]
1248 fn test_serde() {
1249 use rand::rngs::ChaCha8Rng;
1250 use rand_core::SeedableRng;
1251 use serde_test::{assert_tokens, Configure, Token};
1252
1253 let mut rng = ChaCha8Rng::from_seed([42; 32]);
1254 let priv_key = RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");
1255
1256 let priv_tokens = [Token::Str(concat!(
1257 "3056020100300d06092a864886f70d010101050004423040020100020900a",
1258 "b240c3361d02e370203010001020811e54a15259d22f9020500ceff5cf302",
1259 "0500d3a7aaad020500ccaddf17020500cb529d3d020500bb526d6f"
1260 ))];
1261 assert_tokens(&priv_key.clone().readable(), &priv_tokens);
1262
1263 let priv_tokens = [Token::Str(
1264 "3024300d06092a864886f70d01010105000313003010020900ab240c3361d02e370203010001",
1265 )];
1266 assert_tokens(
1267 &RsaPublicKey::from(priv_key.clone()).readable(),
1268 &priv_tokens,
1269 );
1270 }
1271
1272 #[test]
1273 fn invalid_coeff_private_key_regression() {
1274 use base64ct::{Base64, Encoding};
1275
1276 let n = Base64::decode_vec(
1277 "wC8GyQvTCZOK+iiBR5fGQCmzRCTWX9TQ3aRG5gGFk0wB6EFoLMAyEEqeG3gS8xhA\
1278 m2rSWYx9kKufvNat3iWlbSRVqkcbpVAYlj2vTrpqDpJl+6u+zxFYoUEBevlJJkAh\
1279 l8EuCccOA30fVpcfRvXPTtvRd3yFT9E9EwZljtgSI02w7gZwg7VIxaGeajh5Euz6\
1280 ZVQZ+qNRKgXrRC7gPRqVyI6Dt0Jc+Su5KBGNn0QcPDzOahWha1ieaeMkFisZ9mdp\
1281 sJoZ4tw5eicLaUomKzALHXQVt+/rcZSrCd6/7uUo11B/CYBM4UfSpwXaL88J9AE6\
1282 A5++no9hmJzaF2LLp+Qwx4yY3j9TDutxSAjsraxxJOGZ3XyA9nG++Ybt3cxZ5fP7\
1283 ROjxCfROBmVv5dYn0O9OBIqYeCH6QraNpZMadlLNIhyMv8Y+P3r5l/PaK4VJaEi5\
1284 pPosnEPawp0W0yZDzmjk2z1LthaRx0aZVrAjlH0Rb/6goLUQ9qu1xsDtQVVpN4A8\
1285 9ZUmtTWORnnJr0+595eHHxssd2gpzqf4bPjNITdAEuOCCtpvyi4ls23zwuzryUYj\
1286 cUOEnsXNQ+DrZpLKxdtsD/qNV/j1hfeyBoPllC3cV+6bcGOFcVGbjYqb+Kw1b0+j\
1287 L69RSKQqgmS+qYqr8c48nDRxyq3QXhR8qtzUwBFSLVk=",
1288 )
1289 .unwrap();
1290 let e = Base64::decode_vec("AQAB").unwrap();
1291 let d = Base64::decode_vec(
1292 "qQazSQ+FRN7nVK1bRsROMRB8AmsDwLVEHivlz1V3Td2Dr+oW3YUMgxedhztML1Id\
1293 QJPq/ad6qErJ6yRFNySVIjDaxzBTOEoB1eHa1btOnBJWb8rVvvjaorixvJ6Tn3i4\
1294 EuhsvVy9DoR1k4rGj3qSIiFjUVvLRDAbLyhpGgEfsr0Z577yJmTC5E8JLRMOKX8T\
1295 mxsk3jPVpsgd65Hu1s8S/ZmabwuHCf9SkdMeY/1bd/9i7BqqJeeDLE4B5x1xcC3z\
1296 3scqDUTzqGO+vZPhjgprPDRlBamVwgenhr7KwCn8iaLamFinRVwOAag8BeBqOJj7\
1297 lURiOsKQa9FIX1kdFUS1QMQxgtPycLjkbvCJjriqT7zWKsmJ7l8YLs6Wmm9/+QJR\
1298 wNCEVdMTXKfCP1cJjudaiskEQThfUldtgu8gUDNYbQ/Filb2eKfiX4h1TiMxZqUZ\
1299 HVZyb9nShbQoXJ3vj/MGVF0QM8TxhXM8r2Lv9gDYU5t9nQlUMLhs0jVjai48jHAB\
1300 bFNyH3sEcOmJOIwJrCXw1dzG7AotwyaEVUHOmL04TffmwCFfnyrLjbFgnyOeoyII\
1301 BYjcY7QFRm/9nupXMTH5hZ2qrHfCJIp0KK4tNBdQqmnHapFl5l6Le1s4qBS5bEIz\
1302 jitobLvAFm9abPlDGfxmY6mlrMK4+nytwF9Ct7wc1AE=",
1303 )
1304 .unwrap();
1305 let primes = [
1306 Base64::decode_vec(
1307 "9kQWEAzsbzOcdPa+s5wFfw4XDd7bB1q9foZ31b1+TNjGNxbSBCFlDF1q98vwpV6n\
1308 M8bWDh/wtbNoETSQDgpEnYOQ26LWEw6YY1+q1Q2GGEFceYUf+Myk8/vTc8TN6Zw0\
1309 bKZBWy10Qo8h7xk4JpzuI7NcxvjJYTkS9aErFxi3vVH0aiZC0tmfaCqr8a2rJxyV\
1310 wqreRpOjwAWrotMsf2wGsF4ofx5ScoFy5GB5fJkkdOrW1LyTvZAUCX3cstPr19+T\
1311 NC5zZOk7WzZatnCkN5H5WzalWtZuu0oVL205KPOa3R8V2yv5e6fm0v5fTmqSuvjm\
1312 aMJLXCN4QJkmIzojO99ckQ==",
1313 )
1314 .unwrap(),
1315 Base64::decode_vec(
1316 "x8exdMjVA2CiI+Thx7loHtVcevoeE2sZ7btRVAvmBqo+lkHwxb7FHRnWvuj6eJSl\
1317 D2f0T50EewIhhiW3R9BmktCk7hXjbSCnC1u9Oxc1IAUm/7azRqyfCMx43XhLxpD+\
1318 xkBCpWkKDLxGczsRwTuaP3lKS3bSdBrNlGmdblubvVBIq4YZ2vXVlnYtza0cS+dg\
1319 CK7BGTqUsrCUd/ZbIvwcwZkZtpkhj1KQfto9X/0OMurBzAqbkeq1cyRHXHkOfN/q\
1320 bUIIRqr9Ii7Eswf9Vk8xp2O1Nt8nzcYS9PFD12M5eyaeFEkEYfpNMNGuTzp/31oq\
1321 VjbpoCxS6vuWAZyADxhISQ==",
1322 )
1323 .unwrap(),
1324 Base64::decode_vec(
1325 "is7d0LY4HoXszlC2NO7gejkq7XqL4p1W6hZJPYTNx+r37t1CC2n3Vvzg6kNdpRix\
1326 DhIpXVTLjN9O7UO/XuqSumYKJIKoP52eb4Tg+a3hw5Iz2Zsb5lUTNSLgkQSBPAf7\
1327 1LHxbL82JL4g1nBUog8ae60BwnVArThKY4EwlJguGNw09BAU4lwf6csDl/nX2vfV\
1328 wiAloYpeZkHL+L8m+bueGZM5KE2jEz+7ztZCI+T+E5i69rZEYDjx0lfLKlEhQlCW\
1329 3HbCPELqXgNJJkRfi6MP9kXa9lSfnZmoT081RMvqonB/FUa4HOcKyCrw9XZEtnbN\
1330 CIdbitfDVEX+pSSD7596wQ==",
1331 )
1332 .unwrap(),
1333 Base64::decode_vec(
1334 "GPs0injugfycacaeIP5jMa/WX55VEnKLDHom4k6WlfDF4L4gIGoJdekcPEUfxOI5\
1335 faKvHyFwRP1wObkPoRBDM0qZxRfBl4zEtpvjHrd5MibSyJkM8+J0BIKk/nSjbRIG\
1336 eb3hV5O56PvGB3S0dKhCUnuVObiC+ne7izplsD4OTG70l1Yud33UFntyoMxrxGYL\
1337 USqhBMmZfHquJg4NOWOzKNY/K+EcHDLj1Kjvkcgv9Vf7ocsVxvpFdD9uGPceQ6kw\
1338 RDdEl6mb+6FDgWuXVyqR9+904oanEIkbJ7vfkthagLbEf57dyG6nJlqh5FBZWxGI\
1339 R72YGypPuAh7qnnqXXjY2Q==",
1340 )
1341 .unwrap(),
1342 Base64::decode_vec(
1343 "CUWC+hRWOT421kwRllgVjy6FYv6jQUcgDNHeAiYZnf5HjS9iK2ki7v8G5dL/0f+Y\
1344 f+NhE/4q8w4m8go51hACrVpP1p8GJDjiT09+RsOzITsHwl+ceEKoe56ZW6iDHBLl\
1345 rNw5/MtcYhKpjNU9KJ2udm5J/c9iislcjgckrZG2IB8ADgXHMEByZ5DgaMl4AKZ1\
1346 Gx8/q6KftTvmOT5rNTMLi76VN5KWQcDWK/DqXiOiZHM7Nr4dX4me3XeRgABJyNR8\
1347 Fqxj3N1+HrYLe/zs7LOaK0++F9Ul3tLelhrhsvLxei3oCZkF9A/foD3on3luYA+1\
1348 cRcxWpSY3h2J4/22+yo4+Q==",
1349 )
1350 .unwrap(),
1351 ];
1352
1353 let e = BoxedUint::from_be_slice(&e, 64).unwrap();
1354
1355 let bits = 4096;
1356 let n = BoxedUint::from_be_slice(&n, bits).unwrap();
1357 let d = BoxedUint::from_be_slice(&d, bits).unwrap();
1358 let primes = primes
1359 .iter()
1360 .map(|p| BoxedUint::from_be_slice(p, bits / 2).unwrap())
1361 .collect();
1362 let res = RsaPrivateKey::from_components(n, e, d, primes);
1363 assert_eq!(res, Err(Error::InvalidModulus));
1364 }
1365
1366 #[test]
1367 fn reject_oversized_private_key() {
1368 let n = BoxedUint::from_be_slice(
1395 &hex!(
1396 "a909fa3bba5df62a102443b04b6b219c3d9b337f8f68ba2fae8f8e28e13db7b8
1397 f1ae9f9bf57abcd68793eb3379bb9c8f7b06be574f19b0025011b17d0f900c51
1398 990765cfec5bf5c022d0bc0a88d0847a0241f8ce5d9a4e3661ac4319d224d830
1399 2d5e530d52940296d020fcc89bdc83c0ebe5d725c8ca969120d1f3b61cf7eb2b
1400 0799a1e5355659438d011d590e89477ec2ced6f54f6f1cdd1071a4870bc94750
1401 4a9bfc8c9bd054a666cfaa6e6e0d5f2688f74a25a0015fb4e9edf1515b1df4ff
1402 4d74b45703327ac73116cbaf72e4eb5f1f0461cf53b894e15b6db004014e2ba4
1403 a97ed82d67a8b8589aa4d05f09ad3c19dd3ca1ccab0f4707bc29e366b66a98a1
1404 a1a23e3f6550e73ddbc4333b24c44d577ca55ed4a6768e7bd4385872f44269d7
1405 9fad690aee2aa682ee2bc8c1f883bbc627d16478f73cc7ec8c9bab678305e7b2
1406 e0a52ac8eb47a460d875a3a5625ce0c742ecc6c734da1779ffec62130c14170d
1407 14e51ae407efb87293116a3dc951188d30c4408f29ab31a738e189a4ee6bd7a2
1408 a4a79d5c1fa8e57172a2c9c3b7f5f8620ab18ffab6ff5f0b3ee42014ba96473b
1409 077784dd550ca2abdc429b32281948c03f3d50f1c8c85d1a549e9dab6508c448
1410 22de4e37b0ac635b8d2303521745e4cd8e0519a7ed0f171c7094c53f5f63f059
1411 7b275e139e0abc47449289b191b5e884728499b59e11d869efc874e3fc56dfae
1412 29d4dbbd638f70ee0b4efbd9e6c0a729349ab7d8ce906f4776750df0274a0823
1413 d9a5fa7fc34e76be208c306c8f14385108e0a650cd96aa98dbf74f31a6a67a1c
1414 1caede33212d014790654206acf9ab1501262999fdae482bff61f0f13db4abb7
1415 b4944eb922cebdbd33f6c179b5ec1e7328562c91ae358c9a19ea32296cc3adb9
1416 53d95774a8198337f59e00c7725a1991342ff750ea524985d154002148417c0d
1417 5aacddeecae7bdbca6e212eaa0fb8c863914b5372fe98383124ecb07614b0dcc
1418 a6987ff308bdf0e154a2e3e1f2659d7780cec2cfc5a6917e07fa378bd3e25a43
1419 21b50b3a95fc703bf2f52926ffdb6ff275f97d62ff51e5b4b7938ed798e2b061
1420 553d5cc41a1504641a0b08a7740b3e163729fbc7002beff7a4c42086792b187c
1421 ebc7d6086283865ece2f4083069e061a4daeda5c069fb787d68e0e047928ddad
1422 9c2aaab3cdb94704ba77853fd44f7df8fc7f7be486a0858285417d533ba27b6e
1423 d9dda746efe18409204f5dd473af0974cda2981bc7028e830d4b7a9ac58200c3
1424 8011762e3bb680fa7dde7adb6706ab440a8400a0225d08709e6e32299683015c
1425 c2d7cac786b4b2bd6ab238f210ef7314a57fbff5964041e8b80d426409efddb9
1426 4c38a989840867addfe1de59d890a95b4bd4930ceb1f888f6f6872f9305048ec
1427 3592f8cbc86fe51d68f30d06bad31c555bdbb9f43c50b9e1ec34430750e443d6
1428 8157bc52defc0965"
1429 ),
1430 8256,
1431 )
1432 .unwrap();
1433
1434 let e = BoxedUint::from(65_537u64);
1435
1436 assert_eq!(
1437 RsaPublicKey::new(n, e).err().unwrap(),
1438 Error::ModulusTooLarge
1439 );
1440 }
1441
1442 #[test]
1443 #[cfg(feature = "encoding")]
1444 fn build_key_from_primes() {
1445 const RSA_2048_PRIV_DER: &[u8] = include_bytes!("../tests/examples/pkcs8/rsa2048-priv.der");
1446 let ref_key = RsaPrivateKey::from_pkcs8_der(RSA_2048_PRIV_DER).unwrap();
1447 assert_eq!(ref_key.validate(), Ok(()));
1448
1449 let primes = PrivateKeyParts::primes(&ref_key).to_vec();
1450
1451 let exp = PublicKeyParts::e(&ref_key);
1452 let key = RsaPrivateKey::from_primes(primes, exp.clone())
1453 .expect("failed to import key from primes");
1454 assert_eq!(key.validate(), Ok(()));
1455
1456 assert_eq!(PublicKeyParts::n(&key), PublicKeyParts::n(&ref_key));
1457
1458 assert_eq!(PrivateKeyParts::dp(&key), PrivateKeyParts::dp(&ref_key));
1459 assert_eq!(PrivateKeyParts::dq(&key), PrivateKeyParts::dq(&ref_key));
1460
1461 assert_eq!(PrivateKeyParts::d(&key), PrivateKeyParts::d(&ref_key));
1462 }
1463
1464 #[test]
1465 #[cfg(feature = "encoding")]
1466 fn build_key_from_p_q() {
1467 const RSA_2048_SP800_PRIV_DER: &[u8] =
1468 include_bytes!("../tests/examples/pkcs8/rsa2048-sp800-56b-priv.der");
1469 let ref_key = RsaPrivateKey::from_pkcs8_der(RSA_2048_SP800_PRIV_DER).unwrap();
1470 assert_eq!(ref_key.validate(), Ok(()));
1471
1472 let primes = PrivateKeyParts::primes(&ref_key).to_vec();
1473 let exp = PublicKeyParts::e(&ref_key);
1474
1475 let key = RsaPrivateKey::from_p_q(primes[0].clone(), primes[1].clone(), exp.clone())
1476 .expect("failed to import key from primes");
1477 assert_eq!(key.validate(), Ok(()));
1478
1479 assert_eq!(PublicKeyParts::n(&key), PublicKeyParts::n(&ref_key));
1480
1481 assert_eq!(PrivateKeyParts::dp(&key), PrivateKeyParts::dp(&ref_key));
1482 assert_eq!(PrivateKeyParts::dq(&key), PrivateKeyParts::dq(&ref_key));
1483
1484 assert_eq!(PrivateKeyParts::d(&key), PrivateKeyParts::d(&ref_key));
1485 }
1486
1487 #[test]
1488 #[cfg(all(feature = "hazmat", feature = "keygen"))]
1489 fn test_from_components_with_large_exponent() {
1490 use rand::rngs::ChaCha8Rng;
1494 use rand_core::SeedableRng;
1495
1496 let mut rng = ChaCha8Rng::from_seed([42; 32]);
1497
1498 let large_e = BoxedUint::from((1u64 << 34) + 1); let components =
1503 generate_multi_prime_key_with_exp(&mut rng, 2, 1024, large_e.clone()).unwrap();
1504
1505 let n = components.n.get().clone();
1507 let d = components.d;
1508 let primes = components.primes;
1509
1510 let result =
1512 RsaPrivateKey::from_components(n.clone(), large_e.clone(), d.clone(), primes.clone());
1513 assert!(result.is_err());
1514 assert_eq!(result.unwrap_err(), Error::PublicExponentTooLarge);
1515
1516 let key_with_large_exp = RsaPrivateKey::from_components_with_large_exponent(
1518 n.clone(),
1519 large_e.clone(),
1520 d.clone(),
1521 primes.clone(),
1522 );
1523 assert!(key_with_large_exp.is_ok());
1524
1525 let key_with_large_exp = key_with_large_exp.unwrap();
1526 assert_eq!(PublicKeyParts::e(&key_with_large_exp), &large_e);
1527 assert_eq!(PublicKeyParts::n(&key_with_large_exp).as_ref(), &n);
1528 assert_eq!(PrivateKeyParts::d(&key_with_large_exp), &d);
1529
1530 assert!(validate_skip_exponent_size(&key_with_large_exp).is_ok());
1533 }
1534
1535 #[test]
1536 #[cfg(all(feature = "hazmat", feature = "keygen"))]
1537 fn test_from_components_with_small_exponent() {
1538 use rand::rngs::ChaCha8Rng;
1542 use rand_core::SeedableRng;
1543
1544 let mut rng = ChaCha8Rng::from_seed([43; 32]);
1545
1546 let small_e = BoxedUint::from(1u64); let components =
1551 generate_multi_prime_key_with_exp(&mut rng, 2, 1024, small_e.clone()).unwrap();
1552
1553 let n = components.n.get().clone();
1555 let d = components.d;
1556 let primes = components.primes;
1557
1558 let result =
1560 RsaPrivateKey::from_components(n.clone(), small_e.clone(), d.clone(), primes.clone());
1561 assert!(result.is_err());
1562
1563 let key_with_small_exp = RsaPrivateKey::from_components_with_large_exponent(
1565 n.clone(),
1566 small_e.clone(),
1567 d.clone(),
1568 primes,
1569 );
1570 assert!(key_with_small_exp.is_ok());
1571
1572 let key_with_small_exp = key_with_small_exp.unwrap();
1573 assert_eq!(PublicKeyParts::e(&key_with_small_exp), &small_e);
1574
1575 assert!(validate_skip_exponent_size(&key_with_small_exp).is_ok());
1577 }
1578
1579 #[test]
1591 #[cfg(feature = "hazmat")]
1592 fn test_key_invalid_primes() {
1593 let e = RsaPrivateKey::from_components_with_large_exponent(
1594 BoxedUint::from(239u64),
1595 BoxedUint::from(185u64),
1596 BoxedUint::from(0u64),
1597 vec![BoxedUint::from(1u64), BoxedUint::from(239u64)],
1598 )
1599 .unwrap_err();
1600 assert_eq!(e, Error::InvalidPrime);
1601 }
1602}