#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Cert(Vec<u8>);
impl Cert {
fn looks_like_der(bytes: &[u8]) -> bool {
bytes.starts_with(b"\x30")
}
pub fn from_der(cert_der: impl Into<Vec<u8>>) -> Cert {
let cert_der = cert_der.into();
if !Self::looks_like_der(&cert_der) {
panic!("not a DER-encoded certificate");
}
Cert(cert_der)
}
pub fn from_pem(cert_der_pem: impl AsRef<[u8]>) -> Result<Cert, pem::PemError> {
let pem = pem::parse_many(cert_der_pem.as_ref())?;
let count = pem.len();
let mut certs: Vec<Cert> = pem
.into_iter()
.flat_map(|p| match p.tag() == "CERTIFICATE" {
true => Some(Self::from_der(p.contents())),
false => None,
})
.collect();
if certs.len() == 1 {
Ok(certs.swap_remove(0))
} else if certs.len() > 1 {
panic!("PEM file contains {} certificates", certs.len());
} else if count != 0 {
panic!(
"PEM file contains {} entries, but no certificates",
certs.len(),
);
} else if Self::looks_like_der(cert_der_pem.as_ref()) {
panic!("PEM file looks like a DER file");
} else {
panic!("no certificates found in a PEM file",);
}
}
pub fn get_der(&self) -> &[u8] {
&self.0
}
pub fn to_pem(&self) -> String {
pem::encode(&pem::Pem::new("CERTIFICATE", self.0.to_vec()))
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct PrivateKey(Vec<u8>);
impl PrivateKey {
fn looks_like_der(bytes: &[u8]) -> bool {
bytes.starts_with(b"\x30")
}
pub fn from_der(key_der: impl Into<Vec<u8>>) -> PrivateKey {
let key_der = key_der.into();
if key_der.is_empty() {
panic!("empty private key");
}
PrivateKey(key_der)
}
pub fn from_pem(key_pem: impl AsRef<[u8]>) -> Result<PrivateKey, pem::PemError> {
let pem = pem::parse_many(key_pem.as_ref())?;
let count = pem.len();
let mut keys: Vec<PrivateKey> = pem
.into_iter()
.flat_map(|p| match p.tag() {
"PRIVATE KEY" | "RSA PRIVATE KEY" => Some(Self::from_der(p.contents())),
_ => None,
})
.collect();
if keys.len() == 1 {
Ok(keys.swap_remove(0))
} else if keys.len() > 1 {
panic!("PEM file contains {} private keys", keys.len());
} else if count != 0 {
panic!("PEM file contains {} entries, but no private keys", count,);
} else if Self::looks_like_der(key_pem.as_ref()) {
panic!("PEM file looks like a DER file");
} else {
panic!("no private keys found in a PEM file",);
}
}
pub fn get_der(&self) -> &[u8] {
&self.0
}
#[doc(hidden)]
pub fn to_pem_incorrect(&self) -> String {
pem::encode(&pem::Pem::new("RSA PRIVATE KEY", self.0.clone()))
}
}
pub fn pem_to_cert_key_pair(pem: &[u8]) -> Result<(Cert, PrivateKey), pem::PemError> {
let entries = pem::parse_many(pem)?;
if entries.len() != 2 {
panic!(
"PEM file should contain certificate and private key entries, got {} entries",
entries.len()
);
}
let cert = Cert::from_pem(pem)?;
let key = PrivateKey::from_pem(pem)?;
Ok((cert, key))
}
pub struct Pkcs12(pub Vec<u8>);
pub struct Pkcs12AndPassword {
pub pkcs12: Pkcs12,
pub password: String,
}