Skip to main content

rsa/
key.rs

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/// Represents the public part of an RSA key.
31#[derive(Debug, Clone)]
32pub struct RsaPublicKey {
33    /// Modulus: product of prime numbers `p` and `q`
34    n: NonZero<BoxedUint>,
35    /// Public exponent: power to which a plaintext message is raised in
36    /// order to encrypt it.
37    ///
38    /// Typically `0x10001` (`65537`)
39    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        // Domain separator for RSA private keys
56        state.write(b"RsaPublicKey");
57        // TODO(tarcieri): to match the `PartialEq` impl we should strip leading zeros
58        Hash::hash(&self.n.as_limbs(), state);
59        Hash::hash(&self.e.as_limbs(), state);
60    }
61}
62
63/// Represents a whole RSA key, public and private parts.
64#[derive(Clone)]
65pub struct RsaPrivateKey {
66    /// Public components of the private key.
67    pubkey_components: RsaPublicKey,
68    /// Private exponent
69    pub(crate) d: BoxedUint,
70    /// Prime factors of N, contains >= 2 elements.
71    pub(crate) primes: Vec<BoxedUint>,
72    /// Precomputed values to speed up private operations
73    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        // Domain separator for RSA private keys
111        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    /// D mod (P-1)
129    pub(crate) dp: BoxedUint,
130    /// D mod (Q-1)
131    pub(crate) dq: BoxedUint,
132    /// Q^-1 mod P
133    pub(crate) qinv: BoxedMontyForm,
134
135    /// Montgomery params for `p`
136    pub(crate) p_params: BoxedMontyParams,
137    /// Montgomery params for `q`
138    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        // TODO: once these have landed in crypto-bigint
148        // self.p_params.zeroize();
149        // self.q_params.zeroize();
150    }
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    /// Encrypt the given message.
194    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    /// Verify a signed message.
204    ///
205    /// `hashed` must be the result of hashing the input using the hashing function
206    /// passed in through `hash`.
207    ///
208    /// If the message is valid `Ok(())` is returned, otherwise an `Err` indicating failure.
209    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    /// Minimum value of the public exponent `e`.
216    pub const MIN_PUB_EXPONENT: u64 = 2;
217
218    /// Maximum value of the public exponent `e`.
219    ///
220    /// Very large public exponents are a potential denial-of-service vector (a.k.a. "RSADoS")
221    /// because they increase the amount of work required for e.g. signature verification. See:
222    ///
223    /// <https://www.imperialviolet.org/2012/03/17/rsados.html>
224    ///
225    /// The particular constant below has been chosen to align with *ring* where this value was
226    /// selected based on the history of this particular issue, API compatibility concerns, and
227    /// benchmark-driven evaluation. See RustCrypto/RSA#155.
228    ///
229    /// If for some reason you have a legitimate reason to use keys with public exponents larger
230    /// than this value, use the special APIs:
231    ///
232    /// - [`RsaPublicKey::new_with_large_exp`]
233    /// - [`RsaPrivateKey::from_components_with_large_exponent`]
234    pub const MAX_PUB_EXPONENT: u64 = (1 << 33) - 1;
235
236    /// Maximum size of the modulus `n` in bits.
237    pub const MAX_SIZE: usize = 8192;
238
239    /// Create a new public key from its components.
240    ///
241    /// This function accepts public keys with a modulus size up to 8192-bits,
242    /// i.e. [`RsaPublicKey::MAX_SIZE`].
243    pub fn new(n: BoxedUint, e: BoxedUint) -> Result<Self> {
244        Self::new_with_max_size(n, e, Self::MAX_SIZE)
245    }
246
247    /// Create a new public key from its components.
248    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    /// Create a new public key, bypassing checks around the modulus and public
261    /// exponent size.
262    ///
263    /// This method is not recommended, and only intended for unusual use cases.
264    /// Most applications should use [`RsaPublicKey::new`] or
265    /// [`RsaPublicKey::new_with_max_size`] instead.
266    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    /// Default exponent for RSA keys.
291    const EXP: u64 = 65537;
292
293    /// Minimum size of the modulus `n` in bits. Currently only applies to keygen.
294    const MIN_SIZE: u32 = 1024;
295
296    /// Generate a new RSA key pair with a modulus of the given bit size using the passed in `rng`.
297    ///
298    /// # Errors
299    /// - If `bit_size` is lower than the minimum 1024-bits.
300    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    /// Generate a new RSA key pair of the given bit size.
305    ///
306    /// #⚠️Warning: Hazmat!
307    /// This version does not apply minimum key size checks, and as such may generate keys
308    /// which are insecure!
309    #[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    /// Generate a new RSA key pair of the given bit size and the public exponent
315    /// using the passed in `rng`.
316    ///
317    /// Unless you have specific needs, you should use [`RsaPrivateKey::new`] instead.
318    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    /// Generate a new RSA key pair of the given bit size and the public exponent
337    /// using the passed in `rng`.
338    ///
339    /// Unless you have specific needs, you should use [`RsaPrivateKey::new`] instead.
340    ///
341    /// #⚠️Warning: Hazmat!
342    /// This version does not apply minimum key size checks, and as such may generate keys
343    /// which are insecure!
344    #[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    /// Private helper function that constructs an RSA key pair from components
360    /// WITHOUT performing any validation or precomputation.
361    ///
362    /// This is the shared implementation used by `from_components` and
363    /// `from_components_with_large_exponent`.
364    ///
365    /// Callers are responsible for:
366    /// 1. Validating the key (to ensure precomputation won't fail)
367    /// 2. Calling precompute() after validation
368    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        // The modulus may come in padded with zeros, shorten it
377        // to ensure optimal performance of arithmetic operations.
378        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                // Recover `p` and `q` from `d`.
389                // See method in Appendix C.2: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf
390                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                // Check that the product of primes matches the modulus.
397                // This also ensures that `bit_precision` of each prime is <= that of the modulus,
398                // and `bit_precision` of their product is >= that of the modulus.
399                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        // The primes may come in padded with zeros too, so we need to shorten them as well.
410        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    /// Constructs an RSA key pair from individual components, accepting exponents outside
433    /// the normal size bounds.
434    ///
435    /// See [`RsaPrivateKey::from_components`] for an explanation on the parameters.
436    ///
437    /// # ⚠️ Warning: Hazmat!
438    ///
439    /// This method accepts public exponents outside the standard bounds (2 ≤ e ≤ 2^33-1),
440    /// but still performs full cryptographic validation to ensure the key is mathematically
441    /// correct (i.e., verifies that de ≡ 1 mod λ(n)).
442    ///
443    /// **Note:** This method is dangerous as it can be used as a DOS vector if used with
444    /// untrusted input https://www.imperialviolet.org/2012/03/17/rsados.html
445    ///
446    /// This is intended for interoperating with systems that use non-standard exponents
447    /// or loading legacy keys. Use [`RsaPrivateKey::from_components`] for standard key
448    /// construction.
449    #[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 everything except exponent size bounds (to ensure precompute can't fail)
459        validate_skip_exponent_size(&k)?;
460
461        // Precompute when possible, ignore error otherwise.
462        k.precompute().ok();
463
464        Ok(k)
465    }
466
467    /// Constructs an RSA key pair from individual components:
468    ///
469    /// - `n`: RSA modulus
470    /// - `e`: public exponent (i.e. encrypting exponent)
471    /// - `d`: private exponent (i.e. decrypting exponent)
472    /// - `primes`: prime factors of `n`: typically two primes `p` and `q`. More than two primes can
473    ///   be provided for multiprime RSA, however this is generally not recommended. If no `primes`
474    ///   are provided, a prime factor recovery algorithm will be employed to attempt to recover the
475    ///   factors (as described in [NIST SP 800-56B Revision 2] Appendix C.2). This algorithm only
476    ///   works if there are just two prime factors `p` and `q` (as opposed to multiprime), and `e`
477    ///   is between 2^16 and 2^256.
478    ///
479    ///  [NIST SP 800-56B Revision 2]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf
480    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        // Always validate the key, to ensure precompute can't fail
489        k.validate()?;
490
491        // Precompute when possible, ignore error otherwise.
492        k.precompute().ok();
493
494        Ok(k)
495    }
496
497    /// Constructs an RSA key pair from its two primes p and q.
498    ///
499    /// This will rebuild the private exponent and the modulus.
500    ///
501    /// Private exponent will be rebuilt using the method defined in
502    /// [NIST 800-56B Section 6.2.1](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf#page=47).
503    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    /// Constructs an RSA key pair from its primes.
520    ///
521    /// This will rebuild the private exponent and the modulus.
522    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        // Makes sure that the primes are pairwise unequal.
531        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    /// Get the public key from the private key.
546    ///
547    /// Specific alternative to [`AsRef::as_ref`].
548    pub fn as_public_key(&self) -> &RsaPublicKey {
549        &self.pubkey_components
550    }
551
552    /// Get the public key from the private key, cloning `n` and `e`.
553    ///
554    /// Generally this is not needed since `RsaPrivateKey` implements the `PublicKey` trait,
555    /// but it can occasionally be useful to discard the private information entirely.
556    pub fn to_public_key(&self) -> RsaPublicKey {
557        self.pubkey_components.clone()
558    }
559
560    /// Performs some calculations to speed up private key operations.
561    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        // Note that since `p` and `q` may have different `bits_precision`,
590        // so we have to equalize them to calculate the remainder.
591        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    /// Clears precomputed values by setting to None
625    pub fn clear_precomputed(&mut self) {
626        self.precomputed = None;
627    }
628
629    /// Compute CRT coefficient: `(1/q) mod p`.
630    pub fn crt_coefficient(&self) -> Option<BoxedUint> {
631        let p = &self.primes[0];
632        let q = &self.primes[1];
633        // TODO: maybe store primes as `NonZero`?
634        Option::from(q.invert_mod(&NonZero::new(p.clone()).expect("prime")))
635    }
636
637    /// Performs basic sanity checks on the key.
638    /// Returns `Ok(())` if everything is good, otherwise an appropriate error.
639    pub fn validate(&self) -> Result<()> {
640        check_public(self)?;
641        validate_private_key_parts(self)?;
642        Ok(())
643    }
644
645    /// Decrypt the given message.
646    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    /// Decrypt the given message.
651    ///
652    /// Uses `rng` to blind the decryption process.
653    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    /// Sign the given digest.
663    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    /// Sign the given digest using the provided `rng`, which is used in the
668    /// following ways depending on the [`SignatureScheme`]:
669    ///
670    /// - [`Pkcs1v15Sign`][`crate::Pkcs1v15Sign`] padding: uses the RNG
671    ///   to mask the private key operation with random blinding, which helps
672    ///   mitigate sidechannel attacks.
673    /// - [`Pss`][`crate::Pss`] always requires randomness. Use
674    ///   [`Pss::new`][`crate::Pss::new`] for a standard RSASSA-PSS signature, or
675    ///   [`Pss::new_blinded`][`crate::Pss::new_blinded`] for RSA-BSSA blind
676    ///   signatures.
677    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/// Check that the public key is well formed and has an exponent within acceptable bounds.
722#[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/// Check that the public key is well formed and has an exponent within acceptable bounds.
728#[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/// Check that the public key is well formed, skipping exponent size bounds checks.
750///
751/// This is used internally by both public validation functions and hazmat APIs.
752#[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    // Skip exponent size bounds checks
763    Ok(())
764}
765
766/// Helper function that validates the private key structure and cryptographic correctness.
767///
768/// This performs the structural and mathematical validation checks that are common to both
769/// `validate()` and `validate_skip_exponent_size()`.
770fn validate_private_key_parts(key: &RsaPrivateKey) -> Result<()> {
771    // Check that Πprimes == n.
772    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        // Any primes ≤ 1 will cause divide-by-zero panics later.
776        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    // Check that de ≡ 1 mod p-1, for each prime.
786    // This implies that e is coprime to each p-1 as e has a multiplicative
787    // inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) =
788    // exponent(ℤ/nℤ). It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1
789    // mod p. Thus a^de ≡ a mod n for all a coprime to n, as required.
790    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/// Validate the private key structure and cryptographic correctness,
804/// skipping only the exponent size bounds checks.
805///
806/// This performs all the same checks as `RsaPrivateKey::validate()` except
807/// it doesn't verify that the exponent is within the standard bounds.
808#[cfg(feature = "hazmat")]
809fn validate_skip_exponent_size(key: &RsaPrivateKey) -> Result<()> {
810    // Check public key properties (without exponent size checks)
811    check_public_skip_exponent_size(key.pubkey_components.n.as_ref(), &key.pubkey_components.e)?;
812
813    // Perform common private key validation
814    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        // -----BEGIN PUBLIC KEY-----
1111        // MIIEKjANBgkqhkiG9w0BAQEFAAOCBBcAMIIEEgKCBAkAqQn6O7pd9ioQJEOwS2sh
1112        // nD2bM3+PaLovro+OKOE9t7jxrp+b9Xq81oeT6zN5u5yPewa+V08ZsAJQEbF9D5AM
1113        // UZkHZc/sW/XAItC8CojQhHoCQfjOXZpONmGsQxnSJNgwLV5TDVKUApbQIPzIm9yD
1114        // wOvl1yXIypaRINHzthz36ysHmaHlNVZZQ40BHVkOiUd+ws7W9U9vHN0QcaSHC8lH
1115        // UEqb/Iyb0FSmZs+qbm4NXyaI90oloAFftOnt8VFbHfT/TXS0VwMyescxFsuvcuTr
1116        // Xx8EYc9TuJThW22wBAFOK6SpftgtZ6i4WJqk0F8JrTwZ3TyhzKsPRwe8KeNmtmqY
1117        // oaGiPj9lUOc928QzOyTETVd8pV7UpnaOe9Q4WHL0QmnXn61pCu4qpoLuK8jB+IO7
1118        // xifRZHj3PMfsjJurZ4MF57LgpSrI60ekYNh1o6ViXODHQuzGxzTaF3n/7GITDBQX
1119        // DRTlGuQH77hykxFqPclRGI0wxECPKasxpzjhiaTua9eipKedXB+o5XFyosnDt/X4
1120        // Ygqxj/q2/18LPuQgFLqWRzsHd4TdVQyiq9xCmzIoGUjAPz1Q8cjIXRpUnp2rZQjE
1121        // SCLeTjewrGNbjSMDUhdF5M2OBRmn7Q8XHHCUxT9fY/BZeydeE54KvEdEkomxkbXo
1122        // hHKEmbWeEdhp78h04/xW364p1Nu9Y49w7gtO+9nmwKcpNJq32M6Qb0d2dQ3wJ0oI
1123        // I9ml+n/DTna+IIwwbI8UOFEI4KZQzZaqmNv3TzGmpnocHK7eMyEtAUeQZUIGrPmr
1124        // FQEmKZn9rkgr/2Hw8T20q7e0lE65Is69vTP2wXm17B5zKFYska41jJoZ6jIpbMOt
1125        // uVPZV3SoGYM39Z4Ax3JaGZE0L/dQ6lJJhdFUACFIQXwNWqzd7srnvbym4hLqoPuM
1126        // hjkUtTcv6YODEk7LB2FLDcymmH/zCL3w4VSi4+HyZZ13gM7Cz8WmkX4H+jeL0+Ja
1127        // QyG1CzqV/HA78vUpJv/bb/J1+X1i/1HltLeTjteY4rBhVT1cxBoVBGQaCwindAs+
1128        // Fjcp+8cAK+/3pMQghnkrGHzrx9YIYoOGXs4vQIMGngYaTa7aXAaft4fWjg4EeSjd
1129        // rZwqqrPNuUcEuneFP9RPffj8f3vkhqCFgoVBfVM7ontu2d2nRu/hhAkgT13Uc68J
1130        // dM2imBvHAo6DDUt6msWCAMOAEXYuO7aA+n3eettnBqtECoQAoCJdCHCebjIploMB
1131        // XMLXyseGtLK9arI48hDvcxSlf7/1lkBB6LgNQmQJ7925TDipiYQIZ63f4d5Z2JCp
1132        // W0vUkwzrH4iPb2hy+TBQSOw1kvjLyG/lHWjzDQa60xxVW9u59DxQueHsNEMHUORD
1133        // 1oFXvFLe/AllAgMBAAE=
1134        // -----END PUBLIC KEY-----
1135
1136        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        // Test that from_components_with_large_exponent accepts exponents outside normal bounds
1233        // while from_components would reject them
1234
1235        use rand::rngs::ChaCha8Rng;
1236        use rand_core::SeedableRng;
1237
1238        let mut rng = ChaCha8Rng::from_seed([42; 32]);
1239
1240        // Use an exponent larger than the normal maximum (2^33 - 1)
1241        let large_e = BoxedUint::from((1u64 << 34) + 1); // 2^34 + 1 (odd number)
1242
1243        // Generate a key with this large exponent
1244        let components =
1245            generate_multi_prime_key_with_exp(&mut rng, 2, 1024, large_e.clone()).unwrap();
1246
1247        // Extract components
1248        let n = components.n.get().clone();
1249        let d = components.d;
1250        let primes = components.primes;
1251
1252        // from_components should fail with PublicExponentTooLarge
1253        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        // from_components_with_large_exponent should succeed
1259        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        // Verify that the key is still cryptographically valid (de ≡ 1 mod λ(n))
1273        // by checking that validation with skip_exponent_size passes
1274        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        // Test that from_components_with_large_exponent accepts exponents below normal minimum
1281        // (despite the name, it works for any non-standard exponent size)
1282
1283        use rand::rngs::ChaCha8Rng;
1284        use rand_core::SeedableRng;
1285
1286        let mut rng = ChaCha8Rng::from_seed([43; 32]);
1287
1288        // Use an exponent smaller than the normal minimum (2)
1289        let small_e = BoxedUint::from(1u64); // This is odd, which is required
1290
1291        // Generate a key with this small exponent
1292        let components =
1293            generate_multi_prime_key_with_exp(&mut rng, 2, 1024, small_e.clone()).unwrap();
1294
1295        // Extract components
1296        let n = components.n.get().clone();
1297        let d = components.d;
1298        let primes = components.primes;
1299
1300        // from_components should fail
1301        let result =
1302            RsaPrivateKey::from_components(n.clone(), small_e.clone(), d.clone(), primes.clone());
1303        assert!(result.is_err());
1304
1305        // from_components_with_large_exponent should succeed
1306        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        // Verify that the key is cryptographically valid
1318        assert!(validate_skip_exponent_size(&key_with_small_exp).is_ok());
1319    }
1320
1321    /// Regression test for CVE-2026-21895 / GHSA-9c48-w39g-hm26.
1322    ///
1323    /// Loading a secret key whose prime factor is `1` must be rejected with
1324    /// `Error::InvalidPrime` rather than panicking via a divide-by-zero in
1325    /// the validation/precompute path.
1326    ///
1327    /// Adapted from the test added in upstream commit 2926c91bef (PR #624);
1328    /// the original used `num-bigint` `BigUint` types, this version uses
1329    /// `crypto-bigint` `BoxedUint` and goes through
1330    /// `from_components_with_large_exponent` so the small (out-of-range) `e`
1331    /// can be supplied verbatim from the original test.
1332    #[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}