123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- //! A program that generates ca certs, certs verified by the ca, and public
- //! and private keys.
- use openssl::asn1::Asn1Time;
- use openssl::bn::{BigNum, MsbOption};
- use openssl::error::ErrorStack;
- use openssl::hash::MessageDigest;
- use openssl::pkey::{PKey, PKeyRef, Private};
- use openssl::rsa::Rsa;
- use openssl::x509::extension::{
- AuthorityKeyIdentifier, BasicConstraints, KeyUsage, SubjectAlternativeName,
- SubjectKeyIdentifier,
- };
- use openssl::x509::{X509NameBuilder, X509Ref, X509Req, X509ReqBuilder, X509VerifyResult, X509};
- /// Make a CA certificate and private key
- fn mk_ca_cert() -> Result<(X509, PKey<Private>), ErrorStack> {
- let rsa = Rsa::generate(2048)?;
- let key_pair = PKey::from_rsa(rsa)?;
- let mut x509_name = X509NameBuilder::new()?;
- x509_name.append_entry_by_text("C", "US")?;
- x509_name.append_entry_by_text("ST", "TX")?;
- x509_name.append_entry_by_text("O", "Some CA organization")?;
- x509_name.append_entry_by_text("CN", "ca test")?;
- let x509_name = x509_name.build();
- let mut cert_builder = X509::builder()?;
- cert_builder.set_version(2)?;
- let serial_number = {
- let mut serial = BigNum::new()?;
- serial.rand(159, MsbOption::MAYBE_ZERO, false)?;
- serial.to_asn1_integer()?
- };
- cert_builder.set_serial_number(&serial_number)?;
- cert_builder.set_subject_name(&x509_name)?;
- cert_builder.set_issuer_name(&x509_name)?;
- cert_builder.set_pubkey(&key_pair)?;
- let not_before = Asn1Time::days_from_now(0)?;
- cert_builder.set_not_before(¬_before)?;
- let not_after = Asn1Time::days_from_now(365)?;
- cert_builder.set_not_after(¬_after)?;
- cert_builder.append_extension(BasicConstraints::new().critical().ca().build()?)?;
- cert_builder.append_extension(
- KeyUsage::new()
- .critical()
- .key_cert_sign()
- .crl_sign()
- .build()?,
- )?;
- let subject_key_identifier =
- SubjectKeyIdentifier::new().build(&cert_builder.x509v3_context(None, None))?;
- cert_builder.append_extension(subject_key_identifier)?;
- cert_builder.sign(&key_pair, MessageDigest::sha256())?;
- let cert = cert_builder.build();
- Ok((cert, key_pair))
- }
- /// Make a X509 request with the given private key
- fn mk_request(key_pair: &PKey<Private>) -> Result<X509Req, ErrorStack> {
- let mut req_builder = X509ReqBuilder::new()?;
- req_builder.set_pubkey(key_pair)?;
- let mut x509_name = X509NameBuilder::new()?;
- x509_name.append_entry_by_text("C", "US")?;
- x509_name.append_entry_by_text("ST", "TX")?;
- x509_name.append_entry_by_text("O", "Some organization")?;
- x509_name.append_entry_by_text("CN", "www.example.com")?;
- let x509_name = x509_name.build();
- req_builder.set_subject_name(&x509_name)?;
- req_builder.sign(key_pair, MessageDigest::sha256())?;
- let req = req_builder.build();
- Ok(req)
- }
- /// Make a certificate and private key signed by the given CA cert and private key
- fn mk_ca_signed_cert(
- ca_cert: &X509Ref,
- ca_key_pair: &PKeyRef<Private>,
- ) -> Result<(X509, PKey<Private>), ErrorStack> {
- let rsa = Rsa::generate(2048)?;
- let key_pair = PKey::from_rsa(rsa)?;
- let req = mk_request(&key_pair)?;
- let mut cert_builder = X509::builder()?;
- cert_builder.set_version(2)?;
- let serial_number = {
- let mut serial = BigNum::new()?;
- serial.rand(159, MsbOption::MAYBE_ZERO, false)?;
- serial.to_asn1_integer()?
- };
- cert_builder.set_serial_number(&serial_number)?;
- cert_builder.set_subject_name(req.subject_name())?;
- cert_builder.set_issuer_name(ca_cert.subject_name())?;
- cert_builder.set_pubkey(&key_pair)?;
- let not_before = Asn1Time::days_from_now(0)?;
- cert_builder.set_not_before(¬_before)?;
- let not_after = Asn1Time::days_from_now(365)?;
- cert_builder.set_not_after(¬_after)?;
- cert_builder.append_extension(BasicConstraints::new().build()?)?;
- cert_builder.append_extension(
- KeyUsage::new()
- .critical()
- .non_repudiation()
- .digital_signature()
- .key_encipherment()
- .build()?,
- )?;
- let subject_key_identifier =
- SubjectKeyIdentifier::new().build(&cert_builder.x509v3_context(Some(ca_cert), None))?;
- cert_builder.append_extension(subject_key_identifier)?;
- let auth_key_identifier = AuthorityKeyIdentifier::new()
- .keyid(false)
- .issuer(false)
- .build(&cert_builder.x509v3_context(Some(ca_cert), None))?;
- cert_builder.append_extension(auth_key_identifier)?;
- let subject_alt_name = SubjectAlternativeName::new()
- .dns("*.example.com")
- .dns("hello.com")
- .build(&cert_builder.x509v3_context(Some(ca_cert), None))?;
- cert_builder.append_extension(subject_alt_name)?;
- cert_builder.sign(ca_key_pair, MessageDigest::sha256())?;
- let cert = cert_builder.build();
- Ok((cert, key_pair))
- }
- fn real_main() -> Result<(), ErrorStack> {
- let (ca_cert, ca_key_pair) = mk_ca_cert()?;
- let (cert, _key_pair) = mk_ca_signed_cert(&ca_cert, &ca_key_pair)?;
- // Verify that this cert was issued by this ca
- match ca_cert.issued(&cert) {
- X509VerifyResult::OK => println!("Certificate verified!"),
- ver_err => println!("Failed to verify certificate: {}", ver_err),
- };
- Ok(())
- }
- fn main() {
- match real_main() {
- Ok(()) => println!("Finished."),
- Err(e) => println!("Error: {}", e),
- };
- }
|