Support more TLS key types in PKCS format.

Closes #1449.
Resolves #1461.
This commit is contained in:
Abdullah Alyan 2021-03-08 12:39:36 +03:00 committed by Sergio Benitez
parent f254504dc9
commit af48d1f2e6
13 changed files with 227 additions and 29 deletions

View File

@ -41,7 +41,7 @@ fn load_private_key(reader: &mut dyn io::BufRead) -> io::Result<PrivateKey> {
})?;
// Ensure we can use the key.
rustls::sign::RSASigningKey::new(&key)
rustls::sign::any_supported_type(&key)
.map_err(|_| Error::new(Other, "key parsed but is unusable"))
.map(|_| key)
}
@ -126,3 +126,46 @@ impl Connection for TlsStream<TcpStream> {
self.get_ref().0.remote_addr()
}
}
#[cfg(test)]
mod test {
use super::*;
use std::io::Cursor;
macro_rules! tls_example_key {
($k:expr) => {
include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../examples/tls/private/", $k))
}
}
#[test]
fn verify_load_private_keys_of_different_types() -> io::Result<()> {
let rsa_sha256_key = tls_example_key!("rsa_sha256_key.pem");
let ecdsa_nistp256_sha256_key = tls_example_key!("ecdsa_nistp256_sha256_key_pkcs8.pem");
let ecdsa_nistp384_sha384_key = tls_example_key!("ecdsa_nistp384_sha384_key_pkcs8.pem");
let ed2551_key = tls_example_key!("ed25519_key.pem");
load_private_key(&mut Cursor::new(rsa_sha256_key))?;
load_private_key(&mut Cursor::new(ecdsa_nistp256_sha256_key))?;
load_private_key(&mut Cursor::new(ecdsa_nistp384_sha384_key))?;
load_private_key(&mut Cursor::new(ed2551_key))?;
Ok(())
}
#[test]
fn verify_load_certs_of_different_types() -> io::Result<()> {
let rsa_sha256_cert = tls_example_key!("rsa_sha256_cert.pem");
let ecdsa_nistp256_sha256_cert = tls_example_key!("ecdsa_nistp256_sha256_cert.pem");
let ecdsa_nistp384_sha384_cert = tls_example_key!("ecdsa_nistp384_sha384_cert.pem");
let ed2551_cert = tls_example_key!("ed25519_cert.pem");
load_certs(&mut Cursor::new(rsa_sha256_cert))?;
load_certs(&mut Cursor::new(ecdsa_nistp256_sha256_cert))?;
load_certs(&mut Cursor::new(ecdsa_nistp384_sha384_cert))?;
load_certs(&mut Cursor::new(ed2551_cert))?;
Ok(())
}
}

View File

