Skip to content

Commit

Permalink
[rustls] identity: handle elliptic curve private keys
Browse files Browse the repository at this point in the history
This commit improves the user experience of the users leveraging rustls.

When building the identity to use for requests, it's now possible to use
also private keys using Elliptic Curve that are encoded with SEC1
standard.

This is the default encoding used by openssl when EC keys are created.
Prior to this commit users had to convert those keys from the SEC1
encoding to the PKCS 8 one, which is something not trivial.

This feature has been recently added to rustls-pemfile crate.

Signed-off-by: Flavio Castelli <fcastelli@suse.com>
  • Loading branch information
flavio committed Apr 14, 2022
1 parent fe0d968 commit 96704eb
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 28 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Expand Up @@ -118,7 +118,7 @@ rustls = { version = "0.20", features = ["dangerous_configuration"], optional =
tokio-rustls = { version = "0.23", optional = true }
webpki-roots = { version = "0.22", optional = true }
rustls-native-certs = { version = "0.6", optional = true }
rustls-pemfile = { version = "0.3", optional = true }
rustls-pemfile = { version = "1.0", optional = true }

## cookies
cookie_crate = { version = "0.16", package = "cookie", optional = true }
Expand Down
50 changes: 23 additions & 27 deletions src/tls.rs
Expand Up @@ -184,7 +184,7 @@ impl Identity {
/// The input should contain a PEM encoded private key
/// and at least one PEM encoded certificate.
///
/// Note: The private key must be in RSA or PKCS#8 format.
/// Note: The private key must be in RSA, SEC1 Elliptic Curve or PKCS#8 format.
///
/// # Examples
///
Expand All @@ -210,33 +210,29 @@ impl Identity {

let (key, certs) = {
let mut pem = Cursor::new(buf);
let certs = rustls_pemfile::certs(&mut pem)
.map_err(|_| TLSError::General(String::from("No valid certificate was found")))
.map_err(crate::error::builder)?
.into_iter()
.map(rustls::Certificate)
.collect::<Vec<_>>();
pem.set_position(0);
let mut sk = rustls_pemfile::pkcs8_private_keys(&mut pem)
.and_then(|pkcs8_keys| {
if pkcs8_keys.is_empty() {
Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
"No valid private key was found",
))
} else {
Ok(pkcs8_keys)
let mut sk = Vec::<rustls::PrivateKey>::new();
let mut certs = Vec::<rustls::Certificate>::new();

for item in std::iter::from_fn(|| rustls_pemfile::read_one(&mut pem).transpose()) {
match item.map_err(|_| {
crate::error::builder(TLSError::General(String::from(
"Invalid identity PEM file",
)))
})? {
rustls_pemfile::Item::X509Certificate(cert) => {
certs.push(rustls::Certificate(cert))
}
rustls_pemfile::Item::PKCS8Key(key) => sk.push(rustls::PrivateKey(key)),
rustls_pemfile::Item::RSAKey(key) => sk.push(rustls::PrivateKey(key)),
rustls_pemfile::Item::ECKey(key) => sk.push(rustls::PrivateKey(key)),
_ => {
return Err(crate::error::builder(TLSError::General(String::from(
"No valid certificate was found",
))))
}
})
.or_else(|_| {
pem.set_position(0);
rustls_pemfile::rsa_private_keys(&mut pem)
})
.map_err(|_| TLSError::General(String::from("No valid private key was found")))
.map_err(crate::error::builder)?
.into_iter()
.map(rustls::PrivateKey)
.collect::<Vec<_>>();
}
}

if let (Some(sk), false) = (sk.pop(), certs.is_empty()) {
(sk, certs)
} else {
Expand Down

0 comments on commit 96704eb

Please sign in to comment.