1use 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
25pub trait KeyExt {
27 fn to_pem_pkcs8(&self) -> Result<String, KeyError>;
29
30 fn from_pem_pkcs8(pem: &str) -> Result<Self, KeyError>
32 where
33 Self: Sized;
34
35 fn to_pem_pkcs1(&self) -> Result<String, KeyError>;
37
38 fn from_pem_pkcs1(pem: &str) -> Result<Self, KeyError>
40 where
41 Self: Sized;
42}
43
44#[derive(Debug, Error)]
46pub enum KeyError {
47 #[error("Invalid key kind supplied")]
49 Kind,
50
51 #[error("Key not PEM-formatted")]
53 Pem,
54
55 #[error("Error parsing key, {}", .0)]
57 Parse(rsa::errors::Error),
58
59 #[error("Constructed key is invalid")]
61 Validate,
62
63 #[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}