@ -1,9 +1,24 @@
# The certificate/private key pair used here was generated via openssl using the
# `gen_cert.sh` script located in the `private/` subdirectory.
# The certificate/private key pairs used here was generated via openssl using the
# scripts 'gen_ca.sh' and 'gen_certs.sh' located in the `private/` subdirectory.
#
# The certificate is self-signed. As such, you will need to trust it directly
# The certificates are self-signed. As such, you will need to trust them directly
# for your browser to refer to the connection as secure. You should NEVER use
# this certificate/key pair. It is here for DEMONSTRATION PURPOSES ONLY.
[global.tls]
certs = "private/cert.pem"
key = "private/key.pem"
# these certificate/key pairs. They are here for DEMONSTRATION PURPOSES ONLY.
[default.tls]
certs = "private/rsa_sha256_cert.pem"
key = "private/rsa_sha256_key.pem"
[rsa_sha256.tls]
certs = "private/rsa_sha256_cert.pem"
key = "private/rsa_sha256_key.pem"
[ecdsa_nistp256_sha256.tls]
certs = "private/ecdsa_nistp256_sha256_cert.pem"
key = "private/ecdsa_nistp256_sha256_key_pkcs8.pem"
[ecdsa_nistp384_sha384.tls]
certs = "private/ecdsa_nistp384_sha384_cert.pem"
key = "private/ecdsa_nistp384_sha384_key_pkcs8.pem"
[ed25519.tls]
certs = "private/ed25519_cert.pem"
key = "private/ed25519_key.pem"

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDVjCCAT6gAwIBAgIJAI9jdPcCsa4EMA0GCSqGSIb3DQEBCwUAMEcxCzAJBgNV
BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEChMJUm9ja2V0IENBMRcwFQYDVQQD
Ew5Sb2NrZXQgUm9vdCBDQTAeFw0yMTAzMTAxNjAwMjNaFw0zMTAzMDgxNjAwMjNa
MD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEPMA0GA1UECgwGUm9ja2V0MRIw
EAYDVQQDDAlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQzqFmE
N1a7P/mKHJHGgKOpLTFf3KFuhzC5aUsz3vXSgclet6DxTwGeew5MRxBE9Wom8gS4
UHlZL5eVaUyQeKoroxgwFjAUBgNVHREEDTALgglsb2NhbGhvc3QwDQYJKoZIhvcN
AQELBQADggIBAESn9PwlB0mws6CY+w507HqeSAbHXaT+m5YtinHDx4II3V5Q61YD
ew37FAaeey+2IJ6f73K0NqRXIMQL5cFD1eK9b32fDoMO/XtJA9eFue3MSgDuqZaY
sLNtg/MWSvWFYXHzc3bFynX9tr4+1VwYs7oC3dwHAl0rbhyOKKdsZeBzfluIvzjg
BHR5I1P16RQubG7BDFBQTQQ21+oN3Zp0EXjTvqy5g1qfIEvPozqT4hlTHVvY/fcv
kStjUNbhMmZ3WxLbVkiICp1SMXP4UjNDvzUgr4W5F/MuqKAWabuAg9veMu9l1kMf
RjQLyl2srtFKG6tInNmLHQrCx6nW+LPYxVH/JmiBbkfYURowaNPRiWCAi7b8pZ+s
WBAGHwSMYvpVIDWSBSYWcBQvomb+kdp2mF1+PilgDliLttfCO+OByMUSBjdZLXUI
nxBxWVgh9jUxyLM47eaNiH0Y5t79b6e+wlPwgMIz6naEs82cdJKBzfLJJ7lvAKOH
9aAobrDzlJD3N1YffdRlIaOxyUqobgyqBszDiZkq4+mXg4+OhOcqP/qck2A56bu+
e8E+4o17FHQMOoHcJ11tBW3nl6DyPU4jzT2VOJvq0Yu/9flai5lo0HZ3uIP4x0ZJ
iNml6X97ARlipNpjerbkuzRNHdxVhSh4LllPlXV4w4iGxjeONVkj69OB
-----END CERTIFICATE-----

View File

@ -0,0 +1,5 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgyomM+167aYfudwIs
7T9VyM7FGJr2cYfpKOOOaeBIzyuhRANCAAQzqFmEN1a7P/mKHJHGgKOpLTFf3KFu
hzC5aUsz3vXSgclet6DxTwGeew5MRxBE9Wom8gS4UHlZL5eVaUyQeKor
-----END PRIVATE KEY-----

View File

@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDczCCAVugAwIBAgIJAOIfNU0ricf5MA0GCSqGSIb3DQEBDAUAMEcxCzAJBgNV
BAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UEChMJUm9ja2V0IENBMRcwFQYDVQQD
Ew5Sb2NrZXQgUm9vdCBDQTAeFw0yMTAzMTAxNjA4MThaFw0zMTAzMDgxNjA4MTha
MD8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEPMA0GA1UECgwGUm9ja2V0MRIw
EAYDVQQDDAlsb2NhbGhvc3QwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAR69JeIdYW8
x2qkkOAWZSOQYy2Y1S3biBmalAmJdaH+76mfmkMKTlcGyT5Pxns85sp9sZbBiBxm
Odnh3uMZbqh5ej4zNfIP27NjsnmrQzm1HQqgmgU16e3FZ1Sn4Mbi6kCjGDAWMBQG
A1UdEQQNMAuCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQwFAAOCAgEAg/XC/unGAtLZ
1OOKQcBrCRcHWyw9MpnXL7MnmM1yRWsoSbrYzueU1rpEh/i9wa/hkyVhtdYJ5USf
UFjqUW8OV+sElLMdm8VWxT61DxYxUdZIZB3BtWhI/tQXDhIwv9L2UbFMZHoYiTUA
bgPflpNtZtsPabX0PsusUber/GhkSCnwGADmbnPtre2m9ODvSxYfLVcbDn5kF9rE
/c2lnJMROYlNaAb9+P9hH+k8X++MT0xfbB26y/c3dJsp0JKGajT6ki9NlfitnWvy
csmgIo4QdVOTsbUIrfZX6khOCk18fiqYfHRjg6MnbTiRTncC9iuYYdsRH7Q6/q36
wUMyh7XOto3R+ejERDTpS0V34SBL9Q+998LNQMAKpU/gUyU9whD/zhTn2GD2uYe8
8hlYjUy9nSU8qzybPEQUQotgd7AcvMat12ZcQqoUdB/2Rwqw/KQvqtwkcDz1N4Dt
+oJ3jCH6DnC4Ov1Qeyu/PWnc92DRxTmynOv11P/quDoQGrXPKZ+PxEEHktC1yyGi
nff8EPTRzRqLYe+sFPS12MvrWhg7CoMLKxXhqezAH0gmf++bRrOrnkGkmMDbyFFh
YraGkqZaG6X6dK7JyLIXndXv3rx7EfVdEmicIwQ04l7XsirxvYs1ei/wlSzn63k4
uNj+AnJ0PNOmktTAHzfgHLv+fVgIlcM=
-----END CERTIFICATE-----

