use crate::error::NidError;
use der_parser::oid::Oid;
use lazy_static::lazy_static;
use std::collections::HashMap;
#[derive(Debug, PartialEq, Clone, Copy)]
#[repr(u8)]
pub enum Nid {
Undef,
Algorithm,
RsaDsi,
Pkcs,
Md2,
Md5,
Rc4,
RsaEncryption,
RsaMd2,
RsaMd5,
PbdMd2Des,
PbeMd5Des,
X500,
X509,
CommonName,
CountryName,
LocalityName,
StateOrProvinceName,
OrganizationName,
OrganizationalUnitName,
Rsa,
Pkcs7,
Pkcs7Data,
Pkcs7SignedData,
Pkcs7EnvelopedData,
Pkcs7SignedAndEnvelopedData,
Pkcs7DigestData,
Pkcs7EncryptedData,
Pkcs3,
DhKeyAgreement,
DesEcb,
DesCfb,
DesCbc,
DesEde,
DesEde3,
IdeaCbc,
IdeaCfb,
IdeaEcb,
Rc2Cbc,
Rc2Ecb,
Rc2Cfb,
Rc2Ofb,
Sha,
Sha1WithRsaEncryption,
DesEdeCbc,
DesEde3Cbc,
DesOfb,
IdeaOfb,
Pkcs9,
EmailAddress,
UnstructuredName,
ContentType,
MessageDigest,
SigningTime,
Countersignature,
ChallengePassword,
UnstructuredAddress,
ExtendedCertificateAttributes,
RsaSha1,
SubjectKeyIdentifier,
KeyUsage,
PrivateKeyUsagePeriod,
SubjectAltName,
BasicConstraints,
CertificatePolicies,
AuthorityKeyIdentifier,
}
macro_rules! rsadsi {
( ) => { &[ 1, 2, 840, 113549 ] };
( $( $x:expr ),* ) => { &[ 1, 2, 840, 113549, $( $x ),* ] }
}
macro_rules! pkcs1 {
( ) => { rsadsi!( 1, 1 ) };
( $( $x:expr ),* ) => { rsadsi!( 1, 1, $( $x ),* ) }
}
macro_rules! pkcs9 {
( ) => { rsadsi!( 1, 9 ) };
( $( $x:expr ),* ) => { rsadsi!( 1, 9, $( $x ),* ) }
}
macro_rules! algo {
( $( $x:expr ),* ) => { &[ 1, 3, 14, 3, 2, $( $x ),* ] }
}
macro_rules! x509 {
( $( $x:expr ),* ) => { &[ 2, 5, 4, $( $x ),* ] }
}
macro_rules! idce {
( $( $x:expr ),* ) => { &[ 2, 5, 29, $( $x ),* ] }
}
const OBJ_ALGO: &[u64] = algo!();
const OBJ_RSADSI: &[u64] = rsadsi!();
const OBJ_X500: &[u64] = &[2, 5];
const OBJ_X509: &[u64] = x509!();
const OBJ_CN: &[u64] = x509!(3);
const OBJ_C: &[u64] = x509!(6);
const OBJ_L: &[u64] = x509!(7);
const OBJ_ST: &[u64] = x509!(8);
const OBJ_O: &[u64] = x509!(10);
const OBJ_OU: &[u64] = x509!(11);
const OBJ_PKCS9: &[u64] = pkcs9!();
const OBJ_EMAIL: &[u64] = pkcs9!(1);
const OBJ_RSAENC: &[u64] = pkcs1!(1);
const OBJ_RSASHA1: &[u64] = pkcs1!(5);
const OBJ_SKI: &[u64] = idce!(14);
const OBJ_KU: &[u64] = idce!(15);
const OBJ_PKUP: &[u64] = idce!(16);
const OBJ_SAN: &[u64] = idce!(17);
const OBJ_BC: &[u64] = idce!(19);
const OBJ_CPOL: &[u64] = idce!(32);
const OBJ_AKI: &[u64] = idce!(35);
struct OidEntry {
sn: &'static str,
ln: &'static str,
nid: Nid,
}
lazy_static! {
static ref OID_REGISTRY: HashMap<Oid<'static>, OidEntry> = {
let mut m = HashMap::new();
m.insert(Oid::from(&[0]).unwrap(), OidEntry{sn:"UNDEF", ln:"undefined", nid:Nid::Undef});
m.insert(Oid::from(OBJ_ALGO).unwrap(), OidEntry{sn:"Algorithm", ln:"algorithm", nid:Nid::Algorithm});
m.insert(Oid::from(OBJ_RSADSI).unwrap(), OidEntry{sn:"rsadsi", ln:"rsadsi", nid:Nid::RsaDsi});
m.insert(Oid::from(OBJ_X500).unwrap(), OidEntry{sn:"X500", ln:"X500", nid:Nid::X500});
m.insert(Oid::from(OBJ_X509).unwrap(), OidEntry{sn:"X509", ln:"X509", nid:Nid::X509});
m.insert(Oid::from(OBJ_CN).unwrap(), OidEntry{sn:"CN", ln:"commonName", nid:Nid::CommonName});
m.insert(Oid::from(OBJ_C).unwrap(), OidEntry{sn:"C", ln:"countryName", nid:Nid::CountryName});
m.insert(Oid::from(OBJ_L).unwrap(), OidEntry{sn:"L", ln:"localityName", nid:Nid::LocalityName});
m.insert(Oid::from(OBJ_ST).unwrap(), OidEntry{sn:"ST", ln:"stateOrProvinceName", nid:Nid::StateOrProvinceName});
m.insert(Oid::from(OBJ_O).unwrap(), OidEntry{sn:"O", ln:"organizationName", nid:Nid::OrganizationName});
m.insert(Oid::from(OBJ_OU).unwrap(), OidEntry{sn:"OU", ln:"organizationalUnitName", nid:Nid::OrganizationalUnitName});
m.insert(Oid::from(OBJ_PKCS9).unwrap(), OidEntry{sn:"pkcs9", ln:"pkcs9", nid:Nid::Pkcs9});
m.insert(Oid::from(OBJ_EMAIL).unwrap(), OidEntry{sn:"Email", ln:"emailAddress", nid:Nid::EmailAddress});
m.insert(Oid::from(OBJ_RSAENC).unwrap(), OidEntry{sn:"RSA-ENC", ln:"rsaEncryption", nid:Nid::RsaEncryption});
m.insert(Oid::from(OBJ_RSASHA1).unwrap(), OidEntry{sn:"RSA-SHA1", ln:"sha1WithRSAEncryption", nid:Nid::RsaSha1});
m.insert(Oid::from(OBJ_SKI).unwrap(), OidEntry{sn:"subjectKeyIdentifier", ln:"X509v3 Subject Key Identifier", nid:Nid::SubjectKeyIdentifier});
m.insert(Oid::from(OBJ_KU).unwrap(), OidEntry{sn:"subjectKeyIdentifier", ln:"X509v3 Subject Key Identifier", nid:Nid::SubjectKeyIdentifier});
m.insert(Oid::from(OBJ_PKUP).unwrap(), OidEntry{sn:"privateKeyUsagePeriod", ln:"X509v3 Private Key Usage Period", nid:Nid::PrivateKeyUsagePeriod});
m.insert(Oid::from(OBJ_SAN).unwrap(), OidEntry{sn:"subjectAltName", ln:"X509v3 Subject Alternative Name", nid:Nid::SubjectAltName});
m.insert(Oid::from(OBJ_BC).unwrap(), OidEntry{sn:"basicConstraints", ln:"X509v3 Basic Constraints", nid:Nid::BasicConstraints});
m.insert(Oid::from(OBJ_CPOL).unwrap(), OidEntry{sn:"certificatePolicies", ln:"X509v3 Certificate Policies", nid:Nid::CertificatePolicies});
m.insert(Oid::from(OBJ_AKI).unwrap(), OidEntry{sn:"authorityKeyIdentifier", ln:"X509v3 Authority Key Identifier", nid:Nid::AuthorityKeyIdentifier});
m
};
}
pub fn nid2sn(nid: Nid) -> Result<&'static str, NidError> {
OID_REGISTRY
.values()
.find(|o| o.nid == nid)
.map(|o| o.sn)
.ok_or(NidError)
}
pub fn nid2ln(nid: Nid) -> Result<&'static str, NidError> {
OID_REGISTRY
.values()
.find(|o| o.nid == nid)
.map(|o| o.ln)
.ok_or(NidError)
}
pub fn nid2obj(nid: Nid) -> Result<&'static Oid<'static>, NidError> {
OID_REGISTRY
.iter()
.find(|(_, o)| o.nid == nid)
.map(|(oid, _)| oid)
.ok_or(NidError)
}
pub fn oid2nid(oid: &Oid) -> Result<Nid, NidError> {
OID_REGISTRY.get(oid).map(|ref o| o.nid).ok_or(NidError)
}
pub fn oid2sn(oid: &Oid) -> Result<&'static str, NidError> {
OID_REGISTRY.get(oid).map(|ref o| o.sn).ok_or(NidError)
}
pub fn sn2oid(sn: &str) -> Result<&Oid, NidError> {
OID_REGISTRY
.iter()
.find(|(_, o)| *o.sn == *sn)
.map(|(oid, _)| oid)
.ok_or(NidError)
}
#[cfg(test)]
mod tests {
use super::*;
use der_parser::oid::Oid;
#[test]
fn test_obj2nid() {
let oid = Oid::from(&[1, 2, 840, 113_549, 1, 1, 5]).unwrap();
assert_eq!(oid2nid(&oid), Ok(Nid::RsaSha1));
let invalid_oid = Oid::from(&[5, 4, 3, 2, 1]).unwrap();
assert_eq!(oid2nid(&invalid_oid), Err(NidError));
}
#[test]
fn test_nid2sn() {
assert_eq!(nid2sn(Nid::Undef), Ok("UNDEF"));
assert_eq!(nid2sn(Nid::RsaSha1), Ok("RSA-SHA1"));
}
#[test]
fn test_sn2oid() {
let oid = Oid::from(&[1, 2, 840, 113_549, 1, 1, 5]).unwrap();
assert_eq!(sn2oid("RSA-SHA1"), Ok(&oid));
assert_eq!(sn2oid("invalid sn"), Err(NidError));
}
}