1#![forbid(unsafe_code, missing_docs, missing_debug_implementations, warnings)]
2#![doc(html_root_url = "https://docs.rs/rsa-der/0.2.0")]
3
4use simple_asn1::{oid, ASN1Block, BigInt};
25use std::fmt;
26use std::fmt::{Display, Formatter};
27
28pub fn public_key_to_der(n: &[u8], e: &[u8]) -> Vec<u8> {
50 let mut root_sequence = vec![];
51
52 let oid = oid!(1, 2, 840, 113_549, 1, 1, 1);
54 root_sequence.push(ASN1Block::Sequence(
55 0,
56 vec![ASN1Block::ObjectIdentifier(0, oid), ASN1Block::Null(0)],
57 ));
58
59 let n_block = ASN1Block::Integer(0, BigInt::from_signed_bytes_be(n));
60 let e_block = ASN1Block::Integer(0, BigInt::from_signed_bytes_be(e));
61
62 let rsa_key_bits =
63 simple_asn1::to_der(&ASN1Block::Sequence(0, vec![n_block, e_block])).unwrap();
64
65 root_sequence.push(ASN1Block::BitString(
66 0,
67 rsa_key_bits.len() * 8,
68 rsa_key_bits,
69 ));
70
71 simple_asn1::to_der(&ASN1Block::Sequence(0, root_sequence)).unwrap()
72}
73
74#[derive(Debug, Clone, PartialEq)]
76pub enum Error {
77 InvalidDer(simple_asn1::ASN1DecodeErr),
79 BitStringNotFound,
81 SequenceNotFound,
83 ModulusNotFound,
85 ExponentNotFound,
87 InvalidSequenceLength,
90}
91
92type StdResult<T, E> = std::result::Result<T, E>;
93
94pub type Result<T> = StdResult<T, Error>;
97
98impl Display for Error {
99 fn fmt(&self, f: &mut Formatter) -> StdResult<(), fmt::Error> {
100 match self {
101 Error::InvalidDer(e) => e.fmt(f)?,
102 Error::BitStringNotFound => f.write_str("RSA bit string not found in ASN.1 blocks")?,
103 Error::SequenceNotFound => f.write_str("ASN.1 sequence not found")?,
104 Error::ModulusNotFound => f.write_str("ASN.1 public key modulus not found")?,
105 Error::ExponentNotFound => f.write_str("ASN.1 public key exponent not found")?,
106 Error::InvalidSequenceLength => {
107 f.write_str("ASN.1 sequence did not contain exactly two values")?
108 }
109 }
110
111 Ok(())
112 }
113}
114
115impl std::error::Error for Error {
116 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
117 match self {
118 Error::InvalidDer(e) => Some(e),
119 _ => None,
120 }
121 }
122}
123
124pub fn public_key_from_der(der: &[u8]) -> Result<(Vec<u8>, Vec<u8>)> {
149 let blocks = simple_asn1::from_der(der).map_err(Error::InvalidDer)?;
150
151 let mut bit_strings = Vec::with_capacity(1);
152 find_bit_string(&blocks, &mut bit_strings);
153
154 if bit_strings.is_empty() {
155 return Err(Error::BitStringNotFound);
156 }
157
158 let bit_string = &bit_strings[0];
159
160 let inner_asn = simple_asn1::from_der(bit_string).map_err(Error::InvalidDer)?;
161
162 let (n, e) = match &inner_asn[0] {
163 ASN1Block::Sequence(_, blocks) => {
164 if blocks.len() != 2 {
165 return Err(Error::InvalidSequenceLength);
166 }
167
168 let n = match &blocks[0] {
169 ASN1Block::Integer(_, n) => n,
170 _ => return Err(Error::ModulusNotFound),
171 };
172
173 let e = match &blocks[1] {
174 ASN1Block::Integer(_, e) => e,
175 _ => return Err(Error::ExponentNotFound),
176 };
177
178 (n, e)
179 }
180 _ => return Err(Error::SequenceNotFound),
181 };
182
183 Ok((n.to_bytes_be().1, e.to_bytes_be().1))
184}
185
186fn find_bit_string(blocks: &[ASN1Block], mut result: &mut Vec<Vec<u8>>) {
189 for block in blocks.iter() {
190 match block {
191 ASN1Block::BitString(_, _, bytes) => result.push(bytes.to_vec()),
192 ASN1Block::Sequence(_, blocks) => find_bit_string(&blocks[..], &mut result),
193 _ => (),
194 }
195 }
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201 use openssl::rsa::Rsa;
202
203 #[test]
204 fn test_public_key_to_der() {
205 let key = Rsa::generate(2048).unwrap();
206
207 let bytes = public_key_to_der(&key.n().to_vec(), &key.e().to_vec());
208
209 let new_key = Rsa::public_key_from_der(&bytes).unwrap();
211
212 assert_eq!(key.n(), new_key.n());
213 assert_eq!(key.e(), new_key.e());
214 }
215
216 #[test]
217 fn test_public_key_from_der() {
218 let key = Rsa::generate(2048).unwrap();
219
220 let der = key.public_key_to_der().unwrap();
221
222 let (n, e) = public_key_from_der(&der).unwrap();
223
224 assert_eq!(key.n().to_vec(), n);
225 assert_eq!(key.e().to_vec(), e);
226 }
227}