From dfaf4de7748b10353de4d6918c180b38d588541b Mon Sep 17 00:00:00 2001 From: Florian Uekermann Date: Thu, 16 May 2024 17:38:12 +0200 Subject: [PATCH] update rcgen --- Cargo.toml | 4 ++-- src/acme.rs | 17 +++++++++-------- src/caches/test.rs | 36 ++++++++++++------------------------ src/state.rs | 13 ++++++------- 4 files changed, 29 insertions(+), 41 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 33f22bb..dc278ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustls-acme" -version = "0.10.0" +version = "0.10.1" authors = ["Florian Uekermann "] edition = "2018" description = "TLS certificate management and serving using rustls" @@ -13,7 +13,7 @@ categories = ["asynchronous", "cryptography", "network-programming"] [dependencies] futures-rustls = { version = "0.26", default-features = false } futures = "0.3.21" -rcgen = { version = "0.12", default-features = false, features = ["pem"] } +rcgen = { version = "0.13", default-features = false, features = ["pem"] } serde_json = "1.0.81" serde = { version = "1.0.137", features=["derive"] } ring = { version = "0.17.7", features = ["std"], optional = true } diff --git a/src/acme.rs b/src/acme.rs index c3747b6..39a3e4d 100644 --- a/src/acme.rs +++ b/src/acme.rs @@ -7,11 +7,11 @@ use crate::crypto::signature::{EcdsaKeyPair, EcdsaSigningAlgorithm, ECDSA_P256_S use crate::https_helper::{https, HttpsRequestError}; use crate::jose::{key_authorization_sha256, sign, JoseError}; use base64::prelude::*; -use futures_rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer}; +use futures_rustls::pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer}; use futures_rustls::rustls::{sign::CertifiedKey, ClientConfig}; use http::header::ToStrError; use http::{Method, Response}; -use rcgen::{Certificate, CustomExtension, PKCS_ECDSA_P256_SHA256}; +use rcgen::{CustomExtension, KeyPair, PKCS_ECDSA_P256_SHA256}; use serde::{Deserialize, Serialize}; use serde_json::json; use thiserror::Error; @@ -106,7 +106,7 @@ impl Account { let response = self.request(client_config, &url, "").await?; Ok(serde_json::from_str(&response.1)?) } - pub async fn finalize(&self, client_config: &Arc, url: impl AsRef, csr: Vec) -> Result { + pub async fn finalize(&self, client_config: &Arc, url: impl AsRef, csr: &[u8]) -> Result { let payload = format!("{{\"csr\":\"{}\"}}", BASE64_URL_SAFE_NO_PAD.encode(csr)); let response = self.request(client_config, &url, &payload).await?; Ok(serde_json::from_str(&response.1)?) @@ -120,13 +120,14 @@ impl Account { Some(challenge) => challenge, None => return Err(AcmeError::NoTlsAlpn01Challenge), }; - let mut params = rcgen::CertificateParams::new(vec![domain]); + let mut params = rcgen::CertificateParams::new(vec![domain])?; let key_auth = key_authorization_sha256(&self.key_pair, &*challenge.token)?; - params.alg = &PKCS_ECDSA_P256_SHA256; params.custom_extensions = vec![CustomExtension::new_acme_identifier(key_auth.as_ref())]; - let cert = Certificate::from_params(params)?; - let pk = any_ecdsa_type(&PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(cert.serialize_private_key_der()))).unwrap(); - let certified_key = CertifiedKey::new(vec![CertificateDer::from(cert.serialize_der()?)], pk); + let key_pair = KeyPair::generate_for(&PKCS_ECDSA_P256_SHA256)?; + let cert = params.self_signed(&key_pair)?; + + let sk = any_ecdsa_type(&PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(key_pair.serialize_der()))).unwrap(); + let certified_key = CertifiedKey::new(vec![cert.der().clone()], sk); Ok((challenge, certified_key)) } } diff --git a/src/caches/test.rs b/src/caches/test.rs index 083b129..3f373b4 100644 --- a/src/caches/test.rs +++ b/src/caches/test.rs @@ -1,6 +1,6 @@ use crate::{AccountCache, CertCache}; use async_trait::async_trait; -use rcgen::{date_time_ymd, BasicConstraints, CertificateParams, DistinguishedName, DnType, IsCa, KeyUsagePurpose, PKCS_ECDSA_P256_SHA256}; +use rcgen::{date_time_ymd, BasicConstraints, CertificateParams, DistinguishedName, DnType, IsCa, KeyPair, KeyUsagePurpose, PKCS_ECDSA_P256_SHA256}; use std::fmt::Debug; use std::marker::PhantomData; use std::sync::atomic::AtomicPtr; @@ -19,6 +19,7 @@ use std::sync::Arc; /// ``` #[derive(Clone)] pub struct TestCache { + ca_key: Arc, ca_cert: Arc, ca_pem: Arc, _cert_error: PhantomData>>, @@ -33,15 +34,15 @@ impl TestCache { distinguished_name.push(DnType::OrganizationName, "Test CA"); distinguished_name.push(DnType::CommonName, "Test CA"); params.distinguished_name = distinguished_name; - params.alg = &PKCS_ECDSA_P256_SHA256; params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained); params.key_usages = vec![KeyUsagePurpose::KeyCertSign, KeyUsagePurpose::CrlSign]; params.not_before = date_time_ymd(2000, 1, 1); params.not_after = date_time_ymd(3000, 1, 1); - - let ca_cert = rcgen::Certificate::from_params(params).unwrap(); - let ca_pem = ca_cert.serialize_pem().unwrap(); + let key_pair = KeyPair::generate_for(&PKCS_ECDSA_P256_SHA256).unwrap(); + let ca_cert = params.self_signed(&key_pair).unwrap(); + let ca_pem = ca_cert.pem(); Self { + ca_key: key_pair.into(), ca_cert: ca_cert.into(), ca_pem: ca_pem.into(), _cert_error: Default::default(), @@ -57,30 +58,17 @@ impl TestCache { impl CertCache for TestCache { type EC = EC; async fn load_cert(&self, domains: &[String], _directory_url: &str) -> Result>, Self::EC> { - let mut params = CertificateParams::new(domains); + let mut params = CertificateParams::new(domains).unwrap(); let mut distinguished_name = DistinguishedName::new(); distinguished_name.push(DnType::CommonName, "Test Cert"); params.distinguished_name = distinguished_name; - params.alg = &PKCS_ECDSA_P256_SHA256; params.not_before = date_time_ymd(2000, 1, 1); params.not_after = date_time_ymd(3000, 1, 1); - let cert = match rcgen::Certificate::from_params(params) { - Ok(cert) => cert, - Err(err) => { - log::error!("test cache: generation error: {:?}", err); - return Ok(None); - } - }; - let cert_pem = match cert.serialize_pem_with_signer(&self.ca_cert) { - Ok(pem) => pem, - Err(err) => { - log::error!("test cache: signing error: {:?}", err); - return Ok(None); - } - }; - - let pem = [&cert.serialize_private_key_pem(), "\n", &cert_pem, "\n", &self.ca_pem].concat(); - Ok(Some(pem.into_bytes())) + let key_pair = KeyPair::generate_for(&PKCS_ECDSA_P256_SHA256).unwrap(); + let cert = params.signed_by(&key_pair, &self.ca_cert, &self.ca_key).unwrap(); + let private_key_pem = key_pair.serialize_pem(); + let signed_cert_pem = cert.pem(); + Ok(Some([&private_key_pem, "\n", &signed_cert_pem, "\n", &self.ca_pem].concat().into_bytes())) } async fn store_cert(&self, _domains: &[String], _directory_url: &str, _cert: &[u8]) -> Result<(), Self::EC> { log::info!("test cache configured, could not store certificate"); diff --git a/src/state.rs b/src/state.rs index 01b2cc2..b3be325 100644 --- a/src/state.rs +++ b/src/state.rs @@ -11,7 +11,7 @@ use futures_rustls::pki_types::{CertificateDer as RustlsCertificate, PrivateKeyD use futures_rustls::rustls::crypto::CryptoProvider; use futures_rustls::rustls::sign::CertifiedKey; use futures_rustls::rustls::ServerConfig; -use rcgen::{CertificateParams, DistinguishedName, PKCS_ECDSA_P256_SHA256}; +use rcgen::{CertificateParams, DistinguishedName, KeyPair, PKCS_ECDSA_P256_SHA256}; use std::convert::Infallible; use std::fmt::Debug; use std::future::Future; @@ -242,10 +242,10 @@ impl AcmeState { let directory = Directory::discover(&config.client_config, &config.directory_url).await?; let account = Account::create_with_keypair(&config.client_config, directory, &config.contact, &key_pair).await?; - let mut params = CertificateParams::new(config.domains.clone()); + let mut params = CertificateParams::new(config.domains.clone())?; params.distinguished_name = DistinguishedName::new(); - params.alg = &PKCS_ECDSA_P256_SHA256; - let cert = rcgen::Certificate::from_params(params)?; + let key_pair = KeyPair::generate_for(&PKCS_ECDSA_P256_SHA256)?; + let csr = params.serialize_request(&key_pair)?; let (order_url, mut order) = account.new_order(&config.client_config, config.domains.clone()).await?; loop { @@ -271,13 +271,12 @@ impl AcmeState { } OrderStatus::Ready => { log::info!("sending csr"); - let csr = cert.serialize_request_der()?; - order = account.finalize(&config.client_config, order.finalize, csr).await? + order = account.finalize(&config.client_config, order.finalize, csr.der()).await? } OrderStatus::Valid { certificate } => { log::info!("download certificate"); let pem = [ - &cert.serialize_private_key_pem(), + &key_pair.serialize_pem(), "\n", &account.certificate(&config.client_config, certificate).await?, ]