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