1#[derive(Debug, Eq, PartialEq, Clone)]
3pub struct Cert(Vec<u8>);
4
5impl Cert {
6 fn looks_like_der(bytes: &[u8]) -> bool {
7 bytes.starts_with(b"\x30")
17 }
18
19 pub fn from_der(cert_der: impl Into<Vec<u8>>) -> Cert {
21 let cert_der = cert_der.into();
22 if !Self::looks_like_der(&cert_der) {
23 panic!("not a DER-encoded certificate");
24 }
25 Cert(cert_der)
26 }
27
28 pub fn from_pem(cert_der_pem: impl AsRef<[u8]>) -> Result<Cert, pem::PemError> {
30 let pem = pem::parse_many(cert_der_pem.as_ref())?;
31 let count = pem.len();
32 let mut certs: Vec<Cert> = pem
33 .into_iter()
34 .flat_map(|p| match p.tag() == "CERTIFICATE" {
35 true => Some(Self::from_der(p.contents())),
36 false => None,
37 })
38 .collect();
39 if certs.len() == 1 {
40 Ok(certs.swap_remove(0))
41 } else if certs.len() > 1 {
42 panic!("PEM file contains {} certificates", certs.len());
43 } else if count != 0 {
44 panic!(
45 "PEM file contains {} entries, but no certificates",
46 certs.len(),
47 );
48 } else if Self::looks_like_der(cert_der_pem.as_ref()) {
49 panic!("PEM file looks like a DER file");
50 } else {
51 panic!("no certificates found in a PEM file",);
52 }
53 }
54
55 pub fn get_der(&self) -> &[u8] {
57 &self.0
58 }
59
60 pub fn to_pem(&self) -> String {
62 pem::encode(&pem::Pem::new("CERTIFICATE", self.0.to_vec()))
63 }
64}
65
66#[derive(Debug, PartialEq, Clone)]
68pub struct PrivateKey(Vec<u8>);
69
70impl PrivateKey {
71 fn looks_like_der(bytes: &[u8]) -> bool {
72 bytes.starts_with(b"\x30")
74 }
75
76 pub fn from_der(key_der: impl Into<Vec<u8>>) -> PrivateKey {
78 let key_der = key_der.into();
79 if key_der.is_empty() {
81 panic!("empty private key");
82 }
83 PrivateKey(key_der)
84 }
85
86 pub fn from_pem(key_pem: impl AsRef<[u8]>) -> Result<PrivateKey, pem::PemError> {
90 let pem = pem::parse_many(key_pem.as_ref())?;
91 let count = pem.len();
92 let mut keys: Vec<PrivateKey> = pem
93 .into_iter()
94 .flat_map(|p| match p.tag() {
95 "PRIVATE KEY" | "RSA PRIVATE KEY" => Some(Self::from_der(p.contents())),
96 _ => None,
97 })
98 .collect();
99 if keys.len() == 1 {
100 Ok(keys.swap_remove(0))
101 } else if keys.len() > 1 {
102 panic!("PEM file contains {} private keys", keys.len());
103 } else if count != 0 {
104 panic!("PEM file contains {} entries, but no private keys", count,);
105 } else if Self::looks_like_der(key_pem.as_ref()) {
106 panic!("PEM file looks like a DER file");
107 } else {
108 panic!("no private keys found in a PEM file",);
109 }
110 }
111
112 pub fn get_der(&self) -> &[u8] {
114 &self.0
115 }
116
117 #[doc(hidden)]
120 pub fn to_pem_incorrect(&self) -> String {
121 pem::encode(&pem::Pem::new("RSA PRIVATE KEY", self.0.clone()))
122 }
123}
124
125pub fn pem_to_cert_key_pair(pem: &[u8]) -> Result<(Cert, PrivateKey), pem::PemError> {
127 let entries = pem::parse_many(pem)?;
128 if entries.len() != 2 {
129 panic!(
130 "PEM file should contain certificate and private key entries, got {} entries",
131 entries.len()
132 );
133 }
134 let cert = Cert::from_pem(pem)?;
135 let key = PrivateKey::from_pem(pem)?;
136 Ok((cert, key))
137}
138
139pub struct Pkcs12(pub Vec<u8>);
141
142pub struct Pkcs12AndPassword {
144 pub pkcs12: Pkcs12,
146 pub password: String,
148}