1use cfg_if::cfg_if;
27use foreign_types::{ForeignType, ForeignTypeRef};
28use libc::c_int;
29use std::fmt;
30use std::mem;
31use std::ptr;
32
33use crate::bn::{BigNum, BigNumRef};
34use crate::error::ErrorStack;
35use crate::pkey::{HasPrivate, HasPublic, Private, Public};
36use crate::util::ForeignTypeRefExt;
37use crate::{cvt, cvt_n, cvt_p, LenType};
38use openssl_macros::corresponds;
39
40#[derive(Debug, Copy, Clone, PartialEq, Eq)]
46pub struct Padding(c_int);
47
48impl Padding {
49 pub const NONE: Padding = Padding(ffi::RSA_NO_PADDING);
50 pub const PKCS1: Padding = Padding(ffi::RSA_PKCS1_PADDING);
51 pub const PKCS1_OAEP: Padding = Padding(ffi::RSA_PKCS1_OAEP_PADDING);
52 pub const PKCS1_PSS: Padding = Padding(ffi::RSA_PKCS1_PSS_PADDING);
53
54 pub fn from_raw(value: c_int) -> Padding {
56 Padding(value)
57 }
58
59 #[allow(clippy::trivially_copy_pass_by_ref)]
61 pub fn as_raw(&self) -> c_int {
62 self.0
63 }
64}
65
66generic_foreign_type_and_impl_send_sync! {
67 type CType = ffi::RSA;
68 fn drop = ffi::RSA_free;
69
70 pub struct Rsa<T>;
72
73 pub struct RsaRef<T>;
75}
76
77impl<T> Clone for Rsa<T> {
78 fn clone(&self) -> Rsa<T> {
79 (**self).to_owned()
80 }
81}
82
83impl<T> ToOwned for RsaRef<T> {
84 type Owned = Rsa<T>;
85
86 fn to_owned(&self) -> Rsa<T> {
87 unsafe {
88 ffi::RSA_up_ref(self.as_ptr());
89 Rsa::from_ptr(self.as_ptr())
90 }
91 }
92}
93
94impl<T> RsaRef<T>
95where
96 T: HasPrivate,
97{
98 private_key_to_pem! {
99 #[corresponds(PEM_write_bio_RSAPrivateKey)]
103 private_key_to_pem,
104 #[corresponds(PEM_write_bio_RSAPrivateKey)]
108 private_key_to_pem_passphrase,
109 ffi::PEM_write_bio_RSAPrivateKey
110 }
111
112 to_der! {
113 #[corresponds(i2d_RSAPrivateKey)]
115 private_key_to_der,
116 ffi::i2d_RSAPrivateKey
117 }
118
119 #[corresponds(RSA_private_decrypt)]
126 pub fn private_decrypt(
127 &self,
128 from: &[u8],
129 to: &mut [u8],
130 padding: Padding,
131 ) -> Result<usize, ErrorStack> {
132 assert!(from.len() <= i32::MAX as usize);
133 assert!(to.len() >= self.size() as usize);
134
135 unsafe {
136 let len = cvt_n(ffi::RSA_private_decrypt(
137 from.len() as LenType,
138 from.as_ptr(),
139 to.as_mut_ptr(),
140 self.as_ptr(),
141 padding.0,
142 ))?;
143 Ok(len as usize)
144 }
145 }
146
147 #[corresponds(RSA_private_encrypt)]
154 pub fn private_encrypt(
155 &self,
156 from: &[u8],
157 to: &mut [u8],
158 padding: Padding,
159 ) -> Result<usize, ErrorStack> {
160 assert!(from.len() <= i32::MAX as usize);
161 assert!(to.len() >= self.size() as usize);
162
163 unsafe {
164 let len = cvt_n(ffi::RSA_private_encrypt(
165 from.len() as LenType,
166 from.as_ptr(),
167 to.as_mut_ptr(),
168 self.as_ptr(),
169 padding.0,
170 ))?;
171 Ok(len as usize)
172 }
173 }
174
175 #[corresponds(RSA_get0_key)]
177 pub fn d(&self) -> &BigNumRef {
178 unsafe {
179 let mut d = ptr::null();
180 RSA_get0_key(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut d);
181 BigNumRef::from_const_ptr(d)
182 }
183 }
184
185 #[corresponds(RSA_get0_factors)]
187 pub fn p(&self) -> Option<&BigNumRef> {
188 unsafe {
189 let mut p = ptr::null();
190 RSA_get0_factors(self.as_ptr(), &mut p, ptr::null_mut());
191 BigNumRef::from_const_ptr_opt(p)
192 }
193 }
194
195 #[corresponds(RSA_get0_factors)]
197 pub fn q(&self) -> Option<&BigNumRef> {
198 unsafe {
199 let mut q = ptr::null();
200 RSA_get0_factors(self.as_ptr(), ptr::null_mut(), &mut q);
201 BigNumRef::from_const_ptr_opt(q)
202 }
203 }
204
205 #[corresponds(RSA_get0_crt_params)]
207 pub fn dmp1(&self) -> Option<&BigNumRef> {
208 unsafe {
209 let mut dp = ptr::null();
210 RSA_get0_crt_params(self.as_ptr(), &mut dp, ptr::null_mut(), ptr::null_mut());
211 BigNumRef::from_const_ptr_opt(dp)
212 }
213 }
214
215 #[corresponds(RSA_get0_crt_params)]
217 pub fn dmq1(&self) -> Option<&BigNumRef> {
218 unsafe {
219 let mut dq = ptr::null();
220 RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), &mut dq, ptr::null_mut());
221 BigNumRef::from_const_ptr_opt(dq)
222 }
223 }
224
225 #[corresponds(RSA_get0_crt_params)]
227 pub fn iqmp(&self) -> Option<&BigNumRef> {
228 unsafe {
229 let mut qi = ptr::null();
230 RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut qi);
231 BigNumRef::from_const_ptr_opt(qi)
232 }
233 }
234
235 #[corresponds(RSA_check_key)]
237 pub fn check_key(&self) -> Result<bool, ErrorStack> {
238 unsafe {
239 let result = ffi::RSA_check_key(self.as_ptr());
240 if result != 1 {
241 let errors = ErrorStack::get();
242 if errors.errors().is_empty() {
243 Ok(false)
244 } else {
245 Err(errors)
246 }
247 } else {
248 Ok(true)
249 }
250 }
251 }
252}
253
254impl<T> RsaRef<T>
255where
256 T: HasPublic,
257{
258 to_pem! {
259 #[corresponds(PEM_write_bio_RSA_PUBKEY)]
263 public_key_to_pem,
264 ffi::PEM_write_bio_RSA_PUBKEY
265 }
266
267 to_der! {
268 #[corresponds(i2d_RSA_PUBKEY)]
270 public_key_to_der,
271 ffi::i2d_RSA_PUBKEY
272 }
273
274 to_pem! {
275 #[corresponds(PEM_write_bio_RSAPublicKey)]
279 public_key_to_pem_pkcs1,
280 ffi::PEM_write_bio_RSAPublicKey
281 }
282
283 to_der! {
284 #[corresponds(i2d_RSAPublicKey)]
286 public_key_to_der_pkcs1,
287 ffi::i2d_RSAPublicKey
288 }
289
290 #[corresponds(RSA_size)]
292 pub fn size(&self) -> u32 {
293 unsafe { ffi::RSA_size(self.as_ptr()) as u32 }
294 }
295
296 #[corresponds(RSA_public_decrypt)]
302 pub fn public_decrypt(
303 &self,
304 from: &[u8],
305 to: &mut [u8],
306 padding: Padding,
307 ) -> Result<usize, ErrorStack> {
308 assert!(from.len() <= i32::MAX as usize);
309 assert!(to.len() >= self.size() as usize);
310
311 unsafe {
312 let len = cvt_n(ffi::RSA_public_decrypt(
313 from.len() as LenType,
314 from.as_ptr(),
315 to.as_mut_ptr(),
316 self.as_ptr(),
317 padding.0,
318 ))?;
319 Ok(len as usize)
320 }
321 }
322
323 #[corresponds(RSA_public_encrypt)]
329 pub fn public_encrypt(
330 &self,
331 from: &[u8],
332 to: &mut [u8],
333 padding: Padding,
334 ) -> Result<usize, ErrorStack> {
335 assert!(from.len() <= i32::MAX as usize);
336 assert!(to.len() >= self.size() as usize);
337
338 unsafe {
339 let len = cvt_n(ffi::RSA_public_encrypt(
340 from.len() as LenType,
341 from.as_ptr(),
342 to.as_mut_ptr(),
343 self.as_ptr(),
344 padding.0,
345 ))?;
346 Ok(len as usize)
347 }
348 }
349
350 #[corresponds(RSA_get0_key)]
352 pub fn n(&self) -> &BigNumRef {
353 unsafe {
354 let mut n = ptr::null();
355 RSA_get0_key(self.as_ptr(), &mut n, ptr::null_mut(), ptr::null_mut());
356 BigNumRef::from_const_ptr(n)
357 }
358 }
359
360 #[corresponds(RSA_get0_key)]
362 pub fn e(&self) -> &BigNumRef {
363 unsafe {
364 let mut e = ptr::null();
365 RSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut e, ptr::null_mut());
366 BigNumRef::from_const_ptr(e)
367 }
368 }
369}
370
371impl Rsa<Public> {
372 pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa<Public>, ErrorStack> {
382 unsafe {
383 let rsa = cvt_p(ffi::RSA_new())?;
384 RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), ptr::null_mut());
385 mem::forget((n, e));
386 Ok(Rsa::from_ptr(rsa))
387 }
388 }
389
390 from_pem! {
391 #[corresponds(PEM_read_bio_RSA_PUBKEY)]
395 public_key_from_pem,
396 Rsa<Public>,
397 ffi::PEM_read_bio_RSA_PUBKEY
398 }
399
400 from_pem! {
401 #[corresponds(PEM_read_bio_RSAPublicKey)]
405 public_key_from_pem_pkcs1,
406 Rsa<Public>,
407 ffi::PEM_read_bio_RSAPublicKey
408 }
409
410 from_der! {
411 #[corresponds(d2i_RSA_PUBKEY)]
413 public_key_from_der,
414 Rsa<Public>,
415 ffi::d2i_RSA_PUBKEY
416 }
417
418 from_der! {
419 #[corresponds(d2i_RSAPublicKey)]
421 public_key_from_der_pkcs1,
422 Rsa<Public>,
423 ffi::d2i_RSAPublicKey
424 }
425}
426
427pub struct RsaPrivateKeyBuilder {
428 rsa: Rsa<Private>,
429}
430
431impl RsaPrivateKeyBuilder {
432 pub fn new(n: BigNum, e: BigNum, d: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
442 unsafe {
443 let rsa = cvt_p(ffi::RSA_new())?;
444 RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), d.as_ptr());
445 mem::forget((n, e, d));
446 Ok(RsaPrivateKeyBuilder {
447 rsa: Rsa::from_ptr(rsa),
448 })
449 }
450 }
451
452 #[corresponds(RSA_set0_factors)]
456 pub fn set_factors(self, p: BigNum, q: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
458 unsafe {
459 RSA_set0_factors(self.rsa.as_ptr(), p.as_ptr(), q.as_ptr());
460 mem::forget((p, q));
461 }
462 Ok(self)
463 }
464
465 #[corresponds(RSA_set0_crt_params)]
470 pub fn set_crt_params(
472 self,
473 dmp1: BigNum,
474 dmq1: BigNum,
475 iqmp: BigNum,
476 ) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
477 unsafe {
478 RSA_set0_crt_params(
479 self.rsa.as_ptr(),
480 dmp1.as_ptr(),
481 dmq1.as_ptr(),
482 iqmp.as_ptr(),
483 );
484 mem::forget((dmp1, dmq1, iqmp));
485 }
486 Ok(self)
487 }
488
489 pub fn build(self) -> Rsa<Private> {
491 self.rsa
492 }
493}
494
495impl Rsa<Private> {
496 #[allow(clippy::too_many_arguments, clippy::many_single_char_names)]
511 pub fn from_private_components(
512 n: BigNum,
513 e: BigNum,
514 d: BigNum,
515 p: BigNum,
516 q: BigNum,
517 dmp1: BigNum,
518 dmq1: BigNum,
519 iqmp: BigNum,
520 ) -> Result<Rsa<Private>, ErrorStack> {
521 Ok(RsaPrivateKeyBuilder::new(n, e, d)?
522 .set_factors(p, q)?
523 .set_crt_params(dmp1, dmq1, iqmp)?
524 .build())
525 }
526
527 #[corresponds(RSA_generate_key_ex)]
531 pub fn generate(bits: u32) -> Result<Rsa<Private>, ErrorStack> {
532 let e = BigNum::from_u32(ffi::RSA_F4 as u32)?;
533 Rsa::generate_with_e(bits, &e)
534 }
535
536 #[corresponds(RSA_generate_key_ex)]
540 pub fn generate_with_e(bits: u32, e: &BigNumRef) -> Result<Rsa<Private>, ErrorStack> {
541 unsafe {
542 let rsa = Rsa::from_ptr(cvt_p(ffi::RSA_new())?);
543 cvt(ffi::RSA_generate_key_ex(
544 rsa.0,
545 bits as c_int,
546 e.as_ptr(),
547 ptr::null_mut(),
548 ))?;
549 Ok(rsa)
550 }
551 }
552
553 private_key_from_pem! {
555 #[corresponds(PEM_read_bio_RSAPrivateKey)]
557 private_key_from_pem,
558
559 #[corresponds(PEM_read_bio_RSAPrivateKey)]
561 private_key_from_pem_passphrase,
562
563 #[corresponds(PEM_read_bio_RSAPrivateKey)]
567 private_key_from_pem_callback,
568 Rsa<Private>,
569 ffi::PEM_read_bio_RSAPrivateKey
570 }
571
572 from_der! {
573 #[corresponds(d2i_RSAPrivateKey)]
575 private_key_from_der,
576 Rsa<Private>,
577 ffi::d2i_RSAPrivateKey
578 }
579}
580
581impl<T> fmt::Debug for Rsa<T> {
582 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
583 write!(f, "Rsa")
584 }
585}
586
587cfg_if! {
588 if #[cfg(any(ossl110, libressl273, boringssl, awslc))] {
589 use ffi::{
590 RSA_get0_key, RSA_get0_factors, RSA_get0_crt_params, RSA_set0_key, RSA_set0_factors,
591 RSA_set0_crt_params,
592 };
593 } else {
594 #[allow(bad_style)]
595 unsafe fn RSA_get0_key(
596 r: *const ffi::RSA,
597 n: *mut *const ffi::BIGNUM,
598 e: *mut *const ffi::BIGNUM,
599 d: *mut *const ffi::BIGNUM,
600 ) {
601 if !n.is_null() {
602 *n = (*r).n;
603 }
604 if !e.is_null() {
605 *e = (*r).e;
606 }
607 if !d.is_null() {
608 *d = (*r).d;
609 }
610 }
611
612 #[allow(bad_style)]
613 unsafe fn RSA_get0_factors(
614 r: *const ffi::RSA,
615 p: *mut *const ffi::BIGNUM,
616 q: *mut *const ffi::BIGNUM,
617 ) {
618 if !p.is_null() {
619 *p = (*r).p;
620 }
621 if !q.is_null() {
622 *q = (*r).q;
623 }
624 }
625
626 #[allow(bad_style)]
627 unsafe fn RSA_get0_crt_params(
628 r: *const ffi::RSA,
629 dmp1: *mut *const ffi::BIGNUM,
630 dmq1: *mut *const ffi::BIGNUM,
631 iqmp: *mut *const ffi::BIGNUM,
632 ) {
633 if !dmp1.is_null() {
634 *dmp1 = (*r).dmp1;
635 }
636 if !dmq1.is_null() {
637 *dmq1 = (*r).dmq1;
638 }
639 if !iqmp.is_null() {
640 *iqmp = (*r).iqmp;
641 }
642 }
643
644 #[allow(bad_style)]
645 unsafe fn RSA_set0_key(
646 r: *mut ffi::RSA,
647 n: *mut ffi::BIGNUM,
648 e: *mut ffi::BIGNUM,
649 d: *mut ffi::BIGNUM,
650 ) -> c_int {
651 (*r).n = n;
652 (*r).e = e;
653 (*r).d = d;
654 1
655 }
656
657 #[allow(bad_style)]
658 unsafe fn RSA_set0_factors(
659 r: *mut ffi::RSA,
660 p: *mut ffi::BIGNUM,
661 q: *mut ffi::BIGNUM,
662 ) -> c_int {
663 (*r).p = p;
664 (*r).q = q;
665 1
666 }
667
668 #[allow(bad_style)]
669 unsafe fn RSA_set0_crt_params(
670 r: *mut ffi::RSA,
671 dmp1: *mut ffi::BIGNUM,
672 dmq1: *mut ffi::BIGNUM,
673 iqmp: *mut ffi::BIGNUM,
674 ) -> c_int {
675 (*r).dmp1 = dmp1;
676 (*r).dmq1 = dmq1;
677 (*r).iqmp = iqmp;
678 1
679 }
680 }
681}
682
683#[cfg(test)]
684mod test {
685 use crate::symm::Cipher;
686
687 use super::*;
688
689 #[test]
690 fn test_from_password() {
691 let key = include_bytes!("../test/rsa-encrypted.pem");
692 Rsa::private_key_from_pem_passphrase(key, b"mypass").unwrap();
693 }
694
695 #[test]
696 fn test_from_password_callback() {
697 let mut password_queried = false;
698 let key = include_bytes!("../test/rsa-encrypted.pem");
699 Rsa::private_key_from_pem_callback(key, |password| {
700 password_queried = true;
701 password[..6].copy_from_slice(b"mypass");
702 Ok(6)
703 })
704 .unwrap();
705
706 assert!(password_queried);
707 }
708
709 #[test]
710 fn test_to_password() {
711 let key = Rsa::generate(2048).unwrap();
712 let pem = key
713 .private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar")
714 .unwrap();
715 Rsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
716 assert!(Rsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
717 }
718
719 #[test]
720 fn test_public_encrypt_private_decrypt_with_padding() {
721 let key = include_bytes!("../test/rsa.pem.pub");
722 let public_key = Rsa::public_key_from_pem(key).unwrap();
723
724 let mut result = vec![0; public_key.size() as usize];
725 let original_data = b"This is test";
726 let len = public_key
727 .public_encrypt(original_data, &mut result, Padding::PKCS1)
728 .unwrap();
729 assert_eq!(len, 256);
730
731 let pkey = include_bytes!("../test/rsa.pem");
732 let private_key = Rsa::private_key_from_pem(pkey).unwrap();
733 let mut dec_result = vec![0; private_key.size() as usize];
734 let len = private_key
735 .private_decrypt(&result, &mut dec_result, Padding::PKCS1)
736 .unwrap();
737
738 assert_eq!(&dec_result[..len], original_data);
739 }
740
741 #[test]
742 fn test_private_encrypt() {
743 let k0 = super::Rsa::generate(512).unwrap();
744 let k0pkey = k0.public_key_to_pem().unwrap();
745 let k1 = super::Rsa::public_key_from_pem(&k0pkey).unwrap();
746
747 let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8];
748
749 let mut emesg = vec![0; k0.size() as usize];
750 k0.private_encrypt(&msg, &mut emesg, Padding::PKCS1)
751 .unwrap();
752 let mut dmesg = vec![0; k1.size() as usize];
753 let len = k1
754 .public_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
755 .unwrap();
756 assert_eq!(msg, &dmesg[..len]);
757 }
758
759 #[test]
760 fn test_public_encrypt() {
761 let k0 = super::Rsa::generate(512).unwrap();
762 let k0pkey = k0.private_key_to_pem().unwrap();
763 let k1 = super::Rsa::private_key_from_pem(&k0pkey).unwrap();
764
765 let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8];
766
767 let mut emesg = vec![0; k0.size() as usize];
768 k0.public_encrypt(&msg, &mut emesg, Padding::PKCS1).unwrap();
769 let mut dmesg = vec![0; k1.size() as usize];
770 let len = k1
771 .private_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
772 .unwrap();
773 assert_eq!(msg, &dmesg[..len]);
774 }
775
776 #[test]
777 fn test_public_key_from_pem_pkcs1() {
778 let key = include_bytes!("../test/pkcs1.pem.pub");
779 Rsa::public_key_from_pem_pkcs1(key).unwrap();
780 }
781
782 #[test]
783 #[should_panic]
784 fn test_public_key_from_pem_pkcs1_file_panic() {
785 let key = include_bytes!("../test/key.pem.pub");
786 Rsa::public_key_from_pem_pkcs1(key).unwrap();
787 }
788
789 #[test]
790 fn test_public_key_to_pem_pkcs1() {
791 let keypair = super::Rsa::generate(512).unwrap();
792 let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
793 super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
794 }
795
796 #[test]
797 #[should_panic]
798 fn test_public_key_from_pem_pkcs1_generate_panic() {
799 let keypair = super::Rsa::generate(512).unwrap();
800 let pubkey_pem = keypair.public_key_to_pem().unwrap();
801 super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
802 }
803
804 #[test]
805 fn test_pem_pkcs1_encrypt() {
806 let keypair = super::Rsa::generate(2048).unwrap();
807 let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
808 let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
809 let msg = b"Hello, world!";
810
811 let mut encrypted = vec![0; pubkey.size() as usize];
812 let len = pubkey
813 .public_encrypt(msg, &mut encrypted, Padding::PKCS1)
814 .unwrap();
815 assert!(len > msg.len());
816 let mut decrypted = vec![0; keypair.size() as usize];
817 let len = keypair
818 .private_decrypt(&encrypted, &mut decrypted, Padding::PKCS1)
819 .unwrap();
820 assert_eq!(len, msg.len());
821 assert_eq!(&decrypted[..len], msg);
822 }
823
824 #[test]
825 fn test_pem_pkcs1_padding() {
826 let keypair = super::Rsa::generate(2048).unwrap();
827 let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
828 let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
829 let msg = b"foo";
830
831 let mut encrypted1 = vec![0; pubkey.size() as usize];
832 let mut encrypted2 = vec![0; pubkey.size() as usize];
833 let len1 = pubkey
834 .public_encrypt(msg, &mut encrypted1, Padding::PKCS1)
835 .unwrap();
836 let len2 = pubkey
837 .public_encrypt(msg, &mut encrypted2, Padding::PKCS1)
838 .unwrap();
839 assert!(len1 > (msg.len() + 1));
840 assert_eq!(len1, len2);
841 assert_ne!(encrypted1, encrypted2);
842 }
843
844 #[test]
845 #[allow(clippy::redundant_clone)]
846 fn clone() {
847 let key = Rsa::generate(2048).unwrap();
848 drop(key.clone());
849 }
850
851 #[test]
852 fn generate_with_e() {
853 let e = BigNum::from_u32(0x10001).unwrap();
854 Rsa::generate_with_e(2048, &e).unwrap();
855 }
856
857 #[test]
858 fn test_check_key() {
859 let k = Rsa::private_key_from_pem_passphrase(
860 include_bytes!("../test/rsa-encrypted.pem"),
861 b"mypass",
862 )
863 .unwrap();
864 assert!(matches!(k.check_key(), Ok(true)));
865 assert!(ErrorStack::get().errors().is_empty());
866
867 if let Ok(k) = Rsa::private_key_from_pem(include_bytes!("../test/corrupted-rsa.pem")) {
869 assert!(matches!(k.check_key(), Ok(false) | Err(_)));
870 assert!(ErrorStack::get().errors().is_empty());
871 }
872 }
873}