Skip to content

Commit

Permalink
Add TryFrom from &[u8] and Vec<u8> to PrivateKeyDer
Browse files Browse the repository at this point in the history
  • Loading branch information
Alvenix committed Mar 20, 2024
1 parent 034b30e commit 58c67dc
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 0 deletions.
84 changes: 84 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,58 @@ impl<'a> From<PrivatePkcs8KeyDer<'a>> for PrivateKeyDer<'a> {
}
}

impl<'a> TryFrom<&'a [u8]> for PrivateKeyDer<'a> {
type Error = &'static str;

fn try_from(key: &'a [u8]) -> Result<Self, Self::Error> {
if key.len() <= 5 || key[0] != 0x30 {
return Err("invalid key format");
}

// We skip the tag and the length of the sequence
let mut skip_len = 2;

// We skip additonal length bytes
if key[1] >= 0x81 {
skip_len += key[1] - 0x80;
}

match key.get(skip_len as usize..) {
Some([0x02, 0x01, 0x00, // Version = 0
0x30, 0x0D, // Sequence of two elements, which have 13 bytes length
0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, // Object Identifier for RSA Encryption (PKCS #1)
..]) => {
Ok(Self::Pkcs1(key.into()))
}

Some([0x02, 0x01, 0x01, // This is decoded as PKI header with value 1
..]) => {
Ok(Self::Sec1(key.into()))
}

Some([0x02, 0x01, 0x00, // Version = 0
..]) => {
Ok(Self::Pkcs8(key.into()))
}

_ => Err("invalid key format"),
}
}
}

#[cfg(feature = "alloc")]
impl<'a> TryFrom<Vec<u8>> for PrivateKeyDer<'a> {
type Error = &'static str;

fn try_from(key: Vec<u8>) -> Result<Self, Self::Error> {
Ok(match PrivateKeyDer::try_from(&key[..])? {
PrivateKeyDer::Pkcs1(_) => Self::Pkcs1(key.into()),
PrivateKeyDer::Sec1(_) => Self::Sec1(key.into()),
PrivateKeyDer::Pkcs8(_) => Self::Pkcs8(key.into()),
})
}
}

/// A DER-encoded plaintext RSA private key; as specified in PKCS#1/RFC 3447
///
/// RSA private keys are identified in PEM context as `RSA PRIVATE KEY` and when stored in a
Expand Down Expand Up @@ -659,3 +711,35 @@ mod tests {
assert_eq!(format!("{:?}", alg_id), "0x010203");
}
}

#[cfg(test)]
mod non_std_tests {
use super::*;

#[test]
fn test_der_keys_conversion() {
let rsa_1024_key_pkcs1 = include_bytes!("test_keys/rsa_key_pkcs1_1024.der");

let rsa_1024_key_pkcs1 = PrivateKeyDer::try_from(&rsa_1024_key_pkcs1[..]).unwrap();

assert!(matches!(rsa_1024_key_pkcs1, PrivateKeyDer::Pkcs1(_)));

let rsa_2048_key_pkcs1 = include_bytes!("test_keys/rsa_key_pkcs1_2048.der");

let rsa_2048_key_pkcs1 = PrivateKeyDer::try_from(&rsa_2048_key_pkcs1[..]).unwrap();

assert!(matches!(rsa_2048_key_pkcs1, PrivateKeyDer::Pkcs1(_)));

let rsa_4096_key_pkcs1 = include_bytes!("test_keys/rsa_key_pkcs1_4096.der");

let rsa_4096_key_pkcs1 = PrivateKeyDer::try_from(&rsa_4096_key_pkcs1[..]).unwrap();

assert!(matches!(rsa_4096_key_pkcs1, PrivateKeyDer::Pkcs1(_)));

let ec_384_sec1 = include_bytes!("test_keys/ec-384-sec1.der");

let ec_384_sec1 = PrivateKeyDer::try_from(&ec_384_sec1[..]).unwrap();

assert!(matches!(ec_384_sec1, PrivateKeyDer::Sec1(_)));
}
}
Binary file added src/test_keys/ec-384-sec1.der
Binary file not shown.
Binary file added src/test_keys/rsa_key_pkcs1_1024.der
Binary file not shown.
Binary file added src/test_keys/rsa_key_pkcs1_2048.der
Binary file not shown.
Binary file added src/test_keys/rsa_key_pkcs1_4096.der
Binary file not shown.

0 comments on commit 58c67dc

Please sign in to comment.