View File

@ -0,0 +1,6 @@
-----BEGIN PRIVATE KEY-----
MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDDUm43VOrG74fBAQT7y
CqoKnDbOotrUHGbm/NR5KE3axbiccbQx349ZmvDUqOaZZNChZANiAAR69JeIdYW8
x2qkkOAWZSOQYy2Y1S3biBmalAmJdaH+76mfmkMKTlcGyT5Pxns85sp9sZbBiBxm
Odnh3uMZbqh5ej4zNfIP27NjsnmrQzm1HQqgmgU16e3FZ1Sn4Mbi6kA=
-----END PRIVATE KEY-----

View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDMjCCARqgAwIBAgIUNAiGpJKcWHB80qLj99td7IXO6QcwDQYJKoZIhvcNAQEL
BQAwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQKEwlSb2NrZXQg
Q0ExFzAVBgNVBAMTDlJvY2tldCBSb290IENBMB4XDTIxMDMxMDE5NDg1MVoXDTMx
MDMwODE5NDg1MVowPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ8wDQYDVQQK
DAZSb2NrZXQxEjAQBgNVBAMMCWxvY2FsaG9zdDAqMAUGAytlcAMhAAnWZ6qQExvf
pIrjevFoIX8Yo+VCqPq69fhF93GNNU7PoxgwFjAUBgNVHREEDTALgglsb2NhbGhv
c3QwDQYJKoZIhvcNAQELBQADggIBAJQz+xaTgQ9J8tKLMIGWgK7b8W9YbaXFfKvi
zGUrrP9YKTOVuYF38u99B+mMsDKEEpreFz53viKrN3CK6RgfETMPMWloDdS3yI3z
z+FsJM5jsv2AVdGH0RLZyD8lkZfElzHfSjE3tvAQFe43AWnOliRqjze2Vf8JmJfv
TLJGMUNERI8BKvhdd+q9nubi4SlurRjmPVMDUhJChB7eupOe4OSHEfAwEE3JYEBH
U0xfoGi7LbxE61Ew7GFCgzNKllOgkY5RqrfvjVPjwj5Bl9bleuqqhLfaPyJaftVH
LS9FgK8fCLKqmU7XA98qeAXKy+t17OXteDMV+NuT5Us2b/xGECm9J1+NJDQPRHCT
RMYbh4B/6mzR7Jjw87ByJOjzWnl6XWJ2kvf3ZI2Y3uQeUV7mjZbg2YGfEZFirr9T
+C85BivcN+XLLVYbonqK/sD2dUjh4s9jIELkrcFm9XydGBVRvcrZCFu661Fg8Ro+
QOBMUH+T0/45s4VKf14S3d7wZAXE1w5yJdz7/yXw1zpeGojgMZrGBZzFRDI9eh9J
1+MrtLKbvxQcQHni696PJ1BkIMX6f8Wjp6gIr4m+MWoJrNi2VIfTQldVbQVhqVmF
URikFHfMDxMpJxsZ45fAwSfHRO5+jwMyB6KOmaSQhS6y4YpLb6Y3j6QG1KL6+kjf
/IPYS11c
-----END CERTIFICATE-----

View File

@ -0,0 +1,3 @@
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIBkz65y9k4wYXTNXgNDhKfJnCiEosnD95sFoVIxWmOzL
-----END PRIVATE KEY-----

6
examples/tls/private/gen_ca.sh Executable file
View File

@ -0,0 +1,6 @@
#! /bin/bash
CA_SUBJECT="/C=US/ST=CA/O=Rocket CA/CN=Rocket Root CA"
openssl genrsa -out ca_key.pem 4096
openssl req -new -x509 -days 3650 -key ca_key.pem -subj "${CA_SUBJECT}" -out ca_cert.pem

View File

