Skip to main content

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