Refactoring + more idiomatic enum names

This commit is contained in:
Vincent Prouillet 2019-11-03 13:17:04 +00:00
parent 06bebeaae3
commit caef740ad4
2 changed files with 57 additions and 58 deletions

View File

@ -1,5 +1,6 @@
/// The supported RSA key formats, see the documentation for ring::signature::RsaKeyPair /// The supported RSA key formats, see the documentation for ring::signature::RsaKeyPair
/// for more information /// for more information
#[derive(Debug, PartialEq)]
pub enum Key<'a> { pub enum Key<'a> {
/// An unencrypted PKCS#8-encoded key. Can be used with both ECDSA and RSA /// An unencrypted PKCS#8-encoded key. Can be used with both ECDSA and RSA
/// algorithms when signing. See ring for information. /// algorithms when signing. See ring for information.

View File

@ -9,22 +9,22 @@ use simple_asn1::{BigUint, OID};
/// Supported PEM files for EC and RSA Public and Private Keys /// Supported PEM files for EC and RSA Public and Private Keys
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
enum PemType { enum PemType {
ECPublicKey, EcPublicKey,
ECPrivateKey, EcPrivateKey,
RSAPublicKey, RsaPublicKey,
RSAPrivateKey, RsaPrivateKey,
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
enum PemEncodedWith { enum Standard {
PKCS1, Pkcs1,
PKCS8, Pkcs8,
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
enum Classification { enum Classification {
EC, Ec,
RSA, Rsa,
} }
/// The return type of a successful PEM encoded key with `decode_pem` /// The return type of a successful PEM encoded key with `decode_pem`
@ -46,7 +46,7 @@ pub struct PemEncodedKey {
content: Vec<u8>, content: Vec<u8>,
asn1: Vec<simple_asn1::ASN1Block>, asn1: Vec<simple_asn1::ASN1Block>,
pem_type: PemType, pem_type: PemType,
encoded_with: PemEncodedWith, standard: Standard,
} }
impl PemEncodedKey { impl PemEncodedKey {
@ -65,55 +65,51 @@ impl PemEncodedKey {
"RSA PRIVATE KEY" => Ok(PemEncodedKey { "RSA PRIVATE KEY" => Ok(PemEncodedKey {
content: pem_contents, content: pem_contents,
asn1: asn1_content, asn1: asn1_content,
pem_type: PemType::RSAPrivateKey, pem_type: PemType::RsaPrivateKey,
encoded_with: PemEncodedWith::PKCS1, standard: Standard::Pkcs1,
}), }),
"RSA PUBLIC KEY" => Ok(PemEncodedKey { "RSA PUBLIC KEY" => Ok(PemEncodedKey {
content: pem_contents, content: pem_contents,
asn1: asn1_content, asn1: asn1_content,
pem_type: PemType::RSAPublicKey, pem_type: PemType::RsaPublicKey,
encoded_with: PemEncodedWith::PKCS1, standard: Standard::Pkcs1,
}), }),
// No "EC PRIVATE KEY" // No "EC PRIVATE KEY"
// https://security.stackexchange.com/questions/84327/converting-ecc-private-key-to-pkcs1-format // https://security.stackexchange.com/questions/84327/converting-ecc-private-key-to-pkcs1-format
// "there is no such thing as a "PKCS#1 format" for elliptic curve (EC) keys" // "there is no such thing as a "PKCS#1 format" for elliptic curve (EC) keys"
// This handles PKCS#8 private keys // This handles PKCS#8 public & private keys
"PRIVATE KEY" => match classify_pem(&asn1_content) { tag @ "PRIVATE KEY" | tag @ "PUBLIC KEY" => match classify_pem(&asn1_content) {
Some(Classification::EC) => Ok(PemEncodedKey { Some(c) => {
content: pem_contents, let is_private = tag == "PRIVATE KEY";
asn1: asn1_content, let pem_type = match c {
pem_type: PemType::ECPrivateKey, Classification::Ec => {
encoded_with: PemEncodedWith::PKCS8, if is_private {
}), PemType::EcPrivateKey
Some(Classification::RSA) => Ok(PemEncodedKey { } else {
content: pem_contents, PemType::EcPublicKey
asn1: asn1_content, }
pem_type: PemType::RSAPrivateKey, }
encoded_with: PemEncodedWith::PKCS8, Classification::Rsa => {
}), if is_private {
_ => return Err(ErrorKind::InvalidKeyFormat)?, PemType::RsaPrivateKey
} else {
PemType::RsaPublicKey
}
}
};
Ok(PemEncodedKey {
content: pem_contents,
asn1: asn1_content,
pem_type,
standard: Standard::Pkcs8,
})
}
None => return Err(ErrorKind::InvalidKeyFormat)?,
}, },
// This handles PKCS#8 public keys // Unknown/unsupported type
"PUBLIC KEY" => match classify_pem(&asn1_content) {
Some(Classification::EC) => Ok(PemEncodedKey {
content: pem_contents,
asn1: asn1_content,
pem_type: PemType::ECPublicKey,
encoded_with: PemEncodedWith::PKCS8,
}),
Some(Classification::RSA) => Ok(PemEncodedKey {
content: pem_contents,
asn1: asn1_content,
pem_type: PemType::RSAPublicKey,
encoded_with: PemEncodedWith::PKCS8,
}),
_ => return Err(ErrorKind::InvalidKeyFormat)?,
},
// Unknown type
_ => return Err(ErrorKind::InvalidKeyFormat)?, _ => return Err(ErrorKind::InvalidKeyFormat)?,
} }
} }
@ -126,13 +122,13 @@ impl PemEncodedKey {
/// "PRIVATE KEY", "PUBLIC KEY" /// "PRIVATE KEY", "PUBLIC KEY"
/// PEMs with multiple tagged portions are not supported /// PEMs with multiple tagged portions are not supported
pub fn as_key(&self) -> Result<Key<'_>> { pub fn as_key(&self) -> Result<Key<'_>> {
match self.encoded_with { match self.standard {
PemEncodedWith::PKCS1 => Ok(Key::Der(self.content.as_slice())), Standard::Pkcs1 => Ok(Key::Der(self.content.as_slice())),
PemEncodedWith::PKCS8 => match self.pem_type { Standard::Pkcs8 => match self.pem_type {
PemType::RSAPrivateKey => Ok(Key::Der(extract_first_bitstring(&self.asn1)?)), PemType::RsaPrivateKey => Ok(Key::Der(extract_first_bitstring(&self.asn1)?)),
PemType::RSAPublicKey => Ok(Key::Der(extract_first_bitstring(&self.asn1)?)), PemType::RsaPublicKey => Ok(Key::Der(extract_first_bitstring(&self.asn1)?)),
PemType::ECPrivateKey => Ok(Key::Pkcs8(self.content.as_slice())), PemType::EcPrivateKey => Ok(Key::Pkcs8(self.content.as_slice())),
PemType::ECPublicKey => Ok(Key::Pkcs8(extract_first_bitstring(&self.asn1)?)), PemType::EcPublicKey => Ok(Key::Pkcs8(extract_first_bitstring(&self.asn1)?)),
}, },
} }
} }
@ -160,9 +156,10 @@ fn extract_first_bitstring(asn1: &Vec<simple_asn1::ASN1Block>) -> Result<&[u8]>
_ => (), _ => (),
} }
} }
return Err(ErrorKind::InvalidEcdsaKey)?; Err(ErrorKind::InvalidEcdsaKey)?
} }
/// Find whether this is EC or RSA
fn classify_pem(asn1: &Vec<simple_asn1::ASN1Block>) -> Option<Classification> { fn classify_pem(asn1: &Vec<simple_asn1::ASN1Block>) -> Option<Classification> {
// These should be constant but the macro requires // These should be constant but the macro requires
// #![feature(const_vec_new)] // #![feature(const_vec_new)]
@ -178,9 +175,10 @@ fn classify_pem(asn1: &Vec<simple_asn1::ASN1Block>) -> Option<Classification> {
} }
simple_asn1::ASN1Block::ObjectIdentifier(_, oid) => { simple_asn1::ASN1Block::ObjectIdentifier(_, oid) => {
if oid == ec_public_key_oid { if oid == ec_public_key_oid {
return Some(Classification::EC); return Some(Classification::Ec);
} else if oid == rsa_public_key_oid { }
return Some(Classification::RSA); if oid == rsa_public_key_oid {
return Some(Classification::Rsa);
} }
} }
_ => {} _ => {}