1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#[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]>) -> Cert {
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 {
return 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 {
tag: "CERTIFICATE".to_owned(),
contents: self.0.clone(),
})
}
}
#[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]>) -> PrivateKey {
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.as_ref() {
"PRIVATE KEY" | "RSA PRIVATE KEY" => Some(Self::from_der(p.contents)),
_ => None,
})
.collect();
if keys.len() == 1 {
return 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 {
tag: "RSA PRIVATE KEY".to_owned(),
contents: self.0.clone(),
})
}
}
pub fn pem_to_cert_key_pair(pem: &[u8]) -> (Cert, PrivateKey) {
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);
(cert, key)
}
pub struct Pkcs12(pub Vec<u8>);
pub struct Pkcs12AndPassword {
pub pkcs12: Pkcs12,
pub password: String,
}