From cc64b11afbc63ba5a64d4528a0f984cab268f934 Mon Sep 17 00:00:00 2001 From: Oscar Beaumont Date: Tue, 21 May 2024 22:14:20 +0800 Subject: [PATCH 1/5] Add `Certificate::from_der` --- rcgen/src/certificate.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/rcgen/src/certificate.rs b/rcgen/src/certificate.rs index e00b8e8b..fd0c2711 100644 --- a/rcgen/src/certificate.rs +++ b/rcgen/src/certificate.rs @@ -29,10 +29,21 @@ pub struct Certificate { } impl Certificate { + /// TODO + pub fn from_der(der: CertificateDer<'static>, keypair: KeyPair) -> Result { + let params = CertificateParams::from_ca_cert_der(&der)?; + Ok(Self { + params, + subject_public_key_info: keypair.public_key_der(), + der, + }) + } + /// Returns the certificate parameters pub fn params(&self) -> &CertificateParams { &self.params } + /// Calculates a subject key identifier for the certificate subject's public key. /// This key identifier is used in the SubjectKeyIdentifier X.509v3 extension. pub fn key_identifier(&self) -> Vec { @@ -40,6 +51,7 @@ impl Certificate { .key_identifier_method .derive(&self.subject_public_key_info) } + /// Get the certificate in DER encoded format. /// /// [`CertificateDer`] implements `Deref` and `AsRef<[u8]>`, so you can easily @@ -47,6 +59,7 @@ impl Certificate { pub fn der(&self) -> &CertificateDer<'static> { &self.der } + /// Get the certificate in PEM encoded format. #[cfg(feature = "pem")] pub fn pem(&self) -> String { From e9f2a5d1c6d8d3e88a14d34e78062d7fd921e97c Mon Sep 17 00:00:00 2001 From: Oscar Beaumont Date: Tue, 21 May 2024 22:17:26 +0800 Subject: [PATCH 2/5] move `Issuer` to `issuer.rs` --- rcgen/src/issuer.rs | 11 +++++++++++ rcgen/src/lib.rs | 9 ++------- 2 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 rcgen/src/issuer.rs diff --git a/rcgen/src/issuer.rs b/rcgen/src/issuer.rs new file mode 100644 index 00000000..d464368b --- /dev/null +++ b/rcgen/src/issuer.rs @@ -0,0 +1,11 @@ +use crate::{DistinguishedName, KeyIdMethod, KeyPair, KeyUsagePurpose}; + +/// TODO +pub struct Issuer<'a> { + pub(crate) distinguished_name: &'a DistinguishedName, + pub(crate) key_identifier_method: &'a KeyIdMethod, + pub(crate) key_usages: &'a [KeyUsagePurpose], + pub(crate) key_pair: &'a KeyPair, +} + +impl<'a> Issuer<'a> {} diff --git a/rcgen/src/lib.rs b/rcgen/src/lib.rs index 912e9d91..8b93a16b 100644 --- a/rcgen/src/lib.rs +++ b/rcgen/src/lib.rs @@ -58,6 +58,7 @@ pub use crl::{ }; pub use csr::{CertificateSigningRequest, CertificateSigningRequestParams, PublicKey}; pub use error::{Error, InvalidAsn1String}; +pub use issuer::Issuer; use key_pair::PublicKeyData; #[cfg(all(feature = "crypto", feature = "aws_lc_rs"))] pub use key_pair::RsaKeySize; @@ -72,6 +73,7 @@ mod certificate; mod crl; mod csr; mod error; +mod issuer; mod key_pair; mod oid; mod ring_like; @@ -130,13 +132,6 @@ pub fn generate_simple_self_signed( Ok(CertifiedKey { cert, key_pair }) } -struct Issuer<'a> { - distinguished_name: &'a DistinguishedName, - key_identifier_method: &'a KeyIdMethod, - key_usages: &'a [KeyUsagePurpose], - key_pair: &'a KeyPair, -} - // https://tools.ietf.org/html/rfc5280#section-4.1.1 // Example certs usable as reference: From 07181c3c57fb9fdedb04b4ec7370133ef0edebcd Mon Sep 17 00:00:00 2001 From: Oscar Beaumont Date: Tue, 21 May 2024 22:38:43 +0800 Subject: [PATCH 3/5] Owned & public `Issuer` --- rcgen/src/certificate.rs | 28 +++++------------ rcgen/src/crl.rs | 15 ++-------- rcgen/src/csr.rs | 15 ++-------- rcgen/src/issuer.rs | 60 ++++++++++++++++++++++++++++++++----- rustls-cert-gen/src/cert.rs | 25 +++++++--------- 5 files changed, 75 insertions(+), 68 deletions(-) diff --git a/rcgen/src/certificate.rs b/rcgen/src/certificate.rs index fd0c2711..7d46ca0c 100644 --- a/rcgen/src/certificate.rs +++ b/rcgen/src/certificate.rs @@ -160,19 +160,7 @@ impl CertificateParams { /// /// The returned [`Certificate`] may be serialized using [`Certificate::der`] and /// [`Certificate::pem`]. - pub fn signed_by( - self, - key_pair: &KeyPair, - issuer: &Certificate, - issuer_key: &KeyPair, - ) -> Result { - let issuer = Issuer { - distinguished_name: &issuer.params.distinguished_name, - key_identifier_method: &issuer.params.key_identifier_method, - key_usages: &issuer.params.key_usages, - key_pair: issuer_key, - }; - + pub fn signed_by(self, key_pair: &KeyPair, issuer: &Issuer) -> Result { let subject_public_key_info = key_pair.public_key_der(); let der = self.serialize_der_with_signer(key_pair, issuer)?; Ok(Certificate { @@ -188,14 +176,14 @@ impl CertificateParams { /// [`Certificate::pem`]. pub fn self_signed(self, key_pair: &KeyPair) -> Result { let issuer = Issuer { - distinguished_name: &self.distinguished_name, - key_identifier_method: &self.key_identifier_method, - key_usages: &self.key_usages, - key_pair, + distinguished_name: self.distinguished_name, + key_identifier_method: self.key_identifier_method, + key_usages: self.key_usages, + key_pair: todo!(), // TODO: Do we `KeyPair::Clone` or do we make this field a `Cow`? }; let subject_public_key_info = key_pair.public_key_der(); - let der = self.serialize_der_with_signer(key_pair, issuer)?; + let der = self.serialize_der_with_signer(key_pair, &issuer)?; Ok(Certificate { params: self, subject_public_key_info, @@ -610,7 +598,7 @@ impl CertificateParams { pub(crate) fn serialize_der_with_signer( &self, pub_key: &K, - issuer: Issuer<'_>, + issuer: &Issuer, ) -> Result, Error> { let der = issuer.key_pair.sign_der(|writer| { let pub_key_spki = @@ -669,7 +657,7 @@ impl CertificateParams { if self.use_authority_key_identifier_extension { write_x509_authority_key_identifier( writer.next(), - match issuer.key_identifier_method { + match &issuer.key_identifier_method { KeyIdMethod::PreSpecified(aki) => aki.clone(), #[cfg(feature = "crypto")] _ => issuer diff --git a/rcgen/src/crl.rs b/rcgen/src/crl.rs index 8250b88a..12932257 100644 --- a/rcgen/src/crl.rs +++ b/rcgen/src/crl.rs @@ -186,22 +186,11 @@ impl CertificateRevocationListParams { /// Serializes the certificate revocation list (CRL). /// /// Including a signature from the issuing certificate authority's key. - pub fn signed_by( - self, - issuer: &Certificate, - issuer_key: &KeyPair, - ) -> Result { + pub fn signed_by(self, issuer: &Issuer) -> Result { if self.next_update.le(&self.this_update) { return Err(Error::InvalidCrlNextUpdate); } - let issuer = Issuer { - distinguished_name: &issuer.params.distinguished_name, - key_identifier_method: &issuer.params.key_identifier_method, - key_usages: &issuer.params.key_usages, - key_pair: issuer_key, - }; - if !issuer.key_usages.is_empty() && !issuer.key_usages.contains(&KeyUsagePurpose::CrlSign) { return Err(Error::IssuerNotCrlSigner); } @@ -212,7 +201,7 @@ impl CertificateRevocationListParams { }) } - fn serialize_der(&self, issuer: Issuer) -> Result, Error> { + fn serialize_der(&self, issuer: &Issuer) -> Result, Error> { issuer.key_pair.sign_der(|writer| { // Write CRL version. // RFC 5280 ยง5.1.2.1: diff --git a/rcgen/src/csr.rs b/rcgen/src/csr.rs index 90ec2237..4ce239cd 100644 --- a/rcgen/src/csr.rs +++ b/rcgen/src/csr.rs @@ -184,21 +184,10 @@ impl CertificateSigningRequestParams { /// /// The returned [`Certificate`] may be serialized using [`Certificate::der`] and /// [`Certificate::pem`]. - pub fn signed_by( - self, - issuer: &Certificate, - issuer_key: &KeyPair, - ) -> Result { - let issuer = Issuer { - distinguished_name: &issuer.params.distinguished_name, - key_identifier_method: &issuer.params.key_identifier_method, - key_usages: &issuer.params.key_usages, - key_pair: issuer_key, - }; - + pub fn signed_by(self, issuer: &Issuer) -> Result { let der = self .params - .serialize_der_with_signer(&self.public_key, issuer)?; + .serialize_der_with_signer(&self.public_key, &issuer)?; let subject_public_key_info = yasna::construct_der(|writer| { self.public_key.serialize_public_key_der(writer); }); diff --git a/rcgen/src/issuer.rs b/rcgen/src/issuer.rs index d464368b..2dce1227 100644 --- a/rcgen/src/issuer.rs +++ b/rcgen/src/issuer.rs @@ -1,11 +1,57 @@ -use crate::{DistinguishedName, KeyIdMethod, KeyPair, KeyUsagePurpose}; +use pki_types::CertificateDer; + +use crate::{ + Certificate, CertificateParams, DistinguishedName, Error, KeyIdMethod, KeyPair, KeyUsagePurpose, +}; /// TODO -pub struct Issuer<'a> { - pub(crate) distinguished_name: &'a DistinguishedName, - pub(crate) key_identifier_method: &'a KeyIdMethod, - pub(crate) key_usages: &'a [KeyUsagePurpose], - pub(crate) key_pair: &'a KeyPair, +pub struct Issuer { + pub(crate) distinguished_name: DistinguishedName, + pub(crate) key_identifier_method: KeyIdMethod, + pub(crate) key_usages: Vec, + pub(crate) key_pair: KeyPair, } -impl<'a> Issuer<'a> {} +impl Issuer { + /// TODO + pub fn new(ca_cert: CertificateDer, key_pair: KeyPair) -> Result { + let params = CertificateParams::from_ca_cert_der(&ca_cert)?; + Ok(Self { + distinguished_name: params.distinguished_name, + key_identifier_method: params.key_identifier_method, + key_usages: params.key_usages, + key_pair, + }) + } + + /// TODO + pub fn from_params(params: CertificateParams, key_pair: KeyPair) -> Self { + Self { + distinguished_name: params.distinguished_name, + key_identifier_method: params.key_identifier_method, + key_usages: params.key_usages, + key_pair, + } + } + + /// TODO + pub fn certificate(&self) -> Certificate { + // let params = CertificateParams::from_ca_cert_der(&der)?; + // Ok(Certificate { + // params, + // subject_public_key_info: keypair.public_key_der(), + // der, + // }) + todo!(); + } + + /// TODO + pub fn pem(&self) -> String { + todo!(); + } + + /// TODO + pub fn key_pair(&self) -> &KeyPair { + &self.key_pair + } +} diff --git a/rustls-cert-gen/src/cert.rs b/rustls-cert-gen/src/cert.rs index 89378a90..626047e3 100644 --- a/rustls-cert-gen/src/cert.rs +++ b/rustls-cert-gen/src/cert.rs @@ -3,7 +3,8 @@ use std::{fmt, fs::File, io, path::Path}; use bpaf::Bpaf; use rcgen::{ BasicConstraints, Certificate, CertificateParams, DistinguishedName, DnType, - DnValue::PrintableString, ExtendedKeyUsagePurpose, IsCa, KeyPair, KeyUsagePurpose, SanType, + DnValue::PrintableString, ExtendedKeyUsagePurpose, IsCa, Issuer, KeyPair, KeyUsagePurpose, + SanType, }; #[cfg(feature = "aws_lc_rs")] @@ -113,29 +114,25 @@ impl CaBuilder { /// build `Ca` Certificate. pub fn build(self) -> Result { let key_pair = self.alg.to_key_pair()?; - let cert = self.params.self_signed(&key_pair)?; - Ok(Ca { cert, key_pair }) + Ok(Ca(Issuer::from_params(self.params, key_pair))) } } /// End-entity [Certificate] -pub struct Ca { - cert: Certificate, - key_pair: KeyPair, -} +pub struct Ca(Issuer); impl Ca { /// Self-sign and serialize pub fn serialize_pem(&self) -> PemCertifiedKey { PemCertifiedKey { - cert_pem: self.cert.pem(), - private_key_pem: self.key_pair.serialize_pem(), + cert_pem: self.0.pem(), + private_key_pem: self.0.key_pair().serialize_pem(), } } - /// Return `&Certificate` + /// Return `Certificate` #[allow(dead_code)] - pub fn cert(&self) -> &Certificate { - &self.cert + pub fn cert(&self) -> Certificate { + self.0.certificate() } } @@ -203,9 +200,7 @@ impl EndEntityBuilder { /// build `EndEntity` Certificate. pub fn build(self, issuer: &Ca) -> Result { let key_pair = self.alg.to_key_pair()?; - let cert = self - .params - .signed_by(&key_pair, &issuer.cert, &issuer.key_pair)?; + let cert = self.params.signed_by(&key_pair, &issuer.0)?; Ok(EndEntity { cert, key_pair }) } } From 648473ae7c3ff53c967b33d1bce6af933ce8d697 Mon Sep 17 00:00:00 2001 From: Oscar Beaumont Date: Tue, 21 May 2024 22:39:07 +0800 Subject: [PATCH 4/5] Drop `Certificate::from_der` --- rcgen/src/certificate.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/rcgen/src/certificate.rs b/rcgen/src/certificate.rs index 7d46ca0c..01fda812 100644 --- a/rcgen/src/certificate.rs +++ b/rcgen/src/certificate.rs @@ -29,16 +29,6 @@ pub struct Certificate { } impl Certificate { - /// TODO - pub fn from_der(der: CertificateDer<'static>, keypair: KeyPair) -> Result { - let params = CertificateParams::from_ca_cert_der(&der)?; - Ok(Self { - params, - subject_public_key_info: keypair.public_key_der(), - der, - }) - } - /// Returns the certificate parameters pub fn params(&self) -> &CertificateParams { &self.params From b0e10ed49c74cef61766491079a123ec3e272133 Mon Sep 17 00:00:00 2001 From: Oscar Beaumont Date: Tue, 21 May 2024 23:10:48 +0800 Subject: [PATCH 5/5] cleanup naming --- rcgen/src/issuer.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/rcgen/src/issuer.rs b/rcgen/src/issuer.rs index 2dce1227..d713d15d 100644 --- a/rcgen/src/issuer.rs +++ b/rcgen/src/issuer.rs @@ -46,8 +46,13 @@ impl Issuer { } /// TODO - pub fn pem(&self) -> String { - todo!(); + pub fn cert_pem(&self) -> String { + todo!("required for `rustls-cert-gen`"); + } + + /// TODO + pub fn key_pem(&self) -> String { + todo!("seems a fitting complement to `Self::cert_pem`"); } /// TODO