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]>) -> Cert {
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 return 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 {
63 tag: "CERTIFICATE".to_owned(),
64 contents: self.0.clone(),
65 })
66 }
67}
68
69#[derive(Debug, PartialEq, Clone)]
71pub struct PrivateKey(Vec<u8>);
72
73impl PrivateKey {
74 fn looks_like_der(bytes: &[u8]) -> bool {
75 bytes.starts_with(b"\x30")
77 }
78
79 pub fn from_der(key_der: impl Into<Vec<u8>>) -> PrivateKey {
81 let key_der = key_der.into();
82 if key_der.is_empty() {
84 panic!("empty private key");
85 }
86 PrivateKey(key_der)
87 }
88
89 pub fn from_pem(key_pem: impl AsRef<[u8]>) -> PrivateKey {
93 let pem = pem::parse_many(key_pem.as_ref());
94 let count = pem.len();
95 let mut keys: Vec<PrivateKey> = pem
96 .into_iter()
97 .flat_map(|p| match p.tag.as_ref() {
98 "PRIVATE KEY" | "RSA PRIVATE KEY" => Some(Self::from_der(p.contents)),
99 _ => None,
100 })
101 .collect();
102 if keys.len() == 1 {
103 return keys.swap_remove(0);
104 } else if keys.len() > 1 {
105 panic!("PEM file contains {} private keys", keys.len());
106 } else if count != 0 {
107 panic!("PEM file contains {} entries, but no private keys", count,);
108 } else if Self::looks_like_der(key_pem.as_ref()) {
109 panic!("PEM file looks like a DER file");
110 } else {
111 panic!("no private keys found in a PEM file",);
112 }
113 }
114
115 pub fn get_der(&self) -> &[u8] {
117 &self.0
118 }
119
120 #[doc(hidden)]
123 pub fn to_pem_incorrect(&self) -> String {
124 pem::encode(&pem::Pem {
125 tag: "RSA PRIVATE KEY".to_owned(),
126 contents: self.0.clone(),
127 })
128 }
129}
130
131pub fn pem_to_cert_key_pair(pem: &[u8]) -> (Cert, PrivateKey) {
133 let entries = pem::parse_many(pem);
134 if entries.len() != 2 {
135 panic!(
136 "PEM file should contain certificate and private key entries, got {} entries",
137 entries.len()
138 );
139 }
140 let cert = Cert::from_pem(pem);
141 let key = PrivateKey::from_pem(pem);
142 (cert, key)
143}
144
145pub struct Pkcs12(pub Vec<u8>);
147
148pub struct Pkcs12AndPassword {
150 pub pkcs12: Pkcs12,
152 pub password: String,
154}