rsa_pem/
lib.rs

1//! Read and Write PEM files from RSA types
2//!
3//! This library will be useless after the next release of the RSA crate, which should have this
4//! functionality baked in.
5//!
6//! ### Examples
7//! ```rust
8//! use rsa_pem::KeyExt;
9//! use rsa::RSAPrivateKey;
10//! #
11//! # let mut rng = rand::thread_rng();
12//! # let private_key = RSAPrivateKey::new(&mut rng, 2048).unwrap();
13//!
14//! let pkcs8_string = private_key.to_pem_pkcs8().unwrap();
15//! let private_key = RSAPrivateKey::from_pem_pkcs8(&pkcs8_string).unwrap();
16//! ```
17use num_bigint_dig::{BigInt, BigUint, Sign};
18use thiserror::Error;
19
20mod private;
21mod public;
22
23const RSA_OID: [u64; 7] = [1, 2, 840, 113_549, 1, 1, 1];
24
25/// Extensions to keys for formatting and reading PKCS1 and PKCS8 PEM strings
26pub trait KeyExt {
27    /// Write a PKCS8 pem string
28    fn to_pem_pkcs8(&self) -> Result<String, KeyError>;
29
30    /// Read a PKCS8 pem string
31    fn from_pem_pkcs8(pem: &str) -> Result<Self, KeyError>
32    where
33        Self: Sized;
34
35    /// Write a PKCS1 pem string
36    fn to_pem_pkcs1(&self) -> Result<String, KeyError>;
37
38    /// Read a PKCS1 pem string
39    fn from_pem_pkcs1(pem: &str) -> Result<Self, KeyError>
40    where
41        Self: Sized;
42}
43
44/// Errors produced when serializing or deserializing keys
45#[derive(Debug, Error)]
46pub enum KeyError {
47    /// The PEM wrapper has the wrong name
48    #[error("Invalid key kind supplied")]
49    Kind,
50
51    /// The file isn't PEM encoded
52    #[error("Key not PEM-formatted")]
53    Pem,
54
55    /// Parsing the DER bytes failed
56    #[error("Error parsing key, {}", .0)]
57    Parse(rsa::errors::Error),
58
59    /// The private key's fields don't make sense
60    #[error("Constructed key is invalid")]
61    Validate,
62
63    /// Failed to serialize to DER bytes
64    #[error("Could not serialize key")]
65    Serialize,
66}
67
68fn from_dig(biguint: &BigUint) -> num_bigint::BigUint {
69    num_bigint::BigUint::from_bytes_be(&biguint.to_bytes_be())
70}
71
72fn int_from_dig(bigint: &BigInt) -> num_bigint::BigInt {
73    let (sign, bytes) = bigint.to_bytes_be();
74    num_bigint::BigInt::from_bytes_be(sign_from_dig(sign), &bytes)
75}
76
77fn sign_from_dig(sign: Sign) -> num_bigint::Sign {
78    match sign {
79        Sign::Minus => num_bigint::Sign::Minus,
80        Sign::NoSign => num_bigint::Sign::NoSign,
81        Sign::Plus => num_bigint::Sign::Plus,
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use crate::KeyExt;
88    use rsa::{hash::Hash, padding::PaddingScheme, PublicKey, RSAPrivateKey, RSAPublicKey};
89    use sha2::{Digest, Sha256};
90
91    static SIGNING_STRING: &[u8] = b"Hewwo, Mr Obama";
92
93    fn padding() -> PaddingScheme {
94        PaddingScheme::PKCS1v15Sign {
95            hash: Some(Hash::SHA2_256),
96        }
97    }
98
99    #[test]
100    fn priv_can_complete_cycle_pkcs1() {
101        let mut rng = rand::thread_rng();
102        let rsa = RSAPrivateKey::new(&mut rng, 2048).unwrap();
103        let hashed = Sha256::digest(SIGNING_STRING);
104        let sig = rsa.sign(padding(), &hashed).unwrap();
105
106        let string = rsa.to_pem_pkcs1().unwrap();
107
108        let res = RSAPrivateKey::from_pem_pkcs1(&string);
109
110        let pubkey = res.unwrap().to_public_key();
111        pubkey.verify(padding(), &hashed, &sig).unwrap();
112    }
113
114    #[test]
115    fn pub_can_complete_cycle_pkcs1() {
116        let mut rng = rand::thread_rng();
117        let rsa = RSAPrivateKey::new(&mut rng, 2048).unwrap();
118        let hashed = Sha256::digest(SIGNING_STRING);
119        let sig = rsa.sign(padding(), &hashed).unwrap();
120
121        let rsa = rsa.to_public_key();
122        let string = rsa.to_pem_pkcs1().unwrap();
123
124        let res = RSAPublicKey::from_pem_pkcs1(&string);
125
126        let pubkey = res.unwrap();
127        pubkey.verify(padding(), &hashed, &sig).unwrap();
128    }
129
130    #[test]
131    fn priv_can_complete_cycle_pkcs8() {
132        let mut rng = rand::thread_rng();
133        let rsa = RSAPrivateKey::new(&mut rng, 2048).unwrap();
134        let hashed = Sha256::digest(SIGNING_STRING);
135        let sig = rsa.sign(padding(), &hashed).unwrap();
136
137        let string = rsa.to_pem_pkcs8().unwrap();
138
139        let res = RSAPrivateKey::from_pem_pkcs8(&string);
140
141        let pubkey = res.unwrap().to_public_key();
142        pubkey.verify(padding(), &hashed, &sig).unwrap();
143    }
144
145    #[test]
146    fn pub_can_complete_cycle_pkcs8() {
147        let mut rng = rand::thread_rng();
148        let rsa = RSAPrivateKey::new(&mut rng, 2048).unwrap();
149        let hashed = Sha256::digest(SIGNING_STRING);
150        let sig = rsa.sign(padding(), &hashed).unwrap();
151
152        let rsa = rsa.to_public_key();
153        let string = rsa.to_pem_pkcs8().unwrap();
154
155        let res = RSAPublicKey::from_pem_pkcs8(&string);
156
157        let pubkey = res.unwrap();
158        pubkey.verify(padding(), &hashed, &sig).unwrap();
159    }
160}