rsa_der/
lib.rs

1#![forbid(unsafe_code, missing_docs, missing_debug_implementations, warnings)]
2#![doc(html_root_url = "https://docs.rs/rsa-der/0.2.0")]
3
4//! A simple crate to encode and decode DER-formatted public RSA keys.
5//!
6//! Public keys are passed to and returned from functions simply using the `n` and  `e`
7//! components, so any RSA library can be used in conjunction with this crate.
8//!
9//! # Examples
10//! Convert an RSA public key to DER bytes:
11//! ```no_run
12//! # use rsa::{RSAPrivateKey, PublicKey};
13//! use rand::rngs::OsRng;
14//! # fn generate_key() -> impl PublicKey {
15//! # let mut rng = OsRng::new().unwrap();
16//! # let key = RSAPrivateKey::new(&mut rng, 2048).unwrap();
17//! # key
18//! # }
19//!
20//! let key = generate_key();
21//! let der_bytes = rsa_der::public_key_to_der(&key.n().to_bytes_be(), &key.e().to_bytes_be());
22//! ```
23
24use simple_asn1::{oid, ASN1Block, BigInt};
25use std::fmt;
26use std::fmt::{Display, Formatter};
27
28/// Encodes an RSA public key to DER bytes, as specified
29/// by the PKCS#8 format.
30///
31/// The `n` and `e` parameters are the big-endian modulus
32/// and exponent of the public key, respectively. Simple
33/// `u8` slices are used to allow usage of this function
34/// in conjunction with any crypto library.
35///
36/// # Examples
37/// Encoding an RSA public key generated using the [`rsa`](https://docs.rs/rsa)
38/// crate:
39/// ```
40/// use rand::rngs::OsRng;
41/// use rsa_der::public_key_to_der;
42/// use rsa::{RSAPrivateKey, PublicKey};
43///
44/// let mut rng = OsRng::new().unwrap();
45/// let key = RSAPrivateKey::new(&mut rng, 2048).unwrap();
46///
47/// let der_bytes = public_key_to_der(&key.n().to_bytes_be(), &key.e().to_bytes_be());
48/// ```
49pub fn public_key_to_der(n: &[u8], e: &[u8]) -> Vec<u8> {
50    let mut root_sequence = vec![];
51
52    // Weird magic number - I have no idea what this is supposed to mean.
53    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/// Error type for `rsa-der`.
75#[derive(Debug, Clone, PartialEq)]
76pub enum Error {
77    /// Indicates that a DER decoding error occurred.
78    InvalidDer(simple_asn1::ASN1DecodeErr),
79    /// Indicates that the RSA bitstring was not found.
80    BitStringNotFound,
81    /// Indicates that the RSA ASN.1 sequence was not found.
82    SequenceNotFound,
83    /// Indicates that the RSA modulus value was not found.
84    ModulusNotFound,
85    /// Indicates that the RSA exponent value was not found.
86    ExponentNotFound,
87    /// Indicates that the RSA ASN.1 sequence did not contain exactly two values (one
88    /// for `n` and one for `e`).
89    InvalidSequenceLength,
90}
91
92type StdResult<T, E> = std::result::Result<T, E>;
93
94/// Result type for `rsa-der`. This type
95/// is equivalent to `std::result::Result<T, rsa_der::Error>`.
96pub 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
124/// Decodes a DER-encoded public key into the raw
125/// `n` and `e` components.
126///
127/// The returned tuple is in the form `(n, e)`, where `n` and `e`
128/// are both big-endian big integers representing the key modulus
129/// and exponent, respectively.
130///
131/// # Examples
132/// Parsing DER bytes into a public RSA key usable with the
133/// [`rsa`](https://docs.rs/rsa/) crate:
134/// ```no_run
135/// # fn main() -> Result<(), rsa_der::Error> {
136/// use rsa::RSAPublicKey;
137/// use num_bigint_dig::BigUint;
138///
139/// # fn get_der_bytes() -> &'static [u8] { &[0] }
140/// let bytes: &[u8] = get_der_bytes();
141///
142/// let (n, e) = rsa_der::public_key_from_der(bytes)?;
143///
144/// let key = RSAPublicKey::new(BigUint::from_bytes_be(&n), BigUint::from_bytes_be(&e));
145/// # Ok(())
146/// # }
147/// ```
148pub 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
186/// Recursively through ASN1 blocks, attempting
187/// to find a BitString value.
188fn 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        // Confirm that converting back works correctly
210        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}