feat: ecc private key for tls feature (#208)
it adds support for ECC private keys when enabling the --tls feature.
this is particularly useful when generating private keys for
example using clients like Lego ACME which defaults to EC256 keys.
it resolves #207
Diff
src/tls.rs | 70 +++++++++++++++++++++++++++--------------
tests/tls/local.dev_cert.ecc.pem | 12 +++++++-
tests/tls/local.dev_key.ecc.pem | 5 +++-
3 files changed, 64 insertions(+), 23 deletions(-)
@@ -185,32 +185,35 @@ impl TlsConfigBuilder {
.map(Certificate)
.collect();
let key = {
let mut key_vec = Vec::new();
self.key
.read_to_end(&mut key_vec)
.map_err(TlsConfigError::Io)?;
if key_vec.is_empty() {
return Err(TlsConfigError::EmptyKey);
}
let mut pkcs8 = rustls_pemfile::pkcs8_private_keys(&mut key_vec.as_slice())
.map_err(|_e| TlsConfigError::Pkcs8ParseError)?;
if !pkcs8.is_empty() {
PrivateKey(pkcs8.remove(0))
} else {
let mut rsa = rustls_pemfile::rsa_private_keys(&mut key_vec.as_slice())
.map_err(|_e| TlsConfigError::RsaParseError)?;
let mut key_vec = Vec::new();
self.key
.read_to_end(&mut key_vec)
.map_err(TlsConfigError::Io)?;
if key_vec.is_empty() {
return Err(TlsConfigError::EmptyKey);
}
if !rsa.is_empty() {
PrivateKey(rsa.remove(0))
} else {
return Err(TlsConfigError::EmptyKey);
let mut key = None;
let mut reader = std::io::Cursor::new(key_vec);
for item in
rustls_pemfile::read_all(&mut reader).map_err(|_e| TlsConfigError::Pkcs8ParseError)?
{
match item {
rustls_pemfile::Item::RSAKey(k) => key = Some(PrivateKey(k)),
rustls_pemfile::Item::PKCS8Key(k) => key = Some(PrivateKey(k)),
rustls_pemfile::Item::ECKey(k) => key = Some(PrivateKey(k)),
_ => {
return Err(TlsConfigError::InvalidKey(
TlsError::InvalidCertificateData("unknown private key format".to_owned()),
))
}
}
}
let key = match key {
Some(k) => k,
_ => return Err(TlsConfigError::EmptyKey),
};
fn read_trust_anchor(
@@ -426,4 +429,25 @@ mod tests {
.build()
.unwrap();
}
#[test]
fn file_cert_key_ecc() {
TlsConfigBuilder::new()
.cert_path("tests/tls/local.dev_cert.ecc.pem")
.key_path("tests/tls/local.dev_key.ecc.pem")
.build()
.unwrap();
}
#[test]
fn bytes_cert_key_ecc() {
let cert = include_str!("../tests/tls/local.dev_cert.ecc.pem");
let key = include_str!("../tests/tls/local.dev_key.ecc.pem");
TlsConfigBuilder::new()
.key(key.as_bytes())
.cert(cert.as_bytes())
.build()
.unwrap();
}
}
@@ -0,0 +1,12 @@
-----BEGIN CERTIFICATE-----
MIIBtDCCAVoCCQDFz95/8CeJaDAKBggqhkjOPQQDAjBiMQswCQYDVQQGEwJERTEQ
MA4GA1UECAwHR2VybWFueTEQMA4GA1UEBwwHTGVpcHppZzESMBAGA1UEAwwJbG9j
YWwuZGV2MRswGQYJKoZIhvcNAQkBFgxoaUBsb2NhbC5kZXYwHhcNMjMwNTI4MTk0
NzA4WhcNMjYwNTI3MTk0NzA4WjBiMQswCQYDVQQGEwJERTEQMA4GA1UECAwHR2Vy
bWFueTEQMA4GA1UEBwwHTGVpcHppZzESMBAGA1UEAwwJbG9jYWwuZGV2MRswGQYJ
KoZIhvcNAQkBFgxoaUBsb2NhbC5kZXYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
AATZR4F60X+iHjeD6kySZfXljNckDb22QYQ76Ts4GFYWkdDstU6yehxyER+MZWsm
UnTE/Gy3mnpSmMzoSBfoKRmHMAoGCCqGSM49BAMCA0gAMEUCIQChOTwbAYlx6zg0
yc3Oc+zrNY8Yd8oRUD+cG/wdz+gN/wIgP199zXAPXiYUFFd1CnIYmWJSglaOUbYj
ZP/ixZR9HQs=
-----END CERTIFICATE-----
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIPwp3LAnLEyWe2lLz66Y3QCCJ/BEMJheTM0shZnnSw6toAoGCCqGSM49
AwEHoUQDQgAE2UeBetF/oh43g+pMkmX15YzXJA29tkGEO+k7OBhWFpHQ7LVOsnoc
chEfjGVrJlJ0xPxst5p6UpjM6EgX6CkZhw==
-----END EC PRIVATE KEY-----