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        if input.len() > N {
143            return Err(Error::OutputBufferTooSmall);
144        }
145
146        let mut out = Self::new();
147        out.data[..input.len()].copy_from_slice(input);
148        out.len = input.len();
149        Ok(out)
150    }
151}
152
153#[cfg(not(feature = "alloc"))]
154impl<const N: usize> AsRef<[u8]> for Prefix<N> {
155    fn as_ref(&self) -> &[u8] {
156        &self.data[..self.len]
157    }
158}
159
160#[cfg(not(feature = "alloc"))]
161pub(super) fn pkcs1v15_generate_prefix_helper<D: Digest>() -> Prefix
162where
163    D: Digest + AssociatedOid,
164{
165    let mut tmp_prefix = [0u8; 64];
166    let prefix =
167        pkcs1v15_generate_prefix_into::<D>(&mut tmp_prefix).expect("prefix buffer is too small");
168    Prefix::from_slice(prefix).expect("prefix buffer is too small")
169}
170
171impl PaddingScheme for Pkcs1v15Encrypt {
172    #[cfg(feature = "alloc")]
173    fn decrypt<Rng: TryCryptoRng + ?Sized>(
174        self,
175        rng: Option<&mut Rng>,
176        priv_key: &RsaPrivateKey,
177        ciphertext: &[u8],
178    ) -> Result<Vec<u8>> {
179        decrypt(rng, priv_key, ciphertext)
180    }
181
182    #[cfg(feature = "alloc")]
183    fn encrypt<Rng, K, T>(self, rng: &mut Rng, pub_key: &K, msg: &[u8]) -> Result<Vec<u8>>
184    where
185        Rng: TryCryptoRng + ?Sized,
186        T: UnsignedModularInt,
187        K: PublicKeyParts<T>,
188        K::MontyParams: crate::traits::modular::CtModulusParams,
189    {
190        let mut storage = vec![0u8; pub_key.size()];
191        let ciphertext = self.encrypt_into(rng, pub_key, msg, &mut storage)?;
192        Ok(ciphertext.to_vec())
193    }
194}
195
196/// `RSASSA-PKCS1-v1_5`: digital signatures using PKCS#1 v1.5 padding.
197#[derive(Clone, Debug, Eq, PartialEq)]
198pub struct Pkcs1v15Sign {
199    /// Length of hash to use.
200    pub hash_len: Option<usize>,
201
202    /// Prefix.
203    #[cfg(feature = "alloc")]
204    prefix: Box<[u8]>,
205    #[cfg(not(feature = "alloc"))]
206    prefix: Prefix,
207}
208
209impl Pkcs1v15Sign {
210    /// Create new PKCS#1 v1.5 padding for the given digest.
211    ///
212    /// The digest must have an [`AssociatedOid`]. Make sure to enable the `oid`
213    /// feature of the relevant digest crate.
214    pub fn new<D>() -> Self
215    where
216        D: Digest + AssociatedOid,
217    {
218        Self {
219            hash_len: Some(<D as Digest>::output_size()),
220            #[cfg(feature = "alloc")]
221            prefix: pkcs1v15_generate_prefix::<D>().into_boxed_slice(),
222            #[cfg(not(feature = "alloc"))]
223            prefix: pkcs1v15_generate_prefix_helper::<D>(),
224        }
225    }
226
227    /// Create new PKCS#1 v1.5 padding for computing an unprefixed signature.
228    ///
229    /// This sets `hash_len` to `None` and uses an empty `prefix`.
230    pub fn new_unprefixed() -> Self {
231        Self {
232            hash_len: None,
233            #[cfg(feature = "alloc")]
234            prefix: Box::new([]),
235            #[cfg(not(feature = "alloc"))]
236            prefix: Prefix::new(),
237        }
238    }
239}
240
241impl SignatureScheme for Pkcs1v15Sign {
242    #[cfg(feature = "alloc")]
243    fn sign<Rng: TryCryptoRng + ?Sized>(
244        self,
245        rng: Option<&mut Rng>,
246        priv_key: &RsaPrivateKey,
247        hashed: &[u8],
248    ) -> Result<Vec<u8>> {
249        if let Some(hash_len) = self.hash_len {
250            if hashed.len() != hash_len {
251                return Err(Error::InputNotHashed);
252            }
253        }
254
255        sign(rng, priv_key, &self.prefix, hashed)
256    }
257
258    fn verify<K, T>(self, pub_key: &K, hashed: &[u8], sig: &[u8]) -> Result<()>
259    where
260        T: UnsignedModularInt,
261        K: PublicKeyParts<T>,
262    {
263        if let Some(hash_len) = self.hash_len {
264            if hashed.len() != hash_len {
265                return Err(Error::InputNotHashed);
266            }
267        }
268
269        if sig.len() != pub_key.size() {
270            return Err(Error::Verification);
271        }
272
273        let mut storage = pub_key.n().as_ref().to_be_bytes();
274        let sig = T::try_from_be_bytes_vartime(sig).map_err(|_| Error::Verification)?;
275        verify_generic(
276            pub_key,
277            self.prefix.as_ref(),
278            hashed,
279            &sig,
280            storage.as_mut(),
281        )
282    }
283}
284
285/// Encrypts the given message with RSA and the padding
286/// scheme from PKCS#1 v1.5.  The message must be no longer than the
287/// length of the public modulus minus 11 bytes.
288#[inline]
289pub fn encrypt_into<'a, R, K, T>(
290    rng: &mut R,
291    pub_key: &K,
292    msg: &[u8],
293    storage: &'a mut [u8],
294) -> Result<&'a [u8]>
295where
296    R: TryCryptoRng + ?Sized,
297    T: UnsignedModularInt,
298    K: PublicKeyParts<T>,
299    K::MontyParams: crate::traits::modular::CtModulusParams,
300{
301    Pkcs1v15Encrypt.encrypt_into(rng, pub_key, msg, storage)
302}
303
304/// Decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
305///
306/// If an `rng` is passed, it uses RSA blinding to avoid timing side-channel attacks.
307///
308/// Note that whether this function returns an error or not discloses secret
309/// information. If an attacker can cause this function to run repeatedly and
310/// learn whether each instance returned an error then they can decrypt and
311/// forge signatures as if they had the private key. See
312/// `decrypt_session_key` for a way of solving this problem.
313#[cfg(feature = "alloc")]
314#[inline]
315fn decrypt<R: TryCryptoRng + ?Sized>(
316    rng: Option<&mut R>,
317    priv_key: &RsaPrivateKey,
318    ciphertext: &[u8],
319) -> Result<Vec<u8>> {
320    key::check_public(priv_key)?;
321
322    let ciphertext = BoxedUint::from_be_slice(ciphertext, priv_key.n_bits_precision())?;
323    let em = rsa_decrypt_and_check(priv_key, rng, &ciphertext)?;
324    let em = uint_to_zeroizing_be_pad(em, priv_key.size())?;
325
326    pkcs1v15_encrypt_unpad(em, priv_key.size())
327}
328
329/// Calculates the signature of hashed using
330/// RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5. Note that `hashed` must
331/// be the result of hashing the input message using the given hash
332/// function. If hash is `None`, hashed is signed directly. This isn't
333/// advisable except for interoperability.
334///
335/// If `rng` is not `None` then RSA blinding will be used to avoid timing
336/// side-channel attacks.
337///
338/// This function is deterministic. Thus, if the set of possible
339/// messages is small, an attacker may be able to build a map from
340/// messages to signatures and identify the signed messages. As ever,
341/// signatures provide authenticity, not confidentiality.
342#[cfg(feature = "alloc")]
343#[inline]
344fn sign<R: TryCryptoRng + ?Sized>(
345    rng: Option<&mut R>,
346    priv_key: &RsaPrivateKey,
347    prefix: &[u8],
348    hashed: &[u8],
349) -> Result<Vec<u8>> {
350    let em = pkcs1v15_sign_pad(prefix, hashed, priv_key.size())?;
351
352    let em = BoxedUint::from_be_slice(&em, priv_key.n_bits_precision())?;
353    uint_to_zeroizing_be_pad(rsa_decrypt_and_check(priv_key, rng, &em)?, priv_key.size())
354}
355
356/// Verifies an RSA PKCS#1 v1.5 signature.
357#[inline]
358pub(crate) fn verify_generic<K, T>(
359    pub_key: &K,
360    prefix: &[u8],
361    hashed: &[u8],
362    sig: &T,
363    storage: &mut [u8],
364) -> Result<()>
365where
366    T: UnsignedModularInt,
367    K: PublicKeyParts<T>,
368{
369    let n = pub_key.n();
370    if sig >= n.as_ref() || sig.bits_precision() != pub_key.n_bits_precision() {
371        return Err(Error::Verification);
372    }
373
374    let em = uint_to_be_pad_into(rsa_encrypt(pub_key, sig)?, pub_key.size(), storage)?;
375
376    pkcs1v15_sign_unpad(prefix, hashed, em, pub_key.size())
377}
378
379mod oid {
380    use const_oid::ObjectIdentifier;
381
382    /// A trait which associates an RSA-specific OID with a type.
383    pub trait RsaSignatureAssociatedOid {
384        /// The OID associated with this type.
385        const OID: ObjectIdentifier;
386    }
387
388    #[cfg(feature = "sha1")]
389    impl RsaSignatureAssociatedOid for sha1::Sha1 {
390        const OID: ObjectIdentifier =
391            const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.5");
392    }
393
394    #[cfg(feature = "sha2")]
395    impl RsaSignatureAssociatedOid for sha2::Sha224 {
396        const OID: ObjectIdentifier =
397            const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.14");
398    }
399
400    #[cfg(feature = "sha2")]
401    impl RsaSignatureAssociatedOid for sha2::Sha256 {
402        const OID: ObjectIdentifier =
403            const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.11");
404    }
405
406    #[cfg(feature = "sha2")]
407    impl RsaSignatureAssociatedOid for sha2::Sha384 {
408        const OID: ObjectIdentifier =
409            const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.12");
410    }
411
412    #[cfg(feature = "sha2")]
413    impl RsaSignatureAssociatedOid for sha2::Sha512 {
414        const OID: ObjectIdentifier =
415            const_oid::ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.13");
416    }
417}
418
419pub use oid::RsaSignatureAssociatedOid;
420
421#[cfg(test)]
422#[cfg(feature = "alloc")]
423mod tests {
424    use super::*;
425    use ::signature::{
426        hazmat::{PrehashSigner, PrehashVerifier},
427        DigestSigner, DigestVerifier, Keypair, RandomizedDigestSigner, RandomizedSigner,
428        SignatureEncoding, Signer, Verifier,
429    };
430    use base64ct::{Base64, Encoding};
431    use hex_literal::hex;
432    use rand::rngs::ChaCha8Rng;
433    use rand_core::{Rng, SeedableRng};
434    use rstest::rstest;
435    use sha1::{Digest, Sha1};
436    use sha2::Sha256;
437    use sha3::Sha3_256;
438
439    use crate::traits::{
440        Decryptor, EncryptingKeypair, PublicKeyParts, RandomizedDecryptor, RandomizedEncryptor,
441    };
442    use crate::{RsaPrivateKey, RsaPublicKey};
443
444    fn get_private_key() -> RsaPrivateKey {
445        // In order to generate new test vectors you'll need the PEM form of this key:
446        // -----BEGIN RSA PRIVATE KEY-----
447        // MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
448        // fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
449        // /ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu
450        // RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/
451        // EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A
452        // IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS
453        // tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V
454        // -----END RSA PRIVATE KEY-----
455
456        RsaPrivateKey::from_components(
457            BoxedUint::from_be_hex("B2990F49C47DFA8CD400AE6A4D1B8A3B6A13642B23F28B003BFB97790ADE9A4CC82B8B2A81747DDEC08B6296E53A08C331687EF25C4BF4936BA1C0E6041E9D15", 512).unwrap(),
458            BoxedUint::from(65_537u64),
459            BoxedUint::from_be_hex("8ABD6A69F4D1A4B487F0AB8D7AAEFD38609405C999984E30F567E1E8AEEFF44E8B18BDB1EC78DFA31A55E32A48D7FB131F5AF1F44D7D6B2CED2A9DF5E5AE4535", 512).unwrap(),
460            vec![
461                BoxedUint::from_be_hex("DAB2F18048BAA68DE7DF04D2D35D5D80E60E2DFA42D50A9B04219032715E46B3", 256).unwrap(),
462                BoxedUint::from_be_hex("D10F2E66B1D0C13F10EF9927BF5324A379CA218146CBF9CAFC795221F16A3117", 256).unwrap()
463            ],
464        ).unwrap()
465    }
466
467    #[rstest]
468    #[case(
469        "gIcUIoVkD6ATMBk/u/nlCZCCWRKdkfjCgFdo35VpRXLduiKXhNz1XupLLzTXAybEq15juc+EgY5o0DHv/nt3yg==",
470        "x"
471    )]
472    #[case(
473        "Y7TOCSqofGhkRb+jaVRLzK8xw2cSo1IVES19utzv6hwvx+M8kFsoWQm5DzBeJCZTCVDPkTpavUuEbgp8hnUGDw==",
474        "testing."
475    )]
476    #[case(
477        "arReP9DJtEVyV2Dg3dDp4c/PSk1O6lxkoJ8HcFupoRorBZG+7+1fDAwT1olNddFnQMjmkb8vxwmNMoTAT/BFjQ==",
478        "testing.\n"
479    )]
480    #[case(
481        "WtaBXIoGC54+vH0NH0CHHE+dRDOsMc/6BrfFu2lEqcKL9+uDuWaf+Xj9mrbQCjjZcpQuX733zyok/jsnqe/Ftw==",
482        "01234567890123456789012345678901234567890123456789012"
483    )]
484    fn test_decrypt_pkcs1v15(#[case] ciphertext: &str, #[case] plaintext: &str) {
485        let priv_key = get_private_key();
486
487        let out = priv_key
488            .decrypt(Pkcs1v15Encrypt, &Base64::decode_vec(ciphertext).unwrap())
489            .unwrap();
490        assert_eq!(out, plaintext.as_bytes());
491    }
492
493    #[test]
494    fn test_encrypt_decrypt_pkcs1v15() {
495        let mut rng = ChaCha8Rng::from_seed([42; 32]);
496        let priv_key = get_private_key();
497        let k = priv_key.size();
498
499        for i in 1..100 {
500            let mut input = vec![0u8; i * 8];
501            rng.fill_bytes(&mut input);
502            if input.len() > k - 11 {
503                input = input[0..k - 11].to_vec();
504            }
505
506            let pub_key: RsaPublicKey = priv_key.clone().into();
507            let ciphertext = encrypt(&mut rng, &pub_key, &input).unwrap();
508            assert_ne!(input, ciphertext);
509
510            let blind: bool = rng.next_u32() < (1u32 << 31);
511            let blinder = if blind { Some(&mut rng) } else { None };
512            let plaintext = decrypt(blinder, &priv_key, &ciphertext).unwrap();
513            assert_eq!(input, plaintext);
514        }
515    }
516
517    #[rstest]
518    #[case(
519        "gIcUIoVkD6ATMBk/u/nlCZCCWRKdkfjCgFdo35VpRXLduiKXhNz1XupLLzTXAybEq15juc+EgY5o0DHv/nt3yg==",
520        "x"
521    )]
522    #[case(
523        "Y7TOCSqofGhkRb+jaVRLzK8xw2cSo1IVES19utzv6hwvx+M8kFsoWQm5DzBeJCZTCVDPkTpavUuEbgp8hnUGDw==",
524        "testing."
525    )]
526    #[case(
527        "arReP9DJtEVyV2Dg3dDp4c/PSk1O6lxkoJ8HcFupoRorBZG+7+1fDAwT1olNddFnQMjmkb8vxwmNMoTAT/BFjQ==",
528        "testing.\n"
529    )]
530    #[case(
531        "WtaBXIoGC54+vH0NH0CHHE+dRDOsMc/6BrfFu2lEqcKL9+uDuWaf+Xj9mrbQCjjZcpQuX733zyok/jsnqe/Ftw==",
532        "01234567890123456789012345678901234567890123456789012"
533    )]
534    fn test_decrypt_pkcs1v15_traits(#[case] ciphertext: &str, #[case] plaintext: &str) {
535        let priv_key = get_private_key();
536        let decrypting_key = DecryptingKey::new(priv_key);
537
538        let out = decrypting_key
539            .decrypt(&Base64::decode_vec(ciphertext).unwrap())
540            .unwrap();
541        assert_eq!(out, plaintext.as_bytes());
542    }
543
544    #[test]
545    fn test_encrypt_decrypt_pkcs1v15_traits() {
546        let mut rng = ChaCha8Rng::from_seed([42; 32]);
547        let priv_key = get_private_key();
548        let k = priv_key.size();
549        let decrypting_key = DecryptingKey::new(priv_key);
550
551        for i in 1..100 {
552            let mut input = vec![0u8; i * 8];
553            rng.fill_bytes(&mut input);
554            if input.len() > k - 11 {
555                input = input[0..k - 11].to_vec();
556            }
557
558            let encrypting_key = decrypting_key.encrypting_key();
559            let ciphertext = encrypting_key.encrypt_with_rng(&mut rng, &input).unwrap();
560            assert_ne!(input, ciphertext);
561
562            let blind: bool = rng.next_u32() < (1u32 << 31);
563            let plaintext = if blind {
564                decrypting_key
565                    .decrypt_with_rng(&mut rng, &ciphertext)
566                    .unwrap()
567            } else {
568                decrypting_key.decrypt(&ciphertext).unwrap()
569            };
570            assert_eq!(input, plaintext);
571        }
572    }
573
574    #[rstest]
575    #[case("Test.\n", hex!(
576        "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
577        "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"))
578    ]
579    fn test_sign_pkcs1v15(#[case] text: &str, #[case] expected: [u8; 64]) {
580        let priv_key = get_private_key();
581
582        let digest = Sha1::digest(text.as_bytes()).to_vec();
583
584        let out = priv_key.sign(Pkcs1v15Sign::new::<Sha1>(), &digest).unwrap();
585        assert_ne!(out, digest);
586        assert_eq!(out, expected);
587
588        let mut rng = ChaCha8Rng::from_seed([42; 32]);
589        let out2 = priv_key
590            .sign_with_rng(&mut rng, Pkcs1v15Sign::new::<Sha1>(), &digest)
591            .unwrap();
592        assert_eq!(out2, expected);
593    }
594
595    #[rstest]
596    #[case("Test.\n", hex!(
597        "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
598        "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"))
599    ]
600    fn test_sign_pkcs1v15_signer(#[case] text: &str, #[case] expected: [u8; 64]) {
601        let priv_key = get_private_key();
602
603        let signing_key = SigningKey::<Sha1>::new(priv_key);
604        let out = signing_key.sign(text.as_bytes()).to_bytes();
605        assert_ne!(out.as_ref(), text.as_bytes());
606        assert_ne!(out.as_ref(), &Sha1::digest(text.as_bytes()).to_vec());
607        assert_eq!(out.as_ref(), expected);
608
609        let mut rng = ChaCha8Rng::from_seed([42; 32]);
610        let out2 = signing_key
611            .sign_with_rng(&mut rng, text.as_bytes())
612            .to_bytes();
613        assert_eq!(out2.as_ref(), expected);
614    }
615
616    #[rstest]
617    #[case("Test.\n", hex!(
618        "2ffae3f3e130287b3a1dcb320e46f52e8f3f7969b646932273a7e3a6f2a182ea"
619        "02d42875a7ffa4a148aa311f9e4b562e4e13a2223fb15f4e5bf5f2b206d9451b"))
620    ]
621    fn test_sign_pkcs1v15_signer_sha2_256(#[case] text: &str, #[case] expected: [u8; 64]) {
622        let priv_key = get_private_key();
623        let signing_key = SigningKey::<Sha256>::new(priv_key);
624
625        let out = signing_key.sign(text.as_bytes()).to_bytes();
626        assert_ne!(out.as_ref(), text.as_bytes());
627        assert_eq!(out.as_ref(), expected);
628
629        let mut rng = ChaCha8Rng::from_seed([42; 32]);
630        let out2 = signing_key
631            .sign_with_rng(&mut rng, text.as_bytes())
632            .to_bytes();
633        assert_eq!(out2.as_ref(), expected);
634    }
635
636    #[rstest]
637    #[case("Test.\n", hex!(
638        "55e9fba3354dfb51d2c8111794ea552c86afc2cab154652c03324df8c2c51ba7"
639        "2ff7c14de59a6f9ba50d90c13a7537cc3011948369f1f0ec4a49d21eb7e723f9"))
640    ]
641    fn test_sign_pkcs1v15_signer_sha3_256(#[case] text: &str, #[case] expected: [u8; 64]) {
642        let priv_key = get_private_key();
643        let signing_key = SigningKey::<Sha3_256>::new(priv_key);
644
645        let out = signing_key.sign(text.as_bytes()).to_bytes();
646        assert_ne!(out.as_ref(), text.as_bytes());
647        assert_eq!(out.as_ref(), expected);
648
649        let mut rng = ChaCha8Rng::from_seed([42; 32]);
650        let out2 = signing_key
651            .sign_with_rng(&mut rng, text.as_bytes())
652            .to_bytes();
653        assert_eq!(out2.as_ref(), expected);
654    }
655
656    #[rstest]
657    #[case(
658        "Test.\n",
659        hex!(
660            "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
661            "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"
662        )
663    )]
664    fn test_sign_pkcs1v15_digest_signer(#[case] text: &str, #[case] expected: [u8; 64]) {
665        let priv_key = get_private_key();
666        let signing_key = SigningKey::new(priv_key);
667
668        let mut digest = Sha1::new();
669        digest.update(text.as_bytes());
670        let out = signing_key
671            .sign_digest(|digest: &mut Sha1| digest.update(text.as_bytes()))
672            .to_bytes();
673        assert_ne!(out.as_ref(), text.as_bytes());
674        assert_ne!(out.as_ref(), &Sha1::digest(text.as_bytes()).to_vec());
675        assert_eq!(out.as_ref(), expected);
676
677        let mut rng = ChaCha8Rng::from_seed([42; 32]);
678        let out2 = signing_key
679            .sign_digest_with_rng(&mut rng, |digest: &mut Sha1| digest.update(text.as_bytes()))
680            .to_bytes();
681        assert_eq!(out2.as_ref(), expected);
682    }
683
684    #[rstest]
685    #[case(
686        "Test.\n",
687        hex!(
688            "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
689            "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"
690        ),
691        true
692    )]
693    #[case(
694        "Test.\n",
695        hex!(
696            "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
697            "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362af"
698        ),
699        false
700    )]
701    fn test_verify_pkcs1v15(#[case] text: &str, #[case] sig: [u8; 64], #[case] expected: bool) {
702        let priv_key = get_private_key();
703        let pub_key: RsaPublicKey = priv_key.into();
704
705        let digest = Sha1::digest(text.as_bytes()).to_vec();
706
707        let result = pub_key.verify(Pkcs1v15Sign::new::<Sha1>(), &digest, &sig);
708        match expected {
709            true => result.expect("failed to verify"),
710            false => {
711                result.expect_err("expected verifying error");
712            }
713        }
714    }
715
716    #[rstest]
717    #[case(
718        "Test.\n",
719        hex!(
720            "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
721            "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"
722        ),
723        true
724    )]
725    #[case(
726        "Test.\n",
727        hex!(
728            "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
729            "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362af"
730        ),
731        false
732    )]
733    fn test_verify_pkcs1v15_signer(
734        #[case] text: &str,
735        #[case] sig: [u8; 64],
736        #[case] expected: bool,
737    ) {
738        let priv_key = get_private_key();
739
740        let pub_key: RsaPublicKey = priv_key.into();
741        let verifying_key = VerifyingKey::<Sha1>::new(pub_key);
742
743        let result = verifying_key.verify(
744            text.as_bytes(),
745            &Signature::try_from(sig.as_slice()).unwrap(),
746        );
747        match expected {
748            true => result.expect("failed to verify"),
749            false => {
750                result.expect_err("expected verifying error");
751            }
752        }
753    }
754
755    #[rstest]
756    #[case(
757        "Test.\n",
758        hex!(
759            "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
760            "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae"
761        ),
762        true
763    )]
764    #[case(
765        "Test.\n",
766        hex!(
767            "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33"
768            "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362af"
769        ),
770        false
771    )]
772    fn test_verify_pkcs1v15_digest_signer(
773        #[case] text: &str,
774        #[case] sig: [u8; 64],
775        #[case] expected: bool,
776    ) {
777        let priv_key = get_private_key();
778
779        let pub_key: RsaPublicKey = priv_key.into();
780        let verifying_key = VerifyingKey::new(pub_key);
781
782        let result = verifying_key.verify_digest(
783            |digest: &mut Sha1| {
784                digest.update(text.as_bytes());
785                Ok(())
786            },
787            &Signature::try_from(sig.as_slice()).unwrap(),
788        );
789        match expected {
790            true => result.expect("failed to verify"),
791            false => {
792                result.expect_err("expected verifying error");
793            }
794        }
795    }
796
797    #[test]
798    fn test_unpadded_signature() {
799        let msg = b"Thu Dec 19 18:06:16 EST 2013\n";
800        let expected_sig = Base64::decode_vec("pX4DR8azytjdQ1rtUiC040FjkepuQut5q2ZFX1pTjBrOVKNjgsCDyiJDGZTCNoh9qpXYbhl7iEym30BWWwuiZg==").unwrap();
801        let priv_key = get_private_key();
802
803        let sig = priv_key.sign(Pkcs1v15Sign::new_unprefixed(), msg).unwrap();
804        assert_eq!(expected_sig, sig);
805
806        let pub_key: RsaPublicKey = priv_key.into();
807        pub_key
808            .verify(Pkcs1v15Sign::new_unprefixed(), msg, &sig)
809            .expect("failed to verify");
810    }
811
812    #[test]
813    fn test_unpadded_signature_hazmat() {
814        let msg = b"Thu Dec 19 18:06:16 EST 2013\n";
815        let expected_sig = Base64::decode_vec("pX4DR8azytjdQ1rtUiC040FjkepuQut5q2ZFX1pTjBrOVKNjgsCDyiJDGZTCNoh9qpXYbhl7iEym30BWWwuiZg==").unwrap();
816        let priv_key = get_private_key();
817
818        let signing_key = SigningKey::<Sha1>::new_unprefixed(priv_key);
819        let sig = signing_key
820            .sign_prehash(msg)
821            .expect("Failure during sign")
822            .to_bytes();
823        assert_eq!(sig.as_ref(), expected_sig);
824
825        let verifying_key = signing_key.verifying_key();
826        verifying_key
827            .verify_prehash(msg, &Signature::try_from(expected_sig.as_slice()).unwrap())
828            .expect("failed to verify");
829    }
830}