Skip to main content

rama_boring/
rsa.rs

1//! Rivest–Shamir–Adleman cryptosystem
2//!
3//! RSA is one of the earliest asymmetric public key encryption schemes.
4//! Like many other cryptosystems, RSA relies on the presumed difficulty of a hard
5//! mathematical problem, namely factorization of the product of two large prime
6//! numbers. At the moment there does not exist an algorithm that can factor such
7//! large numbers in reasonable time. RSA is used in a wide variety of
8//! applications including digital signatures and key exchanges such as
9//! establishing a TLS/SSL connection.
10//!
11//! The RSA acronym is derived from the first letters of the surnames of the
12//! algorithm's founding trio.
13//!
14//! # Example
15//!
16//! Generate a 2048-bit RSA key pair and use the public key to encrypt some data.
17//!
18//! ```rust
19//! use rama_boring::rsa::{Rsa, Padding};
20//!
21//! let rsa = Rsa::generate(2048).unwrap();
22//! let data = b"foobar";
23//! let mut buf = vec![0; rsa.size() as usize];
24//! let encrypted_len = rsa.public_encrypt(data, &mut buf, Padding::PKCS1).unwrap();
25//! ```
26use crate::ffi;
27use crate::libc_types::c_int;
28use foreign_types::{ForeignType, ForeignTypeRef};
29use openssl_macros::corresponds;
30use std::fmt;
31use std::mem;
32use std::ptr;
33
34use crate::bn::{BigNum, BigNumRef};
35use crate::error::ErrorStack;
36use crate::pkey::{HasPrivate, HasPublic, Private, Public};
37use crate::{cvt, cvt_n, cvt_p};
38
39pub const EVP_PKEY_OP_SIGN: c_int = 1 << 3;
40pub const EVP_PKEY_OP_VERIFY: c_int = 1 << 4;
41pub const EVP_PKEY_OP_VERIFYRECOVER: c_int = 1 << 5;
42pub const EVP_PKEY_OP_SIGNCTX: c_int = 1 << 6;
43pub const EVP_PKEY_OP_VERIFYCTX: c_int = 1 << 7;
44pub const EVP_PKEY_OP_ENCRYPT: c_int = 1 << 8;
45pub const EVP_PKEY_OP_DECRYPT: c_int = 1 << 9;
46
47pub const EVP_PKEY_OP_TYPE_SIG: c_int = EVP_PKEY_OP_SIGN
48    | EVP_PKEY_OP_VERIFY
49    | EVP_PKEY_OP_VERIFYRECOVER
50    | EVP_PKEY_OP_SIGNCTX
51    | EVP_PKEY_OP_VERIFYCTX;
52
53pub const EVP_PKEY_OP_TYPE_CRYPT: c_int = EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT;
54
55/// Type of encryption padding to use.
56///
57/// Random length padding is primarily used to prevent attackers from
58/// predicting or knowing the exact length of a plaintext message that
59/// can possibly lead to breaking encryption.
60#[derive(Debug, Copy, Clone, PartialEq, Eq)]
61pub struct Padding(c_int);
62
63impl Padding {
64    pub const NONE: Padding = Padding(ffi::RSA_NO_PADDING);
65    pub const PKCS1: Padding = Padding(ffi::RSA_PKCS1_PADDING);
66    pub const PKCS1_OAEP: Padding = Padding(ffi::RSA_PKCS1_OAEP_PADDING);
67    pub const PKCS1_PSS: Padding = Padding(ffi::RSA_PKCS1_PSS_PADDING);
68
69    /// Creates a `Padding` from an integer representation.
70    #[must_use]
71    pub fn from_raw(value: c_int) -> Padding {
72        Padding(value)
73    }
74
75    /// Returns the integer representation of `Padding`.
76    #[allow(clippy::trivially_copy_pass_by_ref)]
77    #[must_use]
78    pub fn as_raw(&self) -> c_int {
79        self.0
80    }
81}
82
83generic_foreign_type_and_impl_send_sync! {
84    type CType = ffi::RSA;
85    fn drop = ffi::RSA_free;
86
87    /// An RSA key.
88    pub struct Rsa<T>;
89
90    /// Reference to `RSA`
91    pub struct RsaRef<T>;
92}
93
94impl<T> Clone for Rsa<T> {
95    fn clone(&self) -> Rsa<T> {
96        (**self).to_owned()
97    }
98}
99
100impl<T> ToOwned for RsaRef<T> {
101    type Owned = Rsa<T>;
102
103    fn to_owned(&self) -> Rsa<T> {
104        unsafe {
105            ffi::RSA_up_ref(self.as_ptr());
106            Rsa::from_ptr(self.as_ptr())
107        }
108    }
109}
110
111impl<T> RsaRef<T>
112where
113    T: HasPrivate,
114{
115    private_key_to_pem! {
116        /// Serializes the private key to a PEM-encoded PKCS#1 RSAPrivateKey structure.
117        ///
118        /// The output will have a header of `-----BEGIN RSA PRIVATE KEY-----`.
119        #[corresponds(PEM_write_bio_RSAPrivateKey)]
120        private_key_to_pem,
121        /// Serializes the private key to a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
122        ///
123        /// The output will have a header of `-----BEGIN RSA PRIVATE KEY-----`.
124        #[corresponds(PEM_write_bio_RSAPrivateKey)]
125        private_key_to_pem_passphrase,
126        ffi::PEM_write_bio_RSAPrivateKey
127    }
128
129    to_der! {
130        /// Serializes the private key to a DER-encoded PKCS#1 RSAPrivateKey structure.
131        #[corresponds(i2d_RSAPrivateKey)]
132        private_key_to_der,
133        ffi::i2d_RSAPrivateKey
134    }
135
136    /// Decrypts data using the private key, returning the number of decrypted bytes.
137    ///
138    /// # Panics
139    ///
140    /// Panics if `self` has no private components, or if `to` is smaller
141    /// than `self.size()`.
142    pub fn private_decrypt(
143        &self,
144        from: &[u8],
145        to: &mut [u8],
146        padding: Padding,
147    ) -> Result<usize, ErrorStack> {
148        assert!(i32::try_from(from.len()).is_ok());
149        assert!(to.len() >= self.size() as usize);
150
151        unsafe {
152            let len = cvt_n(ffi::RSA_private_decrypt(
153                from.len(),
154                from.as_ptr(),
155                to.as_mut_ptr(),
156                self.as_ptr(),
157                padding.0,
158            ))?;
159            Ok(len as usize)
160        }
161    }
162
163    /// Encrypts data using the private key, returning the number of encrypted bytes.
164    ///
165    /// # Panics
166    ///
167    /// Panics if `self` has no private components, or if `to` is smaller
168    /// than `self.size()`.
169    pub fn private_encrypt(
170        &self,
171        from: &[u8],
172        to: &mut [u8],
173        padding: Padding,
174    ) -> Result<usize, ErrorStack> {
175        assert!(from.len() <= i32::MAX as usize);
176        assert!(to.len() >= self.size() as usize);
177
178        unsafe {
179            let len = cvt_n(ffi::RSA_private_encrypt(
180                from.len(),
181                from.as_ptr(),
182                to.as_mut_ptr(),
183                self.as_ptr(),
184                padding.0,
185            ))?;
186            Ok(len as usize)
187        }
188    }
189
190    /// Returns a reference to the private exponent of the key.
191    #[corresponds(RSA_get0_key)]
192    #[must_use]
193    pub fn d(&self) -> &BigNumRef {
194        unsafe {
195            let mut d = ptr::null();
196            RSA_get0_key(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut d);
197            BigNumRef::from_ptr(d.cast_mut())
198        }
199    }
200
201    /// Returns a reference to the first factor of the exponent of the key.
202    #[corresponds(RSA_get0_factors)]
203    #[must_use]
204    pub fn p(&self) -> Option<&BigNumRef> {
205        unsafe {
206            let mut p = ptr::null();
207            RSA_get0_factors(self.as_ptr(), &mut p, ptr::null_mut());
208            if p.is_null() {
209                None
210            } else {
211                Some(BigNumRef::from_ptr(p.cast_mut()))
212            }
213        }
214    }
215
216    /// Returns a reference to the second factor of the exponent of the key.
217    #[corresponds(RSA_get0_factors)]
218    #[must_use]
219    pub fn q(&self) -> Option<&BigNumRef> {
220        unsafe {
221            let mut q = ptr::null();
222            RSA_get0_factors(self.as_ptr(), ptr::null_mut(), &mut q);
223            if q.is_null() {
224                None
225            } else {
226                Some(BigNumRef::from_ptr(q.cast_mut()))
227            }
228        }
229    }
230
231    /// Returns a reference to the first exponent used for CRT calculations.
232    #[corresponds(RSA_get0_crt_params)]
233    #[must_use]
234    pub fn dmp1(&self) -> Option<&BigNumRef> {
235        unsafe {
236            let mut dp = ptr::null();
237            RSA_get0_crt_params(self.as_ptr(), &mut dp, ptr::null_mut(), ptr::null_mut());
238            if dp.is_null() {
239                None
240            } else {
241                Some(BigNumRef::from_ptr(dp.cast_mut()))
242            }
243        }
244    }
245
246    /// Returns a reference to the second exponent used for CRT calculations.
247    #[corresponds(RSA_get0_crt_params)]
248    #[must_use]
249    pub fn dmq1(&self) -> Option<&BigNumRef> {
250        unsafe {
251            let mut dq = ptr::null();
252            RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), &mut dq, ptr::null_mut());
253            if dq.is_null() {
254                None
255            } else {
256                Some(BigNumRef::from_ptr(dq.cast_mut()))
257            }
258        }
259    }
260
261    /// Returns a reference to the coefficient used for CRT calculations.
262    #[corresponds(RSA_get0_crt_params)]
263    #[must_use]
264    pub fn iqmp(&self) -> Option<&BigNumRef> {
265        unsafe {
266            let mut qi = ptr::null();
267            RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut qi);
268            if qi.is_null() {
269                None
270            } else {
271                Some(BigNumRef::from_ptr(qi.cast_mut()))
272            }
273        }
274    }
275
276    /// Validates RSA parameters for correctness
277    #[corresponds(RSA_check_key)]
278    #[allow(clippy::unnecessary_cast)]
279    pub fn check_key(&self) -> Result<bool, ErrorStack> {
280        unsafe {
281            let result = ffi::RSA_check_key(self.as_ptr()) as i32;
282            if result == -1 {
283                Err(ErrorStack::get())
284            } else {
285                Ok(result == 1)
286            }
287        }
288    }
289}
290
291impl<T> RsaRef<T>
292where
293    T: HasPublic,
294{
295    to_pem! {
296        /// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
297        ///
298        /// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
299        #[corresponds(PEM_write_bio_RSA_PUBKEY)]
300        public_key_to_pem,
301        ffi::PEM_write_bio_RSA_PUBKEY
302    }
303
304    to_der! {
305        /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
306        #[corresponds(i2d_RSA_PUBKEY)]
307        public_key_to_der,
308        ffi::i2d_RSA_PUBKEY
309    }
310
311    to_pem! {
312        /// Serializes the public key into a PEM-encoded PKCS#1 RSAPublicKey structure.
313        ///
314        /// The output will have a header of `-----BEGIN RSA PUBLIC KEY-----`.
315        #[corresponds(PEM_write_bio_RSAPublicKey)]
316        public_key_to_pem_pkcs1,
317        ffi::PEM_write_bio_RSAPublicKey
318    }
319
320    to_der! {
321        /// Serializes the public key into a DER-encoded PKCS#1 RSAPublicKey structure.
322        #[corresponds(i2d_RSAPublicKey)]
323        public_key_to_der_pkcs1,
324        ffi::i2d_RSAPublicKey
325    }
326
327    /// Returns the size of the modulus in bytes.
328    #[corresponds(RSA_size)]
329    #[allow(clippy::unnecessary_cast)]
330    #[must_use]
331    pub fn size(&self) -> u32 {
332        unsafe { ffi::RSA_size(self.as_ptr()) as u32 }
333    }
334
335    /// Decrypts data using the public key, returning the number of decrypted bytes.
336    ///
337    /// # Panics
338    ///
339    /// Panics if `to` is smaller than `self.size()`.
340    pub fn public_decrypt(
341        &self,
342        from: &[u8],
343        to: &mut [u8],
344        padding: Padding,
345    ) -> Result<usize, ErrorStack> {
346        assert!(i32::try_from(from.len()).is_ok());
347        assert!(to.len() >= self.size() as usize);
348
349        unsafe {
350            let len = cvt_n(ffi::RSA_public_decrypt(
351                from.len(),
352                from.as_ptr(),
353                to.as_mut_ptr(),
354                self.as_ptr(),
355                padding.0,
356            ))?;
357            Ok(len as usize)
358        }
359    }
360
361    /// Encrypts data using the public key, returning the number of encrypted bytes.
362    ///
363    /// # Panics
364    ///
365    /// Panics if `to` is smaller than `self.size()`.
366    pub fn public_encrypt(
367        &self,
368        from: &[u8],
369        to: &mut [u8],
370        padding: Padding,
371    ) -> Result<usize, ErrorStack> {
372        assert!(from.len() <= i32::MAX as usize);
373        assert!(to.len() >= self.size() as usize);
374
375        unsafe {
376            let len = cvt_n(ffi::RSA_public_encrypt(
377                from.len(),
378                from.as_ptr(),
379                to.as_mut_ptr(),
380                self.as_ptr(),
381                padding.0,
382            ))?;
383            Ok(len as usize)
384        }
385    }
386
387    /// Returns a reference to the modulus of the key.
388    #[corresponds(RSA_get0_key)]
389    #[must_use]
390    pub fn n(&self) -> &BigNumRef {
391        unsafe {
392            let mut n = ptr::null();
393            RSA_get0_key(self.as_ptr(), &mut n, ptr::null_mut(), ptr::null_mut());
394            BigNumRef::from_ptr(n.cast_mut())
395        }
396    }
397
398    /// Returns a reference to the public exponent of the key.
399    #[corresponds(RSA_get0_key)]
400    #[must_use]
401    pub fn e(&self) -> &BigNumRef {
402        unsafe {
403            let mut e = ptr::null();
404            RSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut e, ptr::null_mut());
405            BigNumRef::from_ptr(e.cast_mut())
406        }
407    }
408}
409
410impl Rsa<Public> {
411    /// Creates a new RSA key with only public components.
412    ///
413    /// `n` is the modulus common to both public and private key.
414    /// `e` is the public exponent.
415    #[corresponds(RSA_new)]
416    pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa<Public>, ErrorStack> {
417        unsafe {
418            let rsa = cvt_p(ffi::RSA_new())?;
419            cvt(RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), ptr::null_mut()))?;
420            mem::forget((n, e));
421            Ok(Rsa::from_ptr(rsa))
422        }
423    }
424
425    from_pem! {
426        /// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing an RSA key.
427        ///
428        /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
429        #[corresponds(PEM_read_bio_RSA_PUBKEY)]
430        public_key_from_pem,
431        Rsa<Public>,
432        ffi::PEM_read_bio_RSA_PUBKEY
433    }
434
435    from_pem! {
436        /// Decodes a PEM-encoded PKCS#1 RSAPublicKey structure.
437        ///
438        /// The input should have a header of `-----BEGIN RSA PUBLIC KEY-----`.
439        #[corresponds(PEM_read_bio_RSAPublicKey)]
440        public_key_from_pem_pkcs1,
441        Rsa<Public>,
442        ffi::PEM_read_bio_RSAPublicKey
443    }
444
445    from_der! {
446        /// Decodes a DER-encoded SubjectPublicKeyInfo structure containing an RSA key.
447        #[corresponds(d2i_RSA_PUBKEY)]
448        public_key_from_der,
449        Rsa<Public>,
450        ffi::d2i_RSA_PUBKEY,
451        crate::libc_types::c_long
452    }
453
454    from_der! {
455        /// Decodes a DER-encoded PKCS#1 RSAPublicKey structure.
456        #[corresponds(d2i_RSAPublicKey)]
457        public_key_from_der_pkcs1,
458        Rsa<Public>,
459        ffi::d2i_RSAPublicKey,
460        crate::libc_types::c_long
461    }
462}
463
464pub struct RsaPrivateKeyBuilder {
465    rsa: Rsa<Private>,
466}
467
468impl RsaPrivateKeyBuilder {
469    /// Creates a new `RsaPrivateKeyBuilder`.
470    ///
471    /// `n` is the modulus common to both public and private key.
472    /// `e` is the public exponent and `d` is the private exponent.
473    #[corresponds(RSA_new)]
474    pub fn new(n: BigNum, e: BigNum, d: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
475        unsafe {
476            let rsa = cvt_p(ffi::RSA_new())?;
477            cvt(RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), d.as_ptr()))?;
478            mem::forget((n, e, d));
479            Ok(RsaPrivateKeyBuilder {
480                rsa: Rsa::from_ptr(rsa),
481            })
482        }
483    }
484
485    /// Sets the factors of the Rsa key.
486    ///
487    /// `p` and `q` are the first and second factors of `n`.
488    ///
489    // FIXME should be infallible
490    #[corresponds(RSA_set0_factors)]
491    pub fn set_factors(self, p: BigNum, q: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
492        unsafe {
493            cvt(RSA_set0_factors(self.rsa.as_ptr(), p.as_ptr(), q.as_ptr()))?;
494            mem::forget((p, q));
495        }
496        Ok(self)
497    }
498
499    /// Sets the Chinese Remainder Theorem params of the Rsa key.
500    ///
501    /// `dmp1`, `dmq1`, and `iqmp` are the exponents and coefficient for
502    /// CRT calculations which is used to speed up RSA operations.
503    #[corresponds(RSA_set0_crt_params)]
504    pub fn set_crt_params(
505        self,
506        dmp1: BigNum,
507        dmq1: BigNum,
508        iqmp: BigNum,
509    ) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
510        unsafe {
511            cvt(RSA_set0_crt_params(
512                self.rsa.as_ptr(),
513                dmp1.as_ptr(),
514                dmq1.as_ptr(),
515                iqmp.as_ptr(),
516            ))?;
517            mem::forget((dmp1, dmq1, iqmp));
518        }
519        Ok(self)
520    }
521
522    /// Returns the Rsa key.
523    #[must_use]
524    pub fn build(self) -> Rsa<Private> {
525        self.rsa
526    }
527}
528
529impl Rsa<Private> {
530    /// Creates a new RSA key with private components (public components are assumed).
531    ///
532    /// This a convenience method over
533    /// `Rsa::build(n, e, d)?.set_factors(p, q)?.set_crt_params(dmp1, dmq1, iqmp)?.build()`
534    #[allow(clippy::too_many_arguments, clippy::many_single_char_names)]
535    pub fn from_private_components(
536        n: BigNum,
537        e: BigNum,
538        d: BigNum,
539        p: BigNum,
540        q: BigNum,
541        dmp1: BigNum,
542        dmq1: BigNum,
543        iqmp: BigNum,
544    ) -> Result<Rsa<Private>, ErrorStack> {
545        Ok(RsaPrivateKeyBuilder::new(n, e, d)?
546            .set_factors(p, q)?
547            .set_crt_params(dmp1, dmq1, iqmp)?
548            .build())
549    }
550
551    /// Generates a public/private key pair with the specified size.
552    ///
553    /// The public exponent will be 65537.
554    #[corresponds(RSA_generate_key_ex)]
555    pub fn generate(bits: u32) -> Result<Rsa<Private>, ErrorStack> {
556        let e = BigNum::from_u32(ffi::RSA_F4 as u32)?;
557        Rsa::generate_with_e(bits, &e)
558    }
559
560    /// Generates a public/private key pair with the specified size and a custom exponent.
561    ///
562    /// Unless you have specific needs and know what you're doing, use `Rsa::generate` instead.
563    #[corresponds(RSA_generate_key_ex)]
564    pub fn generate_with_e(bits: u32, e: &BigNumRef) -> Result<Rsa<Private>, ErrorStack> {
565        unsafe {
566            let rsa = Rsa::from_ptr(cvt_p(ffi::RSA_new())?);
567            cvt(ffi::RSA_generate_key_ex(
568                rsa.0,
569                bits as c_int,
570                e.as_ptr(),
571                ptr::null_mut(),
572            ))?;
573            Ok(rsa)
574        }
575    }
576
577    // FIXME these need to identify input formats
578    private_key_from_pem! {
579        /// Deserializes a private key from a PEM-encoded PKCS#1 RSAPrivateKey structure.
580        #[corresponds(PEM_read_bio_RSAPrivateKey)]
581        private_key_from_pem,
582
583        /// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
584        #[corresponds(PEM_read_bio_RSAPrivateKey)]
585        private_key_from_pem_passphrase,
586
587        /// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
588        ///
589        /// The callback should fill the password into the provided buffer and return its length.
590        #[corresponds(PEM_read_bio_RSAPrivateKey)]
591        private_key_from_pem_callback,
592        Rsa<Private>,
593        ffi::PEM_read_bio_RSAPrivateKey
594    }
595
596    from_der! {
597        /// Decodes a DER-encoded PKCS#1 RSAPrivateKey structure.
598        #[corresponds(d2i_RSAPrivateKey)]
599        private_key_from_der,
600        Rsa<Private>,
601        ffi::d2i_RSAPrivateKey,
602        crate::libc_types::c_long
603    }
604}
605
606impl<T> fmt::Debug for Rsa<T> {
607    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
608        write!(f, "Rsa")
609    }
610}
611
612use crate::ffi::{
613    RSA_get0_crt_params, RSA_get0_factors, RSA_get0_key, RSA_set0_crt_params, RSA_set0_factors,
614    RSA_set0_key,
615};
616
617#[cfg(test)]
618mod test {
619    use crate::symm::Cipher;
620
621    use super::*;
622
623    #[test]
624    fn test_from_password() {
625        let key = include_bytes!("../test/rsa-encrypted.pem");
626        Rsa::private_key_from_pem_passphrase(key, b"mypass").unwrap();
627    }
628
629    #[test]
630    fn test_from_password_callback() {
631        let mut password_queried = false;
632        let key = include_bytes!("../test/rsa-encrypted.pem");
633        Rsa::private_key_from_pem_callback(key, |password| {
634            password_queried = true;
635            password[..6].copy_from_slice(b"mypass");
636            Ok(6)
637        })
638        .unwrap();
639
640        assert!(password_queried);
641    }
642
643    #[test]
644    fn test_to_password() {
645        let key = Rsa::generate(2048).unwrap();
646        let pem = key
647            .private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar")
648            .unwrap();
649        Rsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
650        assert!(Rsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
651    }
652
653    #[test]
654    fn test_public_encrypt_private_decrypt_with_padding() {
655        let key = include_bytes!("../test/rsa.pem.pub");
656        let public_key = Rsa::public_key_from_pem(key).unwrap();
657
658        let mut result = vec![0; public_key.size() as usize];
659        let original_data = b"This is test";
660        let len = public_key
661            .public_encrypt(original_data, &mut result, Padding::PKCS1)
662            .unwrap();
663        assert_eq!(len, 256);
664
665        let pkey = include_bytes!("../test/rsa.pem");
666        let private_key = Rsa::private_key_from_pem(pkey).unwrap();
667        let mut dec_result = vec![0; private_key.size() as usize];
668        let len = private_key
669            .private_decrypt(&result, &mut dec_result, Padding::PKCS1)
670            .unwrap();
671
672        assert_eq!(&dec_result[..len], original_data);
673    }
674
675    #[test]
676    fn test_private_encrypt() {
677        let k0 = super::Rsa::generate(512).unwrap();
678        let k0pkey = k0.public_key_to_pem().unwrap();
679        let k1 = super::Rsa::public_key_from_pem(&k0pkey).unwrap();
680
681        let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8];
682
683        let mut emesg = vec![0; k0.size() as usize];
684        k0.private_encrypt(&msg, &mut emesg, Padding::PKCS1)
685            .unwrap();
686        let mut dmesg = vec![0; k1.size() as usize];
687        let len = k1
688            .public_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
689            .unwrap();
690        assert_eq!(msg, &dmesg[..len]);
691    }
692
693    #[test]
694    fn test_public_encrypt() {
695        let k0 = super::Rsa::generate(512).unwrap();
696        let k0pkey = k0.private_key_to_pem().unwrap();
697        let k1 = super::Rsa::private_key_from_pem(&k0pkey).unwrap();
698
699        let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8];
700
701        let mut emesg = vec![0; k0.size() as usize];
702        k0.public_encrypt(&msg, &mut emesg, Padding::PKCS1).unwrap();
703        let mut dmesg = vec![0; k1.size() as usize];
704        let len = k1
705            .private_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
706            .unwrap();
707        assert_eq!(msg, &dmesg[..len]);
708    }
709
710    #[test]
711    fn test_public_key_from_pem_pkcs1() {
712        let key = include_bytes!("../test/pkcs1.pem.pub");
713        Rsa::public_key_from_pem_pkcs1(key).unwrap();
714    }
715
716    #[test]
717    #[should_panic]
718    fn test_public_key_from_pem_pkcs1_file_panic() {
719        let key = include_bytes!("../test/key.pem.pub");
720        Rsa::public_key_from_pem_pkcs1(key).unwrap();
721    }
722
723    #[test]
724    fn test_public_key_to_pem_pkcs1() {
725        let keypair = super::Rsa::generate(512).unwrap();
726        let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
727        super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
728    }
729
730    #[test]
731    #[should_panic]
732    fn test_public_key_from_pem_pkcs1_generate_panic() {
733        let keypair = super::Rsa::generate(512).unwrap();
734        let pubkey_pem = keypair.public_key_to_pem().unwrap();
735        super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
736    }
737
738    #[test]
739    fn test_pem_pkcs1_encrypt() {
740        let keypair = super::Rsa::generate(2048).unwrap();
741        let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
742        let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
743        let msg = b"Hello, world!";
744
745        let mut encrypted = vec![0; pubkey.size() as usize];
746        let len = pubkey
747            .public_encrypt(msg, &mut encrypted, Padding::PKCS1)
748            .unwrap();
749        assert!(len > msg.len());
750        let mut decrypted = vec![0; keypair.size() as usize];
751        let len = keypair
752            .private_decrypt(&encrypted, &mut decrypted, Padding::PKCS1)
753            .unwrap();
754        assert_eq!(len, msg.len());
755        assert_eq!(&decrypted[..len], msg);
756    }
757
758    #[test]
759    fn test_pem_pkcs1_padding() {
760        let keypair = super::Rsa::generate(2048).unwrap();
761        let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
762        let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
763        let msg = b"foo";
764
765        let mut encrypted1 = vec![0; pubkey.size() as usize];
766        let mut encrypted2 = vec![0; pubkey.size() as usize];
767        let len1 = pubkey
768            .public_encrypt(msg, &mut encrypted1, Padding::PKCS1)
769            .unwrap();
770        let len2 = pubkey
771            .public_encrypt(msg, &mut encrypted2, Padding::PKCS1)
772            .unwrap();
773        assert!(len1 > (msg.len() + 1));
774        assert_eq!(len1, len2);
775        assert_ne!(encrypted1, encrypted2);
776    }
777
778    #[test]
779    #[allow(clippy::redundant_clone)]
780    fn clone() {
781        let key = Rsa::generate(2048).unwrap();
782        drop(key.clone());
783    }
784
785    #[test]
786    fn generate_with_e() {
787        let e = BigNum::from_u32(0x10001).unwrap();
788        Rsa::generate_with_e(2048, &e).unwrap();
789    }
790}