Skip to main content

rsa/
pkcs1v15.rs

1//! PKCS#1 v1.5 support as described in [RFC8017 § 8.2].
2//!
3//! <div class="warning">
4//! <b>Warning</b>
5//!
6//! PKCS#1 v1.5 padding has a longstanding history of issues generally classed as
7//! [Bleichenbacher Attacks] which were originally discovered in 1998 but keep reappearing in
8//! various forms again and again over the course of decades, including most recently in the 2023
9//! [Marvin Attack], which the `rsa` crate is [still vulnerable] to.
10//!
11//! These attacks can result in complete plaintext recovery for encryption, or signature forgery,
12//! leading to a total failure of either confidentiality or integrity.
13//!
14//! Unless explicitly needed for compatibility reasons, we recommend against using PKCS#1 v1.5,
15//! and suggest using [PSS][`super::pss`] or [OAEP][`super::oaep`] instead (if there is a
16//! requirement to use RSA).
17//! </div>
18//!
19//! [Bleichenbacher Attacks]: https://en.wikipedia.org/wiki/Adaptive_chosen-ciphertext_attack#Practical_attacks
20//! [Marvin Attack]: https://people.redhat.com/~hkario/marvin/
21//! [still vulnerable]: https://github.com/RustCrypto/RSA/issues/626
22//!
23//! # Usage
24//!
25//! See [code example in the toplevel rustdoc](../index.html#pkcs1-v15-signatures).
26//!
27//! [RFC8017 § 8.2]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.2
28
29#[cfg(feature = "alloc")]
30mod decrypting_key;
31mod encrypting_key;
32mod generic_signing_key;
33mod signature;
34#[cfg(feature = "alloc")]
35mod signing_key;
36mod verifying_key;
37
38pub use self::generic_signing_key::GenericSigningKey;
39#[cfg(feature = "alloc")]
40pub use self::{
41    decrypting_key::DecryptingKey,
42    encrypting_key::GenericEncryptingKey,
43    signature::{GenericSignature, SignatureBytes},
44    signing_key::SigningKey,
45    verifying_key::GenericVerifyingKey,
46};
47#[cfg(not(feature = "alloc"))]
48pub use self::{
49    encrypting_key::GenericEncryptingKey,
50    signature::{GenericSignature, SignatureBytes},
51    verifying_key::GenericVerifyingKey,
52};
53
54#[cfg(feature = "alloc")]
55pub use self::{encrypting_key::EncryptingKey, signature::Signature, verifying_key::VerifyingKey};
56
57#[cfg(feature = "alloc")]
58use alloc::{boxed::Box, vec, vec::Vec};
59use const_oid::AssociatedOid;
60use core::fmt::Debug;
61#[cfg(feature = "alloc")]
62use crypto_bigint::BoxedUint;
63use digest::Digest;
64use rand_core::TryCryptoRng;
65
66use crate::algorithms::pad::uint_to_be_pad_into;
67#[cfg(feature = "alloc")]
68use crate::algorithms::pad::uint_to_zeroizing_be_pad;
69use crate::algorithms::pkcs1v15::*;
70#[cfg(not(feature = "alloc"))]
71use crate::algorithms::rsa::rsa_encrypt;
72#[cfg(feature = "alloc")]
73use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt};
74use crate::errors::{Error, Result};
75#[cfg(feature = "alloc")]
76use crate::key::{self, RsaPrivateKey};
77use crate::traits::{PaddingScheme, PublicKeyParts, SignatureScheme, UnsignedModularInt};
78
79/// Encryption using PKCS#1 v1.5 padding.
80#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
81pub struct Pkcs1v15Encrypt;
82
83impl Pkcs1v15Encrypt {
84    /// Encrypts the given message with RSA and PKCS#1 v1.5 padding into caller-provided storage.
85    ///
86    /// The message must be no longer than the length of the public modulus minus 11 bytes.
87    pub fn encrypt_into<'a, R, K, T>(
88        self,
89        rng: &mut R,
90        pub_key: &K,
91        msg: &[u8],
92        storage: &'a mut [u8],
93    ) -> Result<&'a [u8]>
94    where
95        R: TryCryptoRng + ?Sized,
96        T: UnsignedModularInt,
97        K: PublicKeyParts<T>,
98        K::MontyParams: crate::traits::modular::CtModulusParams,
99    {
100        let padded_len = pub_key.size();
101        let em = pkcs1v15_encrypt_pad_into(rng, msg, padded_len, storage)?;
102        let int = T::try_from_be_bytes_vartime(em)?;
103
104        uint_to_be_pad_into(rsa_encrypt(pub_key, &int)?, padded_len, storage)
105    }
106}
107
108/// Encrypts the given message with RSA and the padding
109/// scheme from PKCS#1 v1.5. The message must be no longer than the
110/// length of the public modulus minus 11 bytes.
111#[cfg(feature = "alloc")]
112#[inline]
113#[allow(dead_code)] // Vec-returning convenience wrapper; kept alongside the buffer-taking `encrypt_into`.
114fn encrypt<R: TryCryptoRng + ?Sized, K, T>(rng: &mut R, pub_key: &K, msg: &[u8]) -> Result<Vec<u8>>
115where
116    T: UnsignedModularInt,
117    K: PublicKeyParts<T>,
118    K::MontyParams: crate::traits::modular::CtModulusParams,
119{
120    let mut storage = vec![0u8; pub_key.size()];
121    let ciphertext = Pkcs1v15Encrypt.encrypt_into(rng, pub_key, msg, &mut storage)?;
122    Ok(ciphertext.to_vec())
123}
124
125#[cfg(not(feature = "alloc"))]
126#[derive(Clone, Debug, Eq, PartialEq)]
127pub(super) struct Prefix<const N: usize = 32> {
128    data: [u8; N],
129    len: usize,
130}
131
132#[cfg(not(feature = "alloc"))]
133impl<const N: usize> Prefix<N> {
134    pub const fn new() -> Self {
135        Self {
136            data: [0u8; N],
137            len: 0,
138        }
139    }
140
141    pub fn from_slice(input: &[u8]) -> Result<Self> {
142        let mut out = Self::new();
143        // Fallible `get_mut` + byte-copy loop (no `[..]` indexing /
144        // `copy_from_slice`) so no `slice_index_fail` / `copy_from_slice`
145        // panic path is synthesized into the (embedded) sign binary. The
146        // `get_mut` also subsumes the `input.len() > N` bounds check.
147        let dst = out
148            .data
149            .get_mut(..input.len())
150            .ok_or(Error::OutputBufferTooSmall)?;
151        for (d, s) in dst.iter_mut().zip(input.iter()) {
152            *d = *s;
153        }
154        out.len = input.len();
155        Ok(out)
156    }
157}
158
159#[cfg(not(feature = "alloc"))]
160impl<const N: usize> AsRef<[u8]> for Prefix<N> {
161    fn as_ref(&self) -> &[u8] {
162        // `get(..len)` rather than `[..len]` so no `slice_index_fail`
163        // panic path is synthesized; `len <= N` always holds (set only in
164        // `from_slice` after a bounded `get_mut`), so the fallback is dead.
165        self.data.get(..self.len).unwrap_or(&[])
166    }
167}
168
169#[cfg(not(feature = "alloc"))]
170pub(super) fn pkcs1v15_generate_prefix_helper<D>() -> Prefix
171where
172    D: Digest + AssociatedOid,
173{
174    let mut tmp_prefix = [0u8; 64];
175    let prefix =
176        pkcs1v15_generate_prefix_into::<D>(&mut tmp_prefix).expect("prefix buffer is too small");
177    Prefix::from_slice(prefix).expect("prefix buffer is too small")
178}
179
180impl PaddingScheme for Pkcs1v15Encrypt {
181    #[cfg(feature = "alloc")]
182    fn decrypt<Rng: TryCryptoRng + ?Sized>(
183        self,
184        rng: Option<&mut Rng>,
185        priv_key: &RsaPrivateKey,
186        ciphertext: &[u8],
187    ) -> Result<Vec<u8>> {
188        decrypt(rng, priv_key, ciphertext)
189    }
190
191    #[cfg(feature = "alloc")]
192    fn encrypt<Rng, K, T>(self, rng: &mut Rng, pub_key: &K, msg: &[u8]) -> Result<Vec<u8>>
193    where
194        Rng: TryCryptoRng + ?Sized,
195        T: UnsignedModularInt,
196        K: PublicKeyParts<T>,
197        K::MontyParams: crate::traits::modular::CtModulusParams,
198    {
199        let mut storage = vec![0u8; pub_key.size()];
200        let ciphertext = self.encrypt_into(rng, pub_key, msg, &mut storage)?;
201        Ok(ciphertext.to_vec())
202    }
203}
204
205/// `RSASSA-PKCS1-v1_5`: digital signatures using PKCS#1 v1.5 padding.
206#[derive(Clone, Debug, Eq, PartialEq)]
207pub struct Pkcs1v15Sign {
208    /// Length of hash to use.
209    pub hash_len: Option<usize>,
210
211    /// Prefix.
212    #[cfg(feature = "alloc")]
213    prefix: Box<[u8]>,
214    #[cfg(not(feature = "alloc"))]
215    prefix: Prefix,
216}
217
218impl Pkcs1v15Sign {
219    /// Create new PKCS#1 v1.5 padding for the given digest.
220    ///
221    /// The digest must have an [`AssociatedOid`]. Make sure to enable the `oid`
222    /// feature of the relevant digest crate.
223    pub fn new<D>() -> Self
224    where
225        D: Digest + AssociatedOid,
226    {
227        Self {
228            hash_len: Some(<D as Digest>::output_size()),
229            #[cfg(feature = "alloc")]
230            prefix: pkcs1v15_generate_prefix::<D>().into_boxed_slice(),
231            #[cfg(not(feature = "alloc"))]
232            prefix: pkcs1v15_generate_prefix_helper::<D>(),
233        }
234    }
235
236    /// Create new PKCS#1 v1.5 padding for computing an unprefixed signature.
237    ///
238    /// This sets `hash_len` to `None` and uses an empty `prefix`.
239    pub fn new_unprefixed() -> Self {
240        Self {
241            hash_len: None,
242            #[cfg(feature = "alloc")]
243            prefix: Box::new([]),
244            #[cfg(not(feature = "alloc"))]
245            prefix: Prefix::new(),
246        }
247    }
248}
249
250impl SignatureScheme for Pkcs1v15Sign {
251    #[cfg(feature = "alloc")]
252    fn sign<Rng: TryCryptoRng + ?Sized>(
253        self,
254        rng: Option<&mut Rng>,
255        priv_key: &RsaPrivateKey,
256        hashed: &[u8],
257    ) -> Result<Vec<u8>> {
258        if let Some(hash_len) = self.hash_len {
259            if hashed.len() != hash_len {
260                return Err(Error::InputNotHashed);
261            }
262        }
263
264        sign(rng, priv_key, &self.prefix, hashed)
265    }
266
267    fn verify<K, T>(self, pub_key: &K, hashed: &[u8], sig: &[u8]) -> Result<()>
268    where
269        T: UnsignedModularInt,
270        K: PublicKeyParts<T>,
271    {
272        if let Some(hash_len) = self.hash_len {
273            if hashed.len() != hash_len {
274                return Err(Error::InputNotHashed);
275            }
276        }
277
278        if sig.len() != pub_key.size() {
279            return Err(Error::Verification);
280        }
281
282        let mut storage = pub_key.n().as_ref().to_be_bytes();
283        let sig = T::try_from_be_bytes_vartime(sig).map_err(|_| Error::Verification)?;
284        verify_generic(
285            pub_key,
286            self.prefix.as_ref(),
287            hashed,
288            &sig,
289            storage.as_mut(),
290        )
291    }
292}
293
294/// Encrypts the given message with RSA and the padding
295/// scheme from PKCS#1 v1.5.  The message must be no longer than the
296/// length of the public modulus minus 11 bytes.
297#[inline]
298pub fn encrypt_into<'a, R, K, T>(
299    rng: &mut R,
300    pub_key: &K,
301    msg: &[u8],
302    storage: &'a mut [u8],
303) -> Result<&'a [u8]>
304where
305    R: TryCryptoRng + ?Sized,
306    T: UnsignedModularInt,
307    K: PublicKeyParts<T>,
308    K::MontyParams: crate::traits::modular::CtModulusParams,
309{
310    Pkcs1v15Encrypt.encrypt_into(rng, pub_key, msg, storage)
311}
312
313/// Decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
314///
315/// If an `rng` is passed, it uses RSA blinding to avoid timing side-channel attacks.
316///
317/// Note that whether this function returns an error or not discloses secret
318/// information. If an attacker can cause this function to run repeatedly and
319/// learn whether each instance returned an error then they can decrypt and
320/// forge signatures as if they had the private key. See
321/// `decrypt_session_key` for a way of solving this problem.
322#[cfg(feature = "alloc")]
323#[inline]
324fn decrypt<R: TryCryptoRng + ?Sized>(
325    rng: Option<&mut R>,
326    priv_key: &RsaPrivateKey,
327    ciphertext: &[u8],
328) -> Result<Vec<u8>> {
329    key::check_public(priv_key)?;
330
331    let ciphertext = BoxedUint::from_be_slice(ciphertext, priv_key.n_bits_precision())?;
332    let em = rsa_decrypt_and_check(priv_key, rng, &ciphertext)?;
333    let em = uint_to_zeroizing_be_pad(em, priv_key.size())?;
334
335    pkcs1v15_encrypt_unpad(em, priv_key.size())
336}
337
338/// Calculates the signature of hashed using
339/// RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5. Note that `hashed` must
340/// be the result of hashing the input message using the given hash
341/// function. If hash is `None`, hashed is signed directly. This isn't
342/// advisable except for interoperability.
343///
344/// If `rng` is not `None` then RSA blinding will be used to avoid timing
345/// side-channel attacks.
346///
347/// This function is deterministic. Thus, if the set of possible
348/// messages is small, an attacker may be able to build a map from
349/// messages to signatures and identify the signed messages. As ever,
350/// signatures provide authenticity, not confidentiality.
351#[cfg(feature = "alloc")]
352#[inline]
353fn sign<R: TryCryptoRng + ?Sized>(
354    rng: Option<&mut R>,
355    priv_key: &RsaPrivateKey,
356    prefix: &[u8],
357    hashed: &[u8],
358) -> Result<Vec<u8>> {
359    let em = pkcs1v15_sign_pad(prefix, hashed, priv_key.size())?;
360
361    let em = BoxedUint::from_be_slice(&em, priv_key.n_bits_precision())?;
362    uint_to_zeroizing_be_pad(rsa_decrypt_and_check(priv_key, rng, &em)?, priv_key.size())
363}
364
365/// Verifies an RSA PKCS#1 v1.5 signature.
366#[inline]
367pub(crate) fn verify_generic<K, T>(
368    pub_key: &K,
369    prefix: &[u8],
370    hashed: &[u8],
371    sig: &T,
372    storage: &mut [u8],
373) -> Result<()>
374where
375    T: UnsignedModularInt,
376    K: PublicKeyParts<T>,
377{
378    let n = pub_key.n();
379    if sig >= n.as_ref() || sig.bits_precision() != pub_key.n_bits_precision() {
380        return Err(Error::Verification);
381    }
382
383    let em = uint_to_be_pad_into(rsa_encrypt(pub_key, sig)?, pub_key.size(), storage)?;
384
385    pkcs1v15_sign_unpad(prefix, hashed, em, pub_key.size())
386}
387
388mod oid {
389    use const_oid::ObjectIdentifier;
390
391    /// A trait which associates an RSA-specific OID with a type.
392    pub trait RsaSignatureAssociatedOid {
393        /// The OID associated with this type.
394        const OID: ObjectIdentifier;
395    }
396
397    #[cfg(feature = "sha1")]
398    impl RsaSignatureAssociatedOid for sha1::Sha1 {
399        const OID: ObjectIdentifier =
400            const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.5");
401    }
402
403    #[cfg(feature = "sha2")]
404    impl RsaSignatureAssociatedOid for sha2::Sha224 {
405        const OID: ObjectIdentifier =
406            const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.14");
407    }
408
409    #[cfg(feature = "sha2")]
410    impl RsaSignatureAssociatedOid for sha2::Sha256 {
411        const OID: ObjectIdentifier =
412            const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.11");
413    }
414
415    #[cfg(feature = "sha2")]
416    impl RsaSignatureAssociatedOid for sha2::Sha384 {
417        const OID: ObjectIdentifier =
418            const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.12");
419    }
420
421    #[cfg(feature = "sha2")]
422    impl RsaSignatureAssociatedOid for sha2::Sha512 {
423        const OID: ObjectIdentifier =
424            const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.13");
425    }
426}
427
428pub use oid::RsaSignatureAssociatedOid;
429
430#[cfg(test)]
431#[cfg(feature = "alloc")]
432mod tests {
433    use super::*;
434    use ::signature::{
435        hazmat::{PrehashSigner, PrehashVerifier},
436        DigestSigner, DigestVerifier, Keypair, RandomizedDigestSigner, RandomizedSigner,
437        SignatureEncoding, Signer, Verifier,
438    };
439    use base64ct::{Base64, Encoding};
440    use hex_literal::hex;
441    use rand::rngs::ChaCha8Rng;
442    use rand_core::{Rng, SeedableRng};
443    use rstest::rstest;
444    use sha1::{Digest, Sha1};
445    use sha2::Sha256;
446    use sha3::Sha3_256;
447
448    use crate::traits::{
449        Decryptor, EncryptingKeypair, PublicKeyParts, RandomizedDecryptor, RandomizedEncryptor,
450    };
451    use crate::{RsaPrivateKey, RsaPublicKey};
452
453    fn get_private_key() -> RsaPrivateKey {
454        // In order to generate new test vectors you'll need the PEM form of this key:
455        // -----BEGIN RSA PRIVATE KEY-----
456        // MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
457        // fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
458        // /ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu
459        // RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/
460        // EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A
461        // IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS
462        // tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V
463        // -----END RSA PRIVATE KEY-----
464
465        RsaPrivateKey::from_components(
466            BoxedUint::from_be_hex("B2990F49C47DFA8CD400AE6A4D1B8A3B6A13642B23F28B003BFB97790ADE9A4CC82B8B2A81747DDEC08B6296E53A08C331687EF25C4BF4936BA1C0E6041E9D15", 512).unwrap(),
467            BoxedUint::from(65_537u64),
468            BoxedUint::from_be_hex("8ABD6A69F4D1A4B487F0AB8D7AAEFD38609405C999984E30F567E1E8AEEFF44E8B18BDB1EC78DFA31A55E32A48D7FB131F5AF1F44D7D6B2CED2A9DF5E5AE4535", 512).unwrap(),
469            vec![
470                BoxedUint::from_be_hex("DAB2F18048BAA68DE7DF04D2D35D5D80E60E2DFA42D50A9B04219032715E46B3", 256).unwrap(),
471                BoxedUint::from_be_hex("D10F2E66B1D0C13F10EF9927BF5324A379CA218146CBF9CAFC795221F16A3117", 256).unwrap()
472            ],
473        ).unwrap()
474    }
475
476    #[rstest]
477    #[case(
478        "gIcUIoVkD6ATMBk/u/nlCZCCWRKdkfjCgFdo35VpRXLduiKXhNz1XupLLzTXAybEq15juc+EgY5o0DHv/nt3yg==",
479        "x"
480    )]
481    #[case(
482        "Y7TOCSqofGhkRb+jaVRLzK8xw2cSo1IVES19utzv6hwvx+M8kFsoWQm5DzBeJCZTCVDPkTpavUuEbgp8hnUGDw==",
483        "testing."
484    )]
485    #[case(
486        "arReP9DJtEVyV2Dg3dDp4c/PSk1O6lxkoJ8HcFupoRorBZG+7+1fDAwT1olNddFnQMjmkb8vxwmNMoTAT/BFjQ==",
487        "testing.\n"
488    )]
489    #[case(
490        "WtaBXIoGC54+vH0NH0CHHE+dRDOsMc/6BrfFu2lEqcKL9+uDuWaf+Xj9mrbQCjjZcpQuX733zyok/jsnqe/Ftw==",
491        "01234567890123456789012345678901234567890123456789012"
492    )]
493    fn test_decrypt_pkcs1v15(#[case] ciphertext: &str, #[case] plaintext: &str) {
494        let priv_key = get_private_key();
495
496        let out = priv_key
497            .decrypt(Pkcs1v15Encrypt, &Base64::decode_vec(ciphertext).unwrap())
498            .unwrap();
499        assert_eq!(out, plaintext.as_bytes());
500    }
501
502    #[test]
503    fn test_encrypt_decrypt_pkcs1v15() {
504        let mut rng = ChaCha8Rng::from_seed([42; 32]);
505        let priv_key = get_private_key();
506        let k = priv_key.size();
507
508        for i in 1..100 {
509            let mut input = vec![0u8; i * 8];
510            rng.fill_bytes(&mut input);
511            if input.len() > k - 11 {
512                input = input[0..k - 11].to_vec();
513            }
514
515            let pub_key: RsaPublicKey = priv_key.clone().into();
516            let ciphertext = encrypt(&mut rng, &pub_key, &input).unwrap();
517            assert_ne!(input, ciphertext);
518
519            let blind: bool = rng.next_u32() < (1u32 << 31);
520            let blinder = if blind { Some(&mut rng) } else { None };
521            let plaintext = decrypt(blinder, &priv_key, &ciphertext).unwrap();
522            assert_eq!(input, plaintext);
523        }
524    }
525
526    #[rstest]
527    #[case(
528        "gIcUIoVkD6ATMBk/u/nlCZCCWRKdkfjCgFdo35VpRXLduiKXhNz1XupLLzTXAybEq15juc+EgY5o0DHv/nt3yg==",
529        "x"
530    )]
531    #[case(
532        "Y7TOCSqofGhkRb+jaVRLzK8xw2cSo1IVES19utzv6hwvx+M8kFsoWQm5DzBeJCZTCVDPkTpavUuEbgp8hnUGDw==",
533        "testing."
534    )]
535    #[case(
536        "arReP9DJtEVyV2Dg3dDp4c/PSk1O6lxkoJ8HcFupoRorBZG+7+1fDAwT1olNddFnQMjmkb8vxwmNMoTAT/BFjQ==",
537        "testing.\n"
538    )]
539    #[case(
540        "WtaBXIoGC54+vH0NH0CHHE+dRDOsMc/6BrfFu2lEqcKL9+uDuWaf+Xj9mrbQCjjZcpQuX733zyok/jsnqe/Ftw==",
541        "01234567890123456789012345678901234567890123456789012"
542    )]
543    fn test_decrypt_pkcs1v15_traits(#[case] ciphertext: &str, #[case] plaintext: &str) {
544        let priv_key = get_private_key();
545        let decrypting_key = DecryptingKey::new(priv_key);
546
547        let out = decrypting_key
548            .decrypt(&Base64::decode_vec(ciphertext).unwrap())
549            .unwrap();
550        assert_eq!(out, plaintext.as_bytes());
551    }
552
553    #[test]
554    fn test_encrypt_decrypt_pkcs1v15_traits() {
555        let mut rng = ChaCha8Rng::from_seed([42; 32]);
556        let priv_key = get_private_key();
557        let k = priv_key.size();
558        let decrypting_key = DecryptingKey::new(priv_key);
559
560        for i in 1..100 {
561            let mut input = vec![0u8; i * 8];
562            rng.fill_bytes(&mut input);
563            if input.len() > k - 11 {
564                input = input[0..k - 11].to_vec();
565            }
566
567            let encrypting_key = decrypting_key.encrypting_key();
568            let ciphertext = encrypting_key.encrypt_with_rng(&mut rng, &input).unwrap();
569            assert_ne!(input, ciphertext);
570
571            let blind: bool = rng.next_u32() < (1u32 << 31);
572            let plaintext = if blind {
573                decrypting_key
574                    .decrypt_with_rng(&mut rng, &ciphertext)
575                    .unwrap()
576            } else {
577                decrypting_key.decrypt(&ciphertext).unwrap()
578            };
579            assert_eq!(input, plaintext);
580        }
581    }
582
583    #[rstest]
584    #[case("Test.\n", hex!(
585        "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
586        "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"))
587    ]
588    fn test_sign_pkcs1v15(#[case] text: &str, #[case] expected: [u8; 64]) {
589        let priv_key = get_private_key();
590
591        let digest = Sha1::digest(text.as_bytes()).to_vec();
592
593        let out = priv_key.sign(Pkcs1v15Sign::new::<Sha1>(), &digest).unwrap();
594        assert_ne!(out, digest);
595        assert_eq!(out, expected);
596
597        let mut rng = ChaCha8Rng::from_seed([42; 32]);
598        let out2 = priv_key
599            .sign_with_rng(&mut rng, Pkcs1v15Sign::new::<Sha1>(), &digest)
600            .unwrap();
601        assert_eq!(out2, expected);
602    }
603
604    #[rstest]
605    #[case("Test.\n", hex!(
606        "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
607        "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"))
608    ]
609    fn test_sign_pkcs1v15_signer(#[case] text: &str, #[case] expected: [u8; 64]) {
610        let priv_key = get_private_key();
611
612        let signing_key = SigningKey::<Sha1>::new(priv_key);
613        let out = signing_key.sign(text.as_bytes()).to_bytes();
614        assert_ne!(out.as_ref(), text.as_bytes());
615        assert_ne!(out.as_ref(), &Sha1::digest(text.as_bytes()).to_vec());
616        assert_eq!(out.as_ref(), expected);
617
618        let mut rng = ChaCha8Rng::from_seed([42; 32]);
619        let out2 = signing_key
620            .sign_with_rng(&mut rng, text.as_bytes())
621            .to_bytes();
622        assert_eq!(out2.as_ref(), expected);
623    }
624
625    #[rstest]
626    #[case("Test.\n", hex!(
627        "2ffae3f3e130287b3a1dcb320e46f52e8f3f7969b646932273a7e3a6f2a182ea"
628        "02d42875a7ffa4a148aa311f9e4b562e4e13a2223fb15f4e5bf5f2b206d9451b"))
629    ]
630    fn test_sign_pkcs1v15_signer_sha2_256(#[case] text: &str, #[case] expected: [u8; 64]) {
631        let priv_key = get_private_key();
632        let signing_key = SigningKey::<Sha256>::new(priv_key);
633
634        let out = signing_key.sign(text.as_bytes()).to_bytes();
635        assert_ne!(out.as_ref(), text.as_bytes());
636        assert_eq!(out.as_ref(), expected);
637
638        let mut rng = ChaCha8Rng::from_seed([42; 32]);
639        let out2 = signing_key
640            .sign_with_rng(&mut rng, text.as_bytes())
641            .to_bytes();
642        assert_eq!(out2.as_ref(), expected);
643    }
644
645    #[rstest]
646    #[case("Test.\n", hex!(
647        "55e9fba3354dfb51d2c8111794ea552c86afc2cab154652c03324df8c2c51ba7"
648        "2ff7c14de59a6f9ba50d90c13a7537cc3011948369f1f0ec4a49d21eb7e723f9"))
649    ]
650    fn test_sign_pkcs1v15_signer_sha3_256(#[case] text: &str, #[case] expected: [u8; 64]) {
651        let priv_key = get_private_key();
652        let signing_key = SigningKey::<Sha3_256>::new(priv_key);
653
654        let out = signing_key.sign(text.as_bytes()).to_bytes();
655        assert_ne!(out.as_ref(), text.as_bytes());
656        assert_eq!(out.as_ref(), expected);
657
658        let mut rng = ChaCha8Rng::from_seed([42; 32]);
659        let out2 = signing_key
660            .sign_with_rng(&mut rng, text.as_bytes())
661            .to_bytes();
662        assert_eq!(out2.as_ref(), expected);
663    }
664
665    #[rstest]
666    #[case(
667        "Test.\n",
668        hex!(
669            "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
670            "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"
671        )
672    )]
673    fn test_sign_pkcs1v15_digest_signer(#[case] text: &str, #[case] expected: [u8; 64]) {
674        let priv_key = get_private_key();
675        let signing_key = SigningKey::new(priv_key);
676
677        let mut digest = Sha1::new();
678        digest.update(text.as_bytes());
679        let out = signing_key
680            .sign_digest(|digest: &mut Sha1| digest.update(text.as_bytes()))
681            .to_bytes();
682        assert_ne!(out.as_ref(), text.as_bytes());
683        assert_ne!(out.as_ref(), &Sha1::digest(text.as_bytes()).to_vec());
684        assert_eq!(out.as_ref(), expected);
685
686        let mut rng = ChaCha8Rng::from_seed([42; 32]);
687        let out2 = signing_key
688            .sign_digest_with_rng(&mut rng, |digest: &mut Sha1| digest.update(text.as_bytes()))
689            .to_bytes();
690        assert_eq!(out2.as_ref(), expected);
691    }
692
693    #[rstest]
694    #[case(
695        "Test.\n",
696        hex!(
697            "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
698            "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"
699        ),
700        true
701    )]
702    #[case(
703        "Test.\n",
704        hex!(
705            "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
706            "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362af"
707        ),
708        false
709    )]
710    fn test_verify_pkcs1v15(#[case] text: &str, #[case] sig: [u8; 64], #[case] expected: bool) {
711        let priv_key = get_private_key();
712        let pub_key: RsaPublicKey = priv_key.into();
713
714        let digest = Sha1::digest(text.as_bytes()).to_vec();
715
716        let result = pub_key.verify(Pkcs1v15Sign::new::<Sha1>(), &digest, &sig);
717        match expected {
718            true => result.expect("failed to verify"),
719            false => {
720                result.expect_err("expected verifying error");
721            }
722        }
723    }
724
725    #[rstest]
726    #[case(
727        "Test.\n",
728        hex!(
729            "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
730            "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"
731        ),
732        true
733    )]
734    #[case(
735        "Test.\n",
736        hex!(
737            "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
738            "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362af"
739        ),
740        false
741    )]
742    fn test_verify_pkcs1v15_signer(
743        #[case] text: &str,
744        #[case] sig: [u8; 64],
745        #[case] expected: bool,
746    ) {
747        let priv_key = get_private_key();
748
749        let pub_key: RsaPublicKey = priv_key.into();
750        let verifying_key = VerifyingKey::<Sha1>::new(pub_key);
751
752        let result = verifying_key.verify(
753            text.as_bytes(),
754            &Signature::try_from(sig.as_slice()).unwrap(),
755        );
756        match expected {
757            true => result.expect("failed to verify"),
758            false => {
759                result.expect_err("expected verifying error");
760            }
761        }
762    }
763
764    #[rstest]
765    #[case(
766        "Test.\n",
767        hex!(
768            "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
769            "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"
770        ),
771        true
772    )]
773    #[case(
774        "Test.\n",
775        hex!(
776            "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
777            "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362af"
778        ),
779        false
780    )]
781    fn test_verify_pkcs1v15_digest_signer(
782        #[case] text: &str,
783        #[case] sig: [u8; 64],
784        #[case] expected: bool,
785    ) {
786        let priv_key = get_private_key();
787
788        let pub_key: RsaPublicKey = priv_key.into();
789        let verifying_key = VerifyingKey::new(pub_key);
790
791        let result = verifying_key.verify_digest(
792            |digest: &mut Sha1| {
793                digest.update(text.as_bytes());
794                Ok(())
795            },
796            &Signature::try_from(sig.as_slice()).unwrap(),
797        );
798        match expected {
799            true => result.expect("failed to verify"),
800            false => {
801                result.expect_err("expected verifying error");
802            }
803        }
804    }
805
806    #[test]
807    fn test_unpadded_signature() {
808        let msg = b"Thu Dec 19 18:06:16 EST 2013\n";
809        let expected_sig = Base64::decode_vec("pX4DR8azytjdQ1rtUiC040FjkepuQut5q2ZFX1pTjBrOVKNjgsCDyiJDGZTCNoh9qpXYbhl7iEym30BWWwuiZg==").unwrap();
810        let priv_key = get_private_key();
811
812        let sig = priv_key.sign(Pkcs1v15Sign::new_unprefixed(), msg).unwrap();
813        assert_eq!(expected_sig, sig);
814
815        let pub_key: RsaPublicKey = priv_key.into();
816        pub_key
817            .verify(Pkcs1v15Sign::new_unprefixed(), msg, &sig)
818            .expect("failed to verify");
819    }
820
821    #[test]
822    fn test_unpadded_signature_hazmat() {
823        let msg = b"Thu Dec 19 18:06:16 EST 2013\n";
824        let expected_sig = Base64::decode_vec("pX4DR8azytjdQ1rtUiC040FjkepuQut5q2ZFX1pTjBrOVKNjgsCDyiJDGZTCNoh9qpXYbhl7iEym30BWWwuiZg==").unwrap();
825        let priv_key = get_private_key();
826
827        let signing_key = SigningKey::<Sha1>::new_unprefixed(priv_key);
828        let sig = signing_key
829            .sign_prehash(msg)
830            .expect("Failure during sign")
831            .to_bytes();
832        assert_eq!(sig.as_ref(), expected_sig);
833
834        let verifying_key = signing_key.verifying_key();
835        verifying_key
836            .verify_prehash(msg, &Signature::try_from(expected_sig.as_slice()).unwrap())
837            .expect("failed to verify");
838    }
839}