sad_rsa/
key.rs

1use alloc::vec::Vec;
2use core::cmp::Ordering;
3use core::fmt;
4use core::hash::{Hash, Hasher};
5
6use crypto_bigint::modular::{BoxedMontyForm, BoxedMontyParams};
7use crypto_bigint::{BoxedUint, Integer, NonZero, Odd, Resize};
8use rand_core::CryptoRng;
9use zeroize::{Zeroize, ZeroizeOnDrop};
10#[cfg(feature = "serde")]
11use {
12    pkcs8::{DecodePrivateKey, EncodePrivateKey},
13    serdect::serde::{de, ser, Deserialize, Serialize},
14    spki::{DecodePublicKey, EncodePublicKey},
15};
16
17use crate::algorithms::generate::generate_multi_prime_key_with_exp;
18use crate::algorithms::rsa::{
19    compute_modulus, compute_private_exponent_carmicheal, compute_private_exponent_euler_totient,
20    recover_primes,
21};
22
23use crate::dummy_rng::DummyRng;
24use crate::errors::{Error, Result};
25use crate::traits::keys::{CrtValue, PrivateKeyParts, PublicKeyParts};
26use crate::traits::{PaddingScheme, SignatureScheme};
27
28/// Represents the public part of an RSA key.
29#[derive(Debug, Clone)]
30pub struct RsaPublicKey {
31    /// Modulus: product of prime numbers `p` and `q`
32    n: NonZero<BoxedUint>,
33    /// Public exponent: power to which a plaintext message is raised in
34    /// order to encrypt it.
35    ///
36    /// Typically `0x10001` (`65537`)
37    e: BoxedUint,
38
39    n_params: BoxedMontyParams,
40}
41
42impl Eq for RsaPublicKey {}
43
44impl PartialEq for RsaPublicKey {
45    #[inline]
46    fn eq(&self, other: &RsaPublicKey) -> bool {
47        self.n == other.n && self.e == other.e
48    }
49}
50
51impl Hash for RsaPublicKey {
52    fn hash<H: Hasher>(&self, state: &mut H) {
53        // Domain separator for RSA private keys
54        state.write(b"RsaPublicKey");
55        // TODO(tarcieri): to match the `PartialEq` impl we should strip leading zeros
56        Hash::hash(&self.n.as_limbs(), state);
57        Hash::hash(&self.e.as_limbs(), state);
58    }
59}
60
61/// Represents a whole RSA key, public and private parts.
62#[derive(Clone)]
63pub struct RsaPrivateKey {
64    /// Public components of the private key.
65    pubkey_components: RsaPublicKey,
66    /// Private exponent
67    pub(crate) d: BoxedUint,
68    /// Prime factors of N, contains >= 2 elements.
69    pub(crate) primes: Vec<BoxedUint>,
70    /// Precomputed values to speed up private operations
71    pub(crate) precomputed: Option<PrecomputedValues>,
72}
73
74impl fmt::Debug for RsaPrivateKey {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        let precomputed = if self.precomputed.is_some() {
77            "Some(...)"
78        } else {
79            "None"
80        };
81        f.debug_struct("RsaPrivateKey")
82            .field("pubkey_components", &self.pubkey_components)
83            .field("d", &"...")
84            .field("primes", &"&[...]")
85            .field("precomputed", &precomputed)
86            .finish()
87    }
88}
89
90impl Eq for RsaPrivateKey {}
91impl PartialEq for RsaPrivateKey {
92    #[inline]
93    fn eq(&self, other: &RsaPrivateKey) -> bool {
94        self.pubkey_components == other.pubkey_components
95            && self.d == other.d
96            && self.primes == other.primes
97    }
98}
99
100impl AsRef<RsaPublicKey> for RsaPrivateKey {
101    fn as_ref(&self) -> &RsaPublicKey {
102        &self.pubkey_components
103    }
104}
105
106impl Hash for RsaPrivateKey {
107    fn hash<H: Hasher>(&self, state: &mut H) {
108        // Domain separator for RSA private keys
109        state.write(b"RsaPrivateKey");
110        Hash::hash(&self.pubkey_components, state);
111    }
112}
113
114impl Drop for RsaPrivateKey {
115    fn drop(&mut self) {
116        self.d.zeroize();
117        self.primes.zeroize();
118        self.precomputed.zeroize();
119    }
120}
121
122impl ZeroizeOnDrop for RsaPrivateKey {}
123
124#[derive(Clone)]
125pub(crate) struct PrecomputedValues {
126    /// D mod (P-1)
127    pub(crate) dp: BoxedUint,
128    /// D mod (Q-1)
129    pub(crate) dq: BoxedUint,
130    /// Q^-1 mod P
131    pub(crate) qinv: BoxedMontyForm,
132
133    /// Montgomery params for `p`
134    pub(crate) p_params: BoxedMontyParams,
135    /// Montgomery params for `q`
136    pub(crate) q_params: BoxedMontyParams,
137}
138
139impl ZeroizeOnDrop for PrecomputedValues {}
140
141impl Zeroize for PrecomputedValues {
142    fn zeroize(&mut self) {
143        self.dp.zeroize();
144        self.dq.zeroize();
145        // TODO: once these have landed in crypto-bigint
146        // self.p_params.zeroize();
147        // self.q_params.zeroize();
148    }
149}
150
151impl Drop for PrecomputedValues {
152    fn drop(&mut self) {
153        self.zeroize();
154    }
155}
156
157impl From<RsaPrivateKey> for RsaPublicKey {
158    fn from(private_key: RsaPrivateKey) -> Self {
159        (&private_key).into()
160    }
161}
162
163impl From<&RsaPrivateKey> for RsaPublicKey {
164    fn from(private_key: &RsaPrivateKey) -> Self {
165        let n = PublicKeyParts::n(private_key);
166        let e = PublicKeyParts::e(private_key);
167        let n_params = PublicKeyParts::n_params(private_key);
168        RsaPublicKey {
169            n: n.clone(),
170            e: e.clone(),
171            n_params: n_params.clone(),
172        }
173    }
174}
175
176impl PublicKeyParts for RsaPublicKey {
177    fn n(&self) -> &NonZero<BoxedUint> {
178        &self.n
179    }
180
181    fn e(&self) -> &BoxedUint {
182        &self.e
183    }
184
185    fn n_params(&self) -> &BoxedMontyParams {
186        &self.n_params
187    }
188}
189
190impl RsaPublicKey {
191    /// Encrypt the given message.
192    pub fn encrypt<R: CryptoRng + ?Sized, P: PaddingScheme>(
193        &self,
194        rng: &mut R,
195        padding: P,
196        msg: &[u8],
197    ) -> Result<Vec<u8>> {
198        padding.encrypt(rng, self, msg)
199    }
200
201    /// Verify a signed message.
202    ///
203    /// `hashed` must be the result of hashing the input using the hashing function
204    /// passed in through `hash`.
205    ///
206    /// If the message is valid `Ok(())` is returned, otherwise an `Err` indicating failure.
207    pub fn verify<S: SignatureScheme>(&self, scheme: S, hashed: &[u8], sig: &[u8]) -> Result<()> {
208        scheme.verify(self, hashed, sig)
209    }
210}
211
212impl RsaPublicKey {
213    /// Minimum value of the public exponent `e`.
214    pub const MIN_PUB_EXPONENT: u64 = 2;
215
216    /// Maximum value of the public exponent `e`.
217    pub const MAX_PUB_EXPONENT: u64 = (1 << 33) - 1;
218
219    /// Maximum size of the modulus `n` in bits.
220    pub const MAX_SIZE: usize = 4096;
221
222    /// Create a new public key from its components.
223    ///
224    /// This function accepts public keys with a modulus size up to 4096-bits,
225    /// i.e. [`RsaPublicKey::MAX_SIZE`].
226    pub fn new(n: BoxedUint, e: BoxedUint) -> Result<Self> {
227        Self::new_with_max_size(n, e, Self::MAX_SIZE)
228    }
229
230    /// Create a new public key from its components.
231    pub fn new_with_max_size(n: BoxedUint, e: BoxedUint, max_size: usize) -> Result<Self> {
232        check_public_with_max_size(&n, &e, Some(max_size))?;
233
234        let n_odd = Odd::new(n.clone())
235            .into_option()
236            .ok_or(Error::InvalidModulus)?;
237        let n_params = BoxedMontyParams::new(n_odd);
238        let n = NonZero::new(n).expect("checked above");
239
240        Ok(Self { n, e, n_params })
241    }
242
243    /// Create a new public key, bypassing checks around the modulus and public
244    /// exponent size.
245    ///
246    /// This method is not recommended, and only intended for unusual use cases.
247    /// Most applications should use [`RsaPublicKey::new`] or
248    /// [`RsaPublicKey::new_with_max_size`] instead.
249    pub fn new_unchecked(n: BoxedUint, e: BoxedUint) -> Self {
250        let n_odd = Odd::new(n.clone()).expect("n must be odd");
251        let n_params = BoxedMontyParams::new(n_odd);
252        let n = NonZero::new(n).expect("odd numbers are non zero");
253
254        Self { n, e, n_params }
255    }
256}
257
258impl PublicKeyParts for RsaPrivateKey {
259    fn n(&self) -> &NonZero<BoxedUint> {
260        &self.pubkey_components.n
261    }
262
263    fn e(&self) -> &BoxedUint {
264        &self.pubkey_components.e
265    }
266
267    fn n_params(&self) -> &BoxedMontyParams {
268        &self.pubkey_components.n_params
269    }
270}
271
272impl RsaPrivateKey {
273    /// Default exponent for RSA keys.
274    const EXP: u64 = 65537;
275
276    /// Minimum size of the modulus `n` in bits. Currently only applies to keygen.
277    const MIN_SIZE: u32 = 1024;
278
279    /// Generate a new RSA key pair with a modulus of the given bit size using the passed in `rng`.
280    ///
281    /// # Errors
282    /// - If `bit_size` is lower than the minimum 1024-bits.
283    pub fn new<R: CryptoRng + ?Sized>(rng: &mut R, bit_size: usize) -> Result<Self> {
284        Self::new_with_exp(rng, bit_size, Self::EXP.into())
285    }
286
287    /// Generate a new RSA key pair of the given bit size.
288    ///
289    /// #⚠️Warning: Hazmat!
290    /// This version does not apply minimum key size checks, and as such may generate keys
291    /// which are insecure!
292    #[cfg(feature = "hazmat")]
293    pub fn new_unchecked<R: CryptoRng + ?Sized>(rng: &mut R, bit_size: usize) -> Result<Self> {
294        Self::new_with_exp_unchecked(rng, bit_size, Self::EXP.into())
295    }
296
297    /// Generate a new RSA key pair of the given bit size and the public exponent
298    /// using the passed in `rng`.
299    ///
300    /// Unless you have specific needs, you should use [`RsaPrivateKey::new`] instead.
301    pub fn new_with_exp<R: CryptoRng + ?Sized>(
302        rng: &mut R,
303        bit_size: usize,
304        exp: BoxedUint,
305    ) -> Result<RsaPrivateKey> {
306        if bit_size < Self::MIN_SIZE as usize {
307            return Err(Error::ModulusTooSmall);
308        }
309
310        let components = generate_multi_prime_key_with_exp(rng, 2, bit_size, exp)?;
311        RsaPrivateKey::from_components(
312            components.n.get(),
313            components.e,
314            components.d,
315            components.primes,
316        )
317    }
318
319    /// Generate a new RSA key pair of the given bit size and the public exponent
320    /// using the passed in `rng`.
321    ///
322    /// Unless you have specific needs, you should use [`RsaPrivateKey::new`] instead.
323    ///
324    /// #⚠️Warning: Hazmat!
325    /// This version does not apply minimum key size checks, and as such may generate keys
326    /// which are insecure!
327    #[cfg(feature = "hazmat")]
328    pub fn new_with_exp_unchecked<R: CryptoRng + ?Sized>(
329        rng: &mut R,
330        bit_size: usize,
331        exp: BoxedUint,
332    ) -> Result<RsaPrivateKey> {
333        let components = generate_multi_prime_key_with_exp(rng, 2, bit_size, exp)?;
334        RsaPrivateKey::from_components(
335            components.n.get(),
336            components.e,
337            components.d,
338            components.primes,
339        )
340    }
341
342    /// Constructs an RSA key pair from individual components:
343    ///
344    /// - `n`: RSA modulus
345    /// - `e`: public exponent (i.e. encrypting exponent)
346    /// - `d`: private exponent (i.e. decrypting exponent)
347    /// - `primes`: prime factors of `n`: typically two primes `p` and `q`. More than two primes can
348    ///   be provided for multiprime RSA, however this is generally not recommended. If no `primes`
349    ///   are provided, a prime factor recovery algorithm will be employed to attempt to recover the
350    ///   factors (as described in [NIST SP 800-56B Revision 2] Appendix C.2). This algorithm only
351    ///   works if there are just two prime factors `p` and `q` (as opposed to multiprime), and `e`
352    ///   is between 2^16 and 2^256.
353    ///
354    ///  [NIST SP 800-56B Revision 2]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf
355    pub fn from_components(
356        n: BoxedUint,
357        e: BoxedUint,
358        d: BoxedUint,
359        mut primes: Vec<BoxedUint>,
360    ) -> Result<RsaPrivateKey> {
361        let n = Odd::new(n).into_option().ok_or(Error::InvalidModulus)?;
362
363        // The modulus may come in padded with zeros, shorten it
364        // to ensure optimal performance of arithmetic operations.
365        let n_bits = n.bits_vartime();
366        let n = n.resize_unchecked(n_bits);
367
368        let n_params = BoxedMontyParams::new(n.clone());
369        let n_c = NonZero::new(n.get())
370            .into_option()
371            .ok_or(Error::InvalidModulus)?;
372
373        match primes.len() {
374            0 => {
375                // Recover `p` and `q` from `d`.
376                // See method in Appendix C.2: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf
377                let (p, q) = recover_primes(&n_c, &e, &d)?;
378                primes.push(p);
379                primes.push(q);
380            }
381            1 => return Err(Error::NprimesTooSmall),
382            _ => {
383                // Check that the product of primes matches the modulus.
384                // This also ensures that `bit_precision` of each prime is <= that of the modulus,
385                // and `bit_precision` of their product is >= that of the modulus.
386                if &primes.iter().fold(BoxedUint::one(), |acc, p| acc * p) != n_c.as_ref() {
387                    return Err(Error::InvalidModulus);
388                }
389            }
390        }
391
392        // The primes may come in padded with zeros too, so we need to shorten them as well.
393        let primes = primes
394            .into_iter()
395            .map(|p| {
396                let p_bits = p.bits();
397                p.resize_unchecked(p_bits)
398            })
399            .collect();
400
401        let mut k = RsaPrivateKey {
402            pubkey_components: RsaPublicKey {
403                n: n_c,
404                e,
405                n_params,
406            },
407            d,
408            primes,
409            precomputed: None,
410        };
411
412        // Always validate the key, to ensure precompute can't fail
413        k.validate()?;
414
415        // Precompute when possible, ignore error otherwise.
416        k.precompute().ok();
417
418        Ok(k)
419    }
420
421    /// Constructs an RSA key pair from its two primes p and q.
422    ///
423    /// This will rebuild the private exponent and the modulus.
424    ///
425    /// Private exponent will be rebuilt using the method defined in
426    /// [NIST 800-56B Section 6.2.1](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf#page=47).
427    pub fn from_p_q(
428        p: BoxedUint,
429        q: BoxedUint,
430        public_exponent: BoxedUint,
431    ) -> Result<RsaPrivateKey> {
432        if p == q {
433            return Err(Error::InvalidPrime);
434        }
435
436        let d = compute_private_exponent_carmicheal(&p, &q, &public_exponent)?;
437        let primes = vec![p, q];
438        let n = compute_modulus(&primes);
439
440        Self::from_components(n.get(), public_exponent, d, primes)
441    }
442
443    /// Constructs an RSA key pair from its primes.
444    ///
445    /// This will rebuild the private exponent and the modulus.
446    pub fn from_primes(
447        primes: Vec<BoxedUint>,
448        public_exponent: BoxedUint,
449    ) -> Result<RsaPrivateKey> {
450        if primes.len() < 2 {
451            return Err(Error::NprimesTooSmall);
452        }
453
454        // Makes sure that the primes are pairwise unequal.
455        for (i, prime1) in primes.iter().enumerate() {
456            for prime2 in primes.iter().take(i) {
457                if prime1 == prime2 {
458                    return Err(Error::InvalidPrime);
459                }
460            }
461        }
462
463        let n = compute_modulus(&primes);
464        let d = compute_private_exponent_euler_totient(&primes, &public_exponent)?;
465
466        Self::from_components(n.get(), public_exponent, d, primes)
467    }
468
469    /// Get the public key from the private key.
470    ///
471    /// Specific alternative to [`AsRef::as_ref`].
472    pub fn as_public_key(&self) -> &RsaPublicKey {
473        &self.pubkey_components
474    }
475
476    /// Get the public key from the private key, cloning `n` and `e`.
477    ///
478    /// Generally this is not needed since `RsaPrivateKey` implements the `PublicKey` trait,
479    /// but it can occasionally be useful to discard the private information entirely.
480    pub fn to_public_key(&self) -> RsaPublicKey {
481        self.pubkey_components.clone()
482    }
483
484    /// Performs some calculations to speed up private key operations.
485    pub fn precompute(&mut self) -> Result<()> {
486        if self.precomputed.is_some() {
487            return Ok(());
488        }
489
490        let d = &self.d;
491        let p = self.primes[0].clone();
492        let q = self.primes[1].clone();
493
494        let p_odd = Odd::new(p.clone())
495            .into_option()
496            .ok_or(Error::InvalidPrime)?;
497        let p_params = BoxedMontyParams::new(p_odd);
498        let q_odd = Odd::new(q.clone())
499            .into_option()
500            .ok_or(Error::InvalidPrime)?;
501        let q_params = BoxedMontyParams::new(q_odd);
502
503        let x = NonZero::new(p.wrapping_sub(&BoxedUint::one()))
504            .into_option()
505            .ok_or(Error::InvalidPrime)?;
506        let dp = d.rem_vartime(&x);
507
508        let x = NonZero::new(q.wrapping_sub(&BoxedUint::one()))
509            .into_option()
510            .ok_or(Error::InvalidPrime)?;
511        let dq = d.rem_vartime(&x);
512
513        // Note that since `p` and `q` may have different `bits_precision`,
514        // so we have to equalize them to calculate the remainder.
515        let q_mod_p = match p.bits_precision().cmp(&q.bits_precision()) {
516            Ordering::Less => (&q
517                % NonZero::new(p.clone())
518                    .expect("`p` is non-zero")
519                    .resize_unchecked(q.bits_precision()))
520            .resize_unchecked(p.bits_precision()),
521            Ordering::Greater => {
522                (&q).resize_unchecked(p.bits_precision())
523                    % &NonZero::new(p.clone()).expect("`p` is non-zero")
524            }
525            Ordering::Equal => &q % NonZero::new(p.clone()).expect("`p` is non-zero"),
526        };
527
528        let q_mod_p = BoxedMontyForm::new(q_mod_p, &p_params);
529        let qinv = q_mod_p.invert().into_option().ok_or(Error::InvalidPrime)?;
530
531        debug_assert_eq!(dp.bits_precision(), p.bits_precision());
532        debug_assert_eq!(dq.bits_precision(), q.bits_precision());
533        debug_assert_eq!(qinv.bits_precision(), p.bits_precision());
534        debug_assert_eq!(p_params.bits_precision(), p.bits_precision());
535        debug_assert_eq!(q_params.bits_precision(), q.bits_precision());
536
537        self.precomputed = Some(PrecomputedValues {
538            dp,
539            dq,
540            qinv,
541            p_params,
542            q_params,
543        });
544
545        Ok(())
546    }
547
548    /// Clears precomputed values by setting to None
549    pub fn clear_precomputed(&mut self) {
550        self.precomputed = None;
551    }
552
553    /// Compute CRT coefficient: `(1/q) mod p`.
554    pub fn crt_coefficient(&self) -> Option<BoxedUint> {
555        let p = &self.primes[0];
556        let q = &self.primes[1];
557        // TODO: maybe store primes as `NonZero`?
558        Option::from(q.invert_mod(&NonZero::new(p.clone()).expect("prime")))
559    }
560
561    /// Performs basic sanity checks on the key.
562    /// Returns `Ok(())` if everything is good, otherwise an appropriate error.
563    pub fn validate(&self) -> Result<()> {
564        check_public(self)?;
565
566        // Check that Πprimes == n.
567        let mut m = BoxedUint::one_with_precision(self.pubkey_components.n.bits_precision());
568        let one = BoxedUint::one();
569        for prime in &self.primes {
570            // Any primes ≤ 1 will cause divide-by-zero panics later.
571            if prime < &one {
572                return Err(Error::InvalidPrime);
573            }
574            m = m.wrapping_mul(prime);
575        }
576        if m != *self.pubkey_components.n {
577            return Err(Error::InvalidModulus);
578        }
579
580        // Check that de ≡ 1 mod p-1, for each prime.
581        // This implies that e is coprime to each p-1 as e has a multiplicative
582        // inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) =
583        // exponent(ℤ/nℤ). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1
584        // mod p. Thus a^de ≡ a mod n for all a coprime to n, as required.
585        let de = self.d.mul(&self.pubkey_components.e);
586
587        for prime in &self.primes {
588            let x = NonZero::new(prime.wrapping_sub(&BoxedUint::one())).unwrap();
589            let congruence = de.rem_vartime(&x);
590            if !bool::from(congruence.is_one()) {
591                return Err(Error::InvalidExponent);
592            }
593        }
594
595        Ok(())
596    }
597
598    /// Decrypt the given message.
599    pub fn decrypt<P: PaddingScheme>(&self, padding: P, ciphertext: &[u8]) -> Result<Vec<u8>> {
600        padding.decrypt(Option::<&mut DummyRng>::None, self, ciphertext)
601    }
602
603    /// Decrypt the given message.
604    ///
605    /// Uses `rng` to blind the decryption process.
606    pub fn decrypt_blinded<R: CryptoRng + ?Sized, P: PaddingScheme>(
607        &self,
608        rng: &mut R,
609        padding: P,
610        ciphertext: &[u8],
611    ) -> Result<Vec<u8>> {
612        padding.decrypt(Some(rng), self, ciphertext)
613    }
614
615    /// Sign the given digest.
616    pub fn sign<S: SignatureScheme>(&self, padding: S, digest_in: &[u8]) -> Result<Vec<u8>> {
617        padding.sign(Option::<&mut DummyRng>::None, self, digest_in)
618    }
619
620    /// Sign the given digest using the provided `rng`, which is used in the
621    /// following ways depending on the [`SignatureScheme`]:
622    ///
623    /// - [`Pkcs1v15Sign`][`crate::Pkcs1v15Sign`] padding: uses the RNG
624    ///   to mask the private key operation with random blinding, which helps
625    ///   mitigate sidechannel attacks.
626    /// - [`Pss`][`crate::Pss`] always requires randomness. Use
627    ///   [`Pss::new`][`crate::Pss::new`] for a standard RSASSA-PSS signature, or
628    ///   [`Pss::new_blinded`][`crate::Pss::new_blinded`] for RSA-BSSA blind
629    ///   signatures.
630    pub fn sign_with_rng<R: CryptoRng + ?Sized, S: SignatureScheme>(
631        &self,
632        rng: &mut R,
633        padding: S,
634        digest_in: &[u8],
635    ) -> Result<Vec<u8>> {
636        padding.sign(Some(rng), self, digest_in)
637    }
638}
639
640impl PrivateKeyParts for RsaPrivateKey {
641    fn d(&self) -> &BoxedUint {
642        &self.d
643    }
644
645    fn primes(&self) -> &[BoxedUint] {
646        &self.primes
647    }
648
649    fn dp(&self) -> Option<&BoxedUint> {
650        self.precomputed.as_ref().map(|p| &p.dp)
651    }
652
653    fn dq(&self) -> Option<&BoxedUint> {
654        self.precomputed.as_ref().map(|p| &p.dq)
655    }
656
657    fn qinv(&self) -> Option<&BoxedMontyForm> {
658        self.precomputed.as_ref().map(|p| &p.qinv)
659    }
660
661    fn crt_values(&self) -> Option<&[CrtValue]> {
662        None
663    }
664
665    fn p_params(&self) -> Option<&BoxedMontyParams> {
666        self.precomputed.as_ref().map(|p| &p.p_params)
667    }
668
669    fn q_params(&self) -> Option<&BoxedMontyParams> {
670        self.precomputed.as_ref().map(|p| &p.q_params)
671    }
672}
673
674/// Check that the public key is well formed and has an exponent within acceptable bounds.
675#[inline]
676pub fn check_public(public_key: &impl PublicKeyParts) -> Result<()> {
677    check_public_with_max_size(public_key.n(), public_key.e(), None)
678}
679
680/// Check that the public key is well formed and has an exponent within acceptable bounds.
681#[inline]
682fn check_public_with_max_size(n: &BoxedUint, e: &BoxedUint, max_size: Option<usize>) -> Result<()> {
683    if let Some(max_size) = max_size {
684        if n.bits_vartime() as usize > max_size {
685            return Err(Error::ModulusTooLarge);
686        }
687    }
688
689    if e >= n || n.is_even().into() || n.is_zero().into() {
690        return Err(Error::InvalidModulus);
691    }
692
693    if e.is_even().into() {
694        return Err(Error::InvalidExponent);
695    }
696
697    if e < &BoxedUint::from(RsaPublicKey::MIN_PUB_EXPONENT) {
698        return Err(Error::PublicExponentTooSmall);
699    }
700
701    if e > &BoxedUint::from(RsaPublicKey::MAX_PUB_EXPONENT) {
702        return Err(Error::PublicExponentTooLarge);
703    }
704
705    Ok(())
706}
707
708#[cfg(feature = "serde")]
709impl Serialize for RsaPublicKey {
710    fn serialize<S>(&self, serializer: S) -> core::prelude::v1::Result<S::Ok, S::Error>
711    where
712        S: serdect::serde::Serializer,
713    {
714        let der = self.to_public_key_der().map_err(ser::Error::custom)?;
715        serdect::slice::serialize_hex_lower_or_bin(&der, serializer)
716    }
717}
718
719#[cfg(feature = "serde")]
720impl<'de> Deserialize<'de> for RsaPublicKey {
721    fn deserialize<D>(deserializer: D) -> core::prelude::v1::Result<Self, D::Error>
722    where
723        D: serdect::serde::Deserializer<'de>,
724    {
725        let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?;
726        Self::from_public_key_der(&der_bytes).map_err(de::Error::custom)
727    }
728}
729
730#[cfg(feature = "serde")]
731impl Serialize for RsaPrivateKey {
732    fn serialize<S>(&self, serializer: S) -> core::prelude::v1::Result<S::Ok, S::Error>
733    where
734        S: ser::Serializer,
735    {
736        let der = self.to_pkcs8_der().map_err(ser::Error::custom)?;
737        serdect::slice::serialize_hex_lower_or_bin(&der.as_bytes(), serializer)
738    }
739}
740
741#[cfg(feature = "serde")]
742impl<'de> Deserialize<'de> for RsaPrivateKey {
743    fn deserialize<D>(deserializer: D) -> core::prelude::v1::Result<Self, D::Error>
744    where
745        D: de::Deserializer<'de>,
746    {
747        let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?;
748        Self::from_pkcs8_der(&der_bytes).map_err(de::Error::custom)
749    }
750}
751
752#[cfg(test)]
753mod tests {
754    use super::*;
755    use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt};
756    use crate::traits::{PrivateKeyParts, PublicKeyParts};
757
758    use hex_literal::hex;
759    use rand::rngs::ChaCha8Rng;
760    use rand_core::SeedableRng;
761
762    #[cfg(feature = "encoding")]
763    use pkcs8::DecodePrivateKey;
764
765    #[test]
766    fn test_from_into() {
767        let raw_n = BoxedUint::from(101u64);
768        let n_odd = Odd::new(raw_n.clone()).unwrap();
769        let private_key = RsaPrivateKey {
770            pubkey_components: RsaPublicKey {
771                n: NonZero::new(raw_n.clone()).unwrap(),
772                e: BoxedUint::from(200u64),
773                n_params: BoxedMontyParams::new(n_odd),
774            },
775            d: BoxedUint::from(123u64),
776            primes: vec![],
777            precomputed: None,
778        };
779        let public_key: RsaPublicKey = private_key.into();
780
781        let n_limbs: &[u64] = PublicKeyParts::n(&public_key).as_ref().as_ref();
782        assert_eq!(n_limbs, &[101u64]);
783        assert_eq!(PublicKeyParts::e(&public_key), &BoxedUint::from(200u64));
784        assert_eq!(PublicKeyParts::e_bytes(&public_key), [200].into());
785        assert_eq!(PublicKeyParts::n_bytes(&public_key), [101].into());
786    }
787
788    fn test_key_basics(private_key: &RsaPrivateKey) {
789        private_key.validate().expect("invalid private key");
790
791        assert!(
792            PrivateKeyParts::d(private_key) < PublicKeyParts::n(private_key).as_ref(),
793            "private exponent too large"
794        );
795
796        let pub_key: RsaPublicKey = private_key.clone().into();
797        let m = BoxedUint::from(42u64);
798        let c = rsa_encrypt(&pub_key, &m).expect("encryption successful");
799
800        let m2 = rsa_decrypt_and_check::<ChaCha8Rng>(private_key, None, &c)
801            .expect("unable to decrypt without blinding");
802        assert_eq!(m, m2);
803        let mut rng = ChaCha8Rng::from_seed([42; 32]);
804        let m3 = rsa_decrypt_and_check(private_key, Some(&mut rng), &c)
805            .expect("unable to decrypt with blinding");
806        assert_eq!(m, m3);
807    }
808
809    macro_rules! key_generation {
810        ($name:ident, $multi:expr, $size:expr) => {
811            #[test]
812            fn $name() {
813                let mut rng = ChaCha8Rng::from_seed([42; 32]);
814                let exp = BoxedUint::from(RsaPrivateKey::EXP);
815
816                for _ in 0..10 {
817                    let components =
818                        generate_multi_prime_key_with_exp(&mut rng, $multi, $size, exp.clone())
819                            .unwrap();
820                    let private_key = RsaPrivateKey::from_components(
821                        components.n.get(),
822                        components.e,
823                        components.d,
824                        components.primes,
825                    )
826                    .unwrap();
827                    assert_eq!(PublicKeyParts::n(&private_key).bits(), $size);
828
829                    test_key_basics(&private_key);
830                }
831            }
832        };
833    }
834
835    key_generation!(key_generation_128, 2, 128);
836    key_generation!(key_generation_1024, 2, 1024);
837
838    key_generation!(key_generation_multi_3_256, 3, 256);
839
840    key_generation!(key_generation_multi_4_64, 4, 64);
841
842    key_generation!(key_generation_multi_5_64, 5, 64);
843    key_generation!(key_generation_multi_8_576, 8, 576);
844    key_generation!(key_generation_multi_16_1024, 16, 1024);
845
846    #[test]
847    fn test_negative_decryption_value() {
848        let bits = 128;
849        let private_key = RsaPrivateKey::from_components(
850            BoxedUint::from_le_slice(
851                &[
852                    99, 192, 208, 179, 0, 220, 7, 29, 49, 151, 75, 107, 75, 73, 200, 180,
853                ],
854                bits,
855            )
856            .unwrap(),
857            BoxedUint::from_le_slice(&[1, 0, 1, 0, 0, 0, 0, 0], 64).unwrap(),
858            BoxedUint::from_le_slice(
859                &[
860                    81, 163, 254, 144, 171, 159, 144, 42, 244, 133, 51, 249, 28, 12, 63, 65,
861                ],
862                bits,
863            )
864            .unwrap(),
865            vec![
866                BoxedUint::from_le_slice(&[105, 101, 60, 173, 19, 153, 3, 192], bits / 2).unwrap(),
867                BoxedUint::from_le_slice(&[235, 65, 160, 134, 32, 136, 6, 241], bits / 2).unwrap(),
868            ],
869        )
870        .unwrap();
871
872        for _ in 0..1000 {
873            test_key_basics(&private_key);
874        }
875    }
876
877    #[test]
878    #[cfg(all(feature = "hazmat", feature = "serde"))]
879    fn test_serde() {
880        use rand::rngs::ChaCha8Rng;
881        use rand_core::SeedableRng;
882        use serde_test::{assert_tokens, Configure, Token};
883
884        let mut rng = ChaCha8Rng::from_seed([42; 32]);
885        let priv_key = RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");
886
887        let priv_tokens = [Token::Str(concat!(
888            "3056020100300d06092a864886f70d010101050004423040020100020900a",
889            "b240c3361d02e370203010001020811e54a15259d22f9020500ceff5cf302",
890            "0500d3a7aaad020500ccaddf17020500cb529d3d020500bb526d6f"
891        ))];
892        assert_tokens(&priv_key.clone().readable(), &priv_tokens);
893
894        let priv_tokens = [Token::Str(
895            "3024300d06092a864886f70d01010105000313003010020900ab240c3361d02e370203010001",
896        )];
897        assert_tokens(
898            &RsaPublicKey::from(priv_key.clone()).readable(),
899            &priv_tokens,
900        );
901    }
902
903    #[test]
904    fn invalid_coeff_private_key_regression() {
905        use base64ct::{Base64, Encoding};
906
907        let n = Base64::decode_vec(
908            "wC8GyQvTCZOK+iiBR5fGQCmzRCTWX9TQ3aRG5gGFk0wB6EFoLMAyEEqeG3gS8xhA\
909             m2rSWYx9kKufvNat3iWlbSRVqkcbpVAYlj2vTrpqDpJl+6u+zxFYoUEBevlJJkAh\
910             l8EuCccOA30fVpcfRvXPTtvRd3yFT9E9EwZljtgSI02w7gZwg7VIxaGeajh5Euz6\
911             ZVQZ+qNRKgXrRC7gPRqVyI6Dt0Jc+Su5KBGNn0QcPDzOahWha1ieaeMkFisZ9mdp\
912             sJoZ4tw5eicLaUomKzALHXQVt+/rcZSrCd6/7uUo11B/CYBM4UfSpwXaL88J9AE6\
913             A5++no9hmJzaF2LLp+Qwx4yY3j9TDutxSAjsraxxJOGZ3XyA9nG++Ybt3cxZ5fP7\
914             ROjxCfROBmVv5dYn0O9OBIqYeCH6QraNpZMadlLNIhyMv8Y+P3r5l/PaK4VJaEi5\
915             pPosnEPawp0W0yZDzmjk2z1LthaRx0aZVrAjlH0Rb/6goLUQ9qu1xsDtQVVpN4A8\
916             9ZUmtTWORnnJr0+595eHHxssd2gpzqf4bPjNITdAEuOCCtpvyi4ls23zwuzryUYj\
917             cUOEnsXNQ+DrZpLKxdtsD/qNV/j1hfeyBoPllC3cV+6bcGOFcVGbjYqb+Kw1b0+j\
918             L69RSKQqgmS+qYqr8c48nDRxyq3QXhR8qtzUwBFSLVk=",
919        )
920        .unwrap();
921        let e = Base64::decode_vec("AQAB").unwrap();
922        let d = Base64::decode_vec(
923            "qQazSQ+FRN7nVK1bRsROMRB8AmsDwLVEHivlz1V3Td2Dr+oW3YUMgxedhztML1Id\
924             QJPq/ad6qErJ6yRFNySVIjDaxzBTOEoB1eHa1btOnBJWb8rVvvjaorixvJ6Tn3i4\
925             EuhsvVy9DoR1k4rGj3qSIiFjUVvLRDAbLyhpGgEfsr0Z577yJmTC5E8JLRMOKX8T\
926             mxsk3jPVpsgd65Hu1s8S/ZmabwuHCf9SkdMeY/1bd/9i7BqqJeeDLE4B5x1xcC3z\
927             3scqDUTzqGO+vZPhjgprPDRlBamVwgenhr7KwCn8iaLamFinRVwOAag8BeBqOJj7\
928             lURiOsKQa9FIX1kdFUS1QMQxgtPycLjkbvCJjriqT7zWKsmJ7l8YLs6Wmm9/+QJR\
929             wNCEVdMTXKfCP1cJjudaiskEQThfUldtgu8gUDNYbQ/Filb2eKfiX4h1TiMxZqUZ\
930             HVZyb9nShbQoXJ3vj/MGVF0QM8TxhXM8r2Lv9gDYU5t9nQlUMLhs0jVjai48jHAB\
931             bFNyH3sEcOmJOIwJrCXw1dzG7AotwyaEVUHOmL04TffmwCFfnyrLjbFgnyOeoyII\
932             BYjcY7QFRm/9nupXMTH5hZ2qrHfCJIp0KK4tNBdQqmnHapFl5l6Le1s4qBS5bEIz\
933             jitobLvAFm9abPlDGfxmY6mlrMK4+nytwF9Ct7wc1AE=",
934        )
935        .unwrap();
936        let primes = [
937            Base64::decode_vec(
938                "9kQWEAzsbzOcdPa+s5wFfw4XDd7bB1q9foZ31b1+TNjGNxbSBCFlDF1q98vwpV6n\
939                 M8bWDh/wtbNoETSQDgpEnYOQ26LWEw6YY1+q1Q2GGEFceYUf+Myk8/vTc8TN6Zw0\
940                 bKZBWy10Qo8h7xk4JpzuI7NcxvjJYTkS9aErFxi3vVH0aiZC0tmfaCqr8a2rJxyV\
941                 wqreRpOjwAWrotMsf2wGsF4ofx5ScoFy5GB5fJkkdOrW1LyTvZAUCX3cstPr19+T\
942                 NC5zZOk7WzZatnCkN5H5WzalWtZuu0oVL205KPOa3R8V2yv5e6fm0v5fTmqSuvjm\
943                 aMJLXCN4QJkmIzojO99ckQ==",
944            )
945            .unwrap(),
946            Base64::decode_vec(
947                "x8exdMjVA2CiI+Thx7loHtVcevoeE2sZ7btRVAvmBqo+lkHwxb7FHRnWvuj6eJSl\
948                 D2f0T50EewIhhiW3R9BmktCk7hXjbSCnC1u9Oxc1IAUm/7azRqyfCMx43XhLxpD+\
949                 xkBCpWkKDLxGczsRwTuaP3lKS3bSdBrNlGmdblubvVBIq4YZ2vXVlnYtza0cS+dg\
950                 CK7BGTqUsrCUd/ZbIvwcwZkZtpkhj1KQfto9X/0OMurBzAqbkeq1cyRHXHkOfN/q\
951                 bUIIRqr9Ii7Eswf9Vk8xp2O1Nt8nzcYS9PFD12M5eyaeFEkEYfpNMNGuTzp/31oq\
952                 VjbpoCxS6vuWAZyADxhISQ==",
953            )
954            .unwrap(),
955            Base64::decode_vec(
956                "is7d0LY4HoXszlC2NO7gejkq7XqL4p1W6hZJPYTNx+r37t1CC2n3Vvzg6kNdpRix\
957                 DhIpXVTLjN9O7UO/XuqSumYKJIKoP52eb4Tg+a3hw5Iz2Zsb5lUTNSLgkQSBPAf7\
958                 1LHxbL82JL4g1nBUog8ae60BwnVArThKY4EwlJguGNw09BAU4lwf6csDl/nX2vfV\
959                 wiAloYpeZkHL+L8m+bueGZM5KE2jEz+7ztZCI+T+E5i69rZEYDjx0lfLKlEhQlCW\
960                 3HbCPELqXgNJJkRfi6MP9kXa9lSfnZmoT081RMvqonB/FUa4HOcKyCrw9XZEtnbN\
961                 CIdbitfDVEX+pSSD7596wQ==",
962            )
963            .unwrap(),
964            Base64::decode_vec(
965                "GPs0injugfycacaeIP5jMa/WX55VEnKLDHom4k6WlfDF4L4gIGoJdekcPEUfxOI5\
966                 faKvHyFwRP1wObkPoRBDM0qZxRfBl4zEtpvjHrd5MibSyJkM8+J0BIKk/nSjbRIG\
967                 eb3hV5O56PvGB3S0dKhCUnuVObiC+ne7izplsD4OTG70l1Yud33UFntyoMxrxGYL\
968                 USqhBMmZfHquJg4NOWOzKNY/K+EcHDLj1Kjvkcgv9Vf7ocsVxvpFdD9uGPceQ6kw\
969                 RDdEl6mb+6FDgWuXVyqR9+904oanEIkbJ7vfkthagLbEf57dyG6nJlqh5FBZWxGI\
970                 R72YGypPuAh7qnnqXXjY2Q==",
971            )
972            .unwrap(),
973            Base64::decode_vec(
974                "CUWC+hRWOT421kwRllgVjy6FYv6jQUcgDNHeAiYZnf5HjS9iK2ki7v8G5dL/0f+Y\
975                 f+NhE/4q8w4m8go51hACrVpP1p8GJDjiT09+RsOzITsHwl+ceEKoe56ZW6iDHBLl\
976                 rNw5/MtcYhKpjNU9KJ2udm5J/c9iislcjgckrZG2IB8ADgXHMEByZ5DgaMl4AKZ1\
977                 Gx8/q6KftTvmOT5rNTMLi76VN5KWQcDWK/DqXiOiZHM7Nr4dX4me3XeRgABJyNR8\
978                 Fqxj3N1+HrYLe/zs7LOaK0++F9Ul3tLelhrhsvLxei3oCZkF9A/foD3on3luYA+1\
979                 cRcxWpSY3h2J4/22+yo4+Q==",
980            )
981            .unwrap(),
982        ];
983
984        let e = BoxedUint::from_be_slice(&e, 64).unwrap();
985
986        let bits = 4096;
987        let n = BoxedUint::from_be_slice(&n, bits).unwrap();
988        let d = BoxedUint::from_be_slice(&d, bits).unwrap();
989        let primes = primes
990            .iter()
991            .map(|p| BoxedUint::from_be_slice(p, bits / 2).unwrap())
992            .collect();
993        let res = RsaPrivateKey::from_components(n, e, d, primes);
994        assert_eq!(res, Err(Error::InvalidModulus));
995    }
996
997    #[test]
998    fn reject_oversized_private_key() {
999        // -----BEGIN PUBLIC KEY-----
1000        // MIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEAkMBiB8qsNVXAsJR6Xoto
1001        // H1r2rtZl/xzUK2tIfy99aPE489u+5tLxCQhQf+a89158vSDpr2/xwgK8w9u0Xpu2
1002        // m7XRKjVMS0Y6UIINFoeTc87rVXT92Scr47kNVcGmSFXez4BSDpS+LKpWwXN+0AQu
1003        // +cmcfdtsx2862iEbqQvq4PwKGQJOdOR0yldH8O4yeJK/buvIOXRHjb++vtQND/xi
1004        // bFGAcd9WJqvaOG7tclhbZ277mbO6ER+y9Lj7AyO8ywybWqNeHaVPHMysPhT7HUWI
1005        // 17m59i1OpuVwwEnvzDQQEUf9d5hUmkLYb5qQzuf6Ddnx/04QJCKAgkhyr9CXgnV6
1006        // vEZ3PKtpicCHRxk7eqTEmgBlgwqH5vflRFV1iywQMXJnuRhzWOQaXl/vb8v4HIvF
1007        // 4TatEZKqfzpbyScLIiYbPEAhHXKdZMd2zY8hkSbicifePApAZmuNpAxxJDZzphh7
1008        // r4lD6t8MPT/RUAdtrZfihqaBhduFI6YeVIy6emg05M6YWvlUyer7nYGaPRS1JqD4
1009        // 0v7xOtme5I8Qw6APiFPXhTqBK3occr7TgGb3V3lpC8Eq+esNHrji98R1fITkFXJW
1010        // KdFcTWjBghPxiobUzMCFUrPIDJcWXeBzrARAryU+hXjEiFfzluXrps0B7RJQ/rLD
1011        // LXeTn4vovUeHQVHa7YfoyWMy9pfqeVC+56LBK7SEIAvL0I3lrq5vIv+ZIuOAdbVg
1012        // JiRy8DneCOk2LP3RnA8M0HSevYW93DiC+4h/l4ntjjiOfi6yRVOZ8WbVyXZ/83j4
1013        // 6+pGWgvi0uMyb+btgOXjBQv7bGqdyHMc5Lqk5bF7ExETx51vKQMYCV4351caS6aX
1014        // q16lYZATHgbTADEAZHdroDMJB+HMQaze9O6qU5ZO8wxxAjw89xry0dnoOQD/yA4H
1015        // 7CRCo9vVDpV2hqIvHY9RI2T7cek28kmQpKvNvvK+ovmM138dHKViWULHk0fBRt7m
1016        // 4wQ+tiL2PmJ/Tr8g1gVhM6S9D1XdE9z0KeDnODCWn1Q8sx2G2ah4ynnYQURDWcwO
1017        // McAoP6bdJ7cCt+4F2tEsMPf4S/EwlnjvuNoQjvztxCPahYe9EnyggtQXyHJveIn7
1018        // gDJsP6b93VB6x4QbLy5ch4DUhqDWginuKVeo7CTgDkq03j/IEaS1BHwreSDQceny
1019        // +bYWONwV+4TMpGytKOHvU5288kmHbyZHdXuaXk8LLqbnqr30fa6Cbp4llCi9sH5a
1020        // Kmi5jxQfVTe+elkMs7oVsLsVgkZS6NqPcOuEckAFijNqG223+IJoqvifCzO5Bdcs
1021        // JTOLE+YaUYc8LUJwIaPykgcXmtMvQjeT8MCQ3aAlzkHfDpSvvICrXtqbGiaKolU6
1022        // mQIDAQAB
1023        // -----END PUBLIC KEY-----
1024
1025        let n = BoxedUint::from_be_slice(
1026            &hex!(
1027                "
1028            90c06207caac3555c0b0947a5e8b681f5af6aed665ff1cd42b6b487f2f7d68f1
1029            38f3dbbee6d2f10908507fe6bcf75e7cbd20e9af6ff1c202bcc3dbb45e9bb69b
1030            b5d12a354c4b463a50820d16879373ceeb5574fdd9272be3b90d55c1a64855de
1031            cf80520e94be2caa56c1737ed0042ef9c99c7ddb6cc76f3ada211ba90beae0fc
1032            0a19024e74e474ca5747f0ee327892bf6eebc83974478dbfbebed40d0ffc626c
1033            518071df5626abda386eed72585b676efb99b3ba111fb2f4b8fb0323bccb0c9b
1034            5aa35e1da54f1cccac3e14fb1d4588d7b9b9f62d4ea6e570c049efcc34101147
1035            fd7798549a42d86f9a90cee7fa0dd9f1ff4e10242280824872afd09782757abc
1036            46773cab6989c08747193b7aa4c49a0065830a87e6f7e54455758b2c10317267
1037            b9187358e41a5e5fef6fcbf81c8bc5e136ad1192aa7f3a5bc9270b22261b3c40
1038            211d729d64c776cd8f219126e27227de3c0a40666b8da40c71243673a6187baf
1039            8943eadf0c3d3fd150076dad97e286a68185db8523a61e548cba7a6834e4ce98
1040            5af954c9eafb9d819a3d14b526a0f8d2fef13ad99ee48f10c3a00f8853d7853a
1041            812b7a1c72bed38066f75779690bc12af9eb0d1eb8e2f7c4757c84e415725629
1042            d15c4d68c18213f18a86d4ccc08552b3c80c97165de073ac0440af253e8578c4
1043            8857f396e5eba6cd01ed1250feb2c32d77939f8be8bd47874151daed87e8c963
1044            32f697ea7950bee7a2c12bb484200bcbd08de5aeae6f22ff9922e38075b56026
1045            2472f039de08e9362cfdd19c0f0cd0749ebd85bddc3882fb887f9789ed8e388e
1046            7e2eb2455399f166d5c9767ff378f8ebea465a0be2d2e3326fe6ed80e5e3050b
1047            fb6c6a9dc8731ce4baa4e5b17b131113c79d6f290318095e37e7571a4ba697ab
1048            5ea56190131e06d300310064776ba0330907e1cc41acdef4eeaa53964ef30c71
1049            023c3cf71af2d1d9e83900ffc80e07ec2442a3dbd50e957686a22f1d8f512364
1050            fb71e936f24990a4abcdbef2bea2f98cd77f1d1ca5625942c79347c146dee6e3
1051            043eb622f63e627f4ebf20d6056133a4bd0f55dd13dcf429e0e73830969f543c
1052            b31d86d9a878ca79d841444359cc0e31c0283fa6dd27b702b7ee05dad12c30f7
1053            f84bf1309678efb8da108efcedc423da8587bd127ca082d417c8726f7889fb80
1054            326c3fa6fddd507ac7841b2f2e5c8780d486a0d68229ee2957a8ec24e00e4ab4
1055            de3fc811a4b5047c2b7920d071e9f2f9b61638dc15fb84cca46cad28e1ef539d
1056            bcf249876f2647757b9a5e4f0b2ea6e7aabdf47dae826e9e259428bdb07e5a2a
1057            68b98f141f5537be7a590cb3ba15b0bb15824652e8da8f70eb847240058a336a
1058            1b6db7f88268aaf89f0b33b905d72c25338b13e61a51873c2d427021a3f29207
1059            179ad32f423793f0c090dda025ce41df0e94afbc80ab5eda9b1a268aa2553a99"
1060            ),
1061            8192,
1062        )
1063        .unwrap();
1064
1065        let e = BoxedUint::from(65_537u64);
1066
1067        assert_eq!(
1068            RsaPublicKey::new(n, e).err().unwrap(),
1069            Error::ModulusTooLarge
1070        );
1071    }
1072
1073    #[test]
1074    #[cfg(feature = "encoding")]
1075    fn build_key_from_primes() {
1076        const RSA_2048_PRIV_DER: &[u8] = include_bytes!("../tests/examples/pkcs8/rsa2048-priv.der");
1077        let ref_key = RsaPrivateKey::from_pkcs8_der(RSA_2048_PRIV_DER).unwrap();
1078        assert_eq!(ref_key.validate(), Ok(()));
1079
1080        let primes = PrivateKeyParts::primes(&ref_key).to_vec();
1081
1082        let exp = PublicKeyParts::e(&ref_key);
1083        let key = RsaPrivateKey::from_primes(primes, exp.clone())
1084            .expect("failed to import key from primes");
1085        assert_eq!(key.validate(), Ok(()));
1086
1087        assert_eq!(PublicKeyParts::n(&key), PublicKeyParts::n(&ref_key));
1088
1089        assert_eq!(PrivateKeyParts::dp(&key), PrivateKeyParts::dp(&ref_key));
1090        assert_eq!(PrivateKeyParts::dq(&key), PrivateKeyParts::dq(&ref_key));
1091
1092        assert_eq!(PrivateKeyParts::d(&key), PrivateKeyParts::d(&ref_key));
1093    }
1094
1095    #[test]
1096    #[cfg(feature = "encoding")]
1097    fn build_key_from_p_q() {
1098        const RSA_2048_SP800_PRIV_DER: &[u8] =
1099            include_bytes!("../tests/examples/pkcs8/rsa2048-sp800-56b-priv.der");
1100        let ref_key = RsaPrivateKey::from_pkcs8_der(RSA_2048_SP800_PRIV_DER).unwrap();
1101        assert_eq!(ref_key.validate(), Ok(()));
1102
1103        let primes = PrivateKeyParts::primes(&ref_key).to_vec();
1104        let exp = PublicKeyParts::e(&ref_key);
1105
1106        let key = RsaPrivateKey::from_p_q(primes[0].clone(), primes[1].clone(), exp.clone())
1107            .expect("failed to import key from primes");
1108        assert_eq!(key.validate(), Ok(()));
1109
1110        assert_eq!(PublicKeyParts::n(&key), PublicKeyParts::n(&ref_key));
1111
1112        assert_eq!(PrivateKeyParts::dp(&key), PrivateKeyParts::dp(&ref_key));
1113        assert_eq!(PrivateKeyParts::dq(&key), PrivateKeyParts::dq(&ref_key));
1114
1115        assert_eq!(PrivateKeyParts::d(&key), PrivateKeyParts::d(&ref_key));
1116    }
1117}