@ -1,21 +0,0 @@
#! /bin/bash
# TODO: `rustls` (really, `webpki`) doesn't currently use the CN in the subject
# to check if a certificate is valid for a server name sent via SNI. It's not
# clear if this is intended, since certificates _should_ have a `subjectAltName`
# with a DNS name, or if it simply hasn't been implemented yet. See
# https://bugzilla.mozilla.org/show_bug.cgi?id=552346 for a bit more info.
CA_SUBJECT="/C=US/ST=CA/O=Rocket CA/CN=Rocket Root CA"
SUBJECT="/C=US/ST=CA/O=Rocket/CN=localhost"
ALT="DNS:localhost"
openssl genrsa -out ca_key.pem 4096
openssl req -new -x509 -days 3650 -key ca_key.pem -subj "${CA_SUBJECT}" -out ca_cert.pem
openssl req -newkey rsa:4096 -nodes -sha256 -keyout key.pem -subj "${SUBJECT}" -out server.csr
openssl x509 -req -sha256 -extfile <(printf "subjectAltName=${ALT}") -days 3650 \
-CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial \
-in server.csr -out cert.pem
rm ca_cert.srl server.csr

View File

@ -0,0 +1,80 @@
#! /bin/bash
# Should use gen_ca.sh first to generate the CA.
# To generate certificates of specific private key type, pass any of the following arguements:
# 'ed25519', 'rsa_sha256', 'ecdsa_nistp256_sha256' or 'ecdsa_nistp384_sha384'
#
# If no argument is passed all supported certificates types will be generated.
#
# TODO: `rustls` (really, `webpki`) doesn't currently use the CN in the subject
# to check if a certificate is valid for a server name sent via SNI. It's not
# clear if this is intended, since certificates _should_ have a `subjectAltName`
# with a DNS name, or if it simply hasn't been implemented yet. See
# https://bugzilla.mozilla.org/show_bug.cgi?id=552346 for a bit more info.
SUBJECT="/C=US/ST=CA/O=Rocket/CN=localhost"
ALT="DNS:localhost"
function gen_rsa_sha256() {
openssl req -newkey rsa:4096 -nodes -sha256 -keyout rsa_sha256_key.pem -subj "${SUBJECT}" -out server.csr
openssl x509 -req -sha256 -extfile <(printf "subjectAltName=${ALT}") -days 3650 \
-CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial \
-in server.csr -out rsa_sha256_cert.pem
rm ca_cert.srl server.csr
}
function gen_ed25519() {
openssl genpkey -algorithm ED25519 > ed25519_key.pem
openssl req -new -key ed25519_key.pem -subj "${SUBJECT}" -out server.csr
openssl x509 -req -extfile <(printf "subjectAltName=${ALT}") -days 3650 \
-CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial \
-in server.csr -out ed25519_cert.pem
rm ca_cert.srl server.csr
}
function gen_ecdsa_nistp256_sha256() {
openssl ecparam -out ecdsa_nistp256_sha256_key.pem -name prime256v1 -genkey
# Convert to pkcs8 format supported by rustls
openssl pkcs8 -topk8 -nocrypt -in ecdsa_nistp256_sha256_key.pem -out ecdsa_nistp256_sha256_key_pkcs8.pem
openssl req -new -nodes -sha256 -key ecdsa_nistp256_sha256_key_pkcs8.pem -subj "${SUBJECT}" -out server.csr
openssl x509 -req -sha256 -extfile <(printf "subjectAltName=${ALT}") -days 3650 \
-CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial \
-in server.csr -out ecdsa_nistp256_sha256_cert.pem
rm ca_cert.srl server.csr ecdsa_nistp256_sha256_key.pem
}
function gen_ecdsa_nistp384_sha384() {
openssl ecparam -out ecdsa_nistp384_sha384_key.pem -name secp384r1 -genkey
# Convert to pkcs8 format supported by rustls
openssl pkcs8 -topk8 -nocrypt -in ecdsa_nistp384_sha384_key.pem -out ecdsa_nistp384_sha384_key_pkcs8.pem
openssl req -new -nodes -sha384 -key ecdsa_nistp384_sha384_key_pkcs8.pem -subj "${SUBJECT}" -out server.csr
openssl x509 -req -sha384 -extfile <(printf "subjectAltName=${ALT}") -days 3650 \
-CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial \
-in server.csr -out ecdsa_nistp384_sha384_cert.pem
rm ca_cert.srl server.csr ecdsa_nistp384_sha384_key.pem
}
case $1 in
ed25519) gen_ed25519 ;;
rsa_sha256) gen_rsa_sha256 ;;
ecdsa_nistp256_sha256) gen_ecdsa_nistp256_sha256 ;;
ecdsa_nistp384_sha384) gen_ecdsa_nistp384_sha384 ;;
*)
gen_ed25519
gen_rsa_sha256
gen_ecdsa_nistp256_sha256
gen_ecdsa_nistp384_sha384
;;
esac