index : static-web-server.git

ascending towards madness

author Jose Quintana <1700322+joseluisq@users.noreply.github.com> 2023-05-28 21:00:39.0 +00:00:00
committer GitHub <noreply@github.com> 2023-05-28 21:00:39.0 +00:00:00
commit
0f66443c2f90bb6f1eccd9e7af32107364c81c72 [patch]
tree
b06fa160481efa2567a4e2520c584ac735694b8b
parent
c64e3d6754fc35974a0d0872b311d06505ae568a
download
0f66443c2f90bb6f1eccd9e7af32107364c81c72.tar.gz

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(-)

diff --git a/src/tls.rs b/src/tls.rs
index 195141e..72d8878 100644
--- a/src/tls.rs
+++ b/src/tls.rs
@@ -185,32 +185,35 @@ impl TlsConfigBuilder {
            .map(Certificate)
            .collect();

        let key = {
            // convert it to Vec<u8> to allow reading it again if key is RSA
            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)?;
        // convert it to Vec<u8> to allow reading it again if key is RSA
        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();
    }
}
diff --git a/tests/tls/local.dev_cert.ecc.pem b/tests/tls/local.dev_cert.ecc.pem
new file mode 100644
index 0000000..f661a63
--- /dev/null
+++ b/tests/tls/local.dev_cert.ecc.pem
@@ -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-----
diff --git a/tests/tls/local.dev_key.ecc.pem b/tests/tls/local.dev_key.ecc.pem
new file mode 100644
index 0000000..9287db7
--- /dev/null
+++ b/tests/tls/local.dev_key.ecc.pem
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIPwp3LAnLEyWe2lLz66Y3QCCJ/BEMJheTM0shZnnSw6toAoGCCqGSM49
AwEHoUQDQgAE2UeBetF/oh43g+pMkmX15YzXJA29tkGEO+k7OBhWFpHQ7LVOsnoc
chEfjGVrJlJ0xPxst5p6UpjM6EgX6CkZhw==
-----END EC PRIVATE KEY-----