From aa2caf96d8d3da37413ec7641c85cfe3787d9723 Mon Sep 17 00:00:00 2001 From: tbro Date: Mon, 9 Oct 2023 18:26:29 -0500 Subject: [PATCH] Add example of generating a cert chain Generate two certificates and sign the second with the first. --- Cargo.toml | 4 +++ examples/sign-leaf-with-ca.rs | 58 +++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 examples/sign-leaf-with-ca.rs diff --git a/Cargo.toml b/Cargo.toml index a47fb72f..3ba0d556 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,10 @@ required-features = ["pem"] name = "rsa-irc-openssl" required-features = ["pem"] +[[example]] +name = "sign-leaf-with-ca" +required-features = ["pem", "x509-parser"] + [dependencies] yasna = { version = "0.5.2", features = ["time", "std"] } ring = "0.17" diff --git a/examples/sign-leaf-with-ca.rs b/examples/sign-leaf-with-ca.rs new file mode 100644 index 00000000..ae8c83af --- /dev/null +++ b/examples/sign-leaf-with-ca.rs @@ -0,0 +1,58 @@ +use rcgen::{ + BasicConstraints, Certificate, CertificateParams, DnType, DnValue::PrintableString, + ExtendedKeyUsagePurpose, IsCa, KeyUsagePurpose, +}; +use time::{Duration, OffsetDateTime}; + +/// Example demonstrating signing end-endity certificate with ca +fn main() { + let ca = new_ca(); + let end_entity = new_end_entity(); + + let end_entity_pem = end_entity.serialize_pem_with_signer(&ca).unwrap(); + println!("directly signed end-entity certificate: {end_entity_pem}"); + + let ca_cert_pem = ca.serialize_pem().unwrap(); + println!("ca certificate: {ca_cert_pem}",); +} + +fn new_ca() -> Certificate { + let mut params = CertificateParams::new(Vec::default()); + let (yesterday, tomorrow) = validity_period(); + params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained); + params + .distinguished_name + .push(DnType::CountryName, PrintableString("BR".into())); + params + .distinguished_name + .push(DnType::OrganizationName, "Crab widgits SE"); + params.key_usages.push(KeyUsagePurpose::DigitalSignature); + params.key_usages.push(KeyUsagePurpose::KeyCertSign); + params.key_usages.push(KeyUsagePurpose::CrlSign); + + params.not_before = yesterday; + params.not_after = tomorrow; + Certificate::from_params(params).unwrap() +} + +fn new_end_entity() -> Certificate { + let name = "entity.other.host"; + let mut params = CertificateParams::new(vec![name.into()]); + let (yesterday, tomorrow) = validity_period(); + params.distinguished_name.push(DnType::CommonName, name); + params.use_authority_key_identifier_extension = true; + params.key_usages.push(KeyUsagePurpose::DigitalSignature); + params + .extended_key_usages + .push(ExtendedKeyUsagePurpose::ServerAuth); + params.not_before = yesterday; + params.not_after = tomorrow; + Certificate::from_params(params).unwrap() +} + +fn validity_period() -> (OffsetDateTime, OffsetDateTime) { + let day = Duration::new(86400, 0); + let yesterday = OffsetDateTime::now_utc().checked_sub(day).unwrap(); + let tomorrow = OffsetDateTime::now_utc().checked_add(day).unwrap(); + (yesterday, tomorrow) +}