]> git.proxmox.com Git - cargo.git/blob - vendor/openssl/examples/mk_certs.rs
New upstream version 0.52.0
[cargo.git] / vendor / openssl / examples / mk_certs.rs
1 //! A program that generates ca certs, certs verified by the ca, and public
2 //! and private keys.
3
4 use openssl::asn1::Asn1Time;
5 use openssl::bn::{BigNum, MsbOption};
6 use openssl::error::ErrorStack;
7 use openssl::hash::MessageDigest;
8 use openssl::pkey::{PKey, PKeyRef, Private};
9 use openssl::rsa::Rsa;
10 use openssl::x509::extension::{
11 AuthorityKeyIdentifier, BasicConstraints, KeyUsage, SubjectAlternativeName,
12 SubjectKeyIdentifier,
13 };
14 use openssl::x509::{X509NameBuilder, X509Ref, X509Req, X509ReqBuilder, X509VerifyResult, X509};
15
16 /// Make a CA certificate and private key
17 fn mk_ca_cert() -> Result<(X509, PKey<Private>), ErrorStack> {
18 let rsa = Rsa::generate(2048)?;
19 let privkey = PKey::from_rsa(rsa)?;
20
21 let mut x509_name = X509NameBuilder::new()?;
22 x509_name.append_entry_by_text("C", "US")?;
23 x509_name.append_entry_by_text("ST", "TX")?;
24 x509_name.append_entry_by_text("O", "Some CA organization")?;
25 x509_name.append_entry_by_text("CN", "ca test")?;
26 let x509_name = x509_name.build();
27
28 let mut cert_builder = X509::builder()?;
29 cert_builder.set_version(2)?;
30 let serial_number = {
31 let mut serial = BigNum::new()?;
32 serial.rand(159, MsbOption::MAYBE_ZERO, false)?;
33 serial.to_asn1_integer()?
34 };
35 cert_builder.set_serial_number(&serial_number)?;
36 cert_builder.set_subject_name(&x509_name)?;
37 cert_builder.set_issuer_name(&x509_name)?;
38 cert_builder.set_pubkey(&privkey)?;
39 let not_before = Asn1Time::days_from_now(0)?;
40 cert_builder.set_not_before(&not_before)?;
41 let not_after = Asn1Time::days_from_now(365)?;
42 cert_builder.set_not_after(&not_after)?;
43
44 cert_builder.append_extension(BasicConstraints::new().critical().ca().build()?)?;
45 cert_builder.append_extension(
46 KeyUsage::new()
47 .critical()
48 .key_cert_sign()
49 .crl_sign()
50 .build()?,
51 )?;
52
53 let subject_key_identifier =
54 SubjectKeyIdentifier::new().build(&cert_builder.x509v3_context(None, None))?;
55 cert_builder.append_extension(subject_key_identifier)?;
56
57 cert_builder.sign(&privkey, MessageDigest::sha256())?;
58 let cert = cert_builder.build();
59
60 Ok((cert, privkey))
61 }
62
63 /// Make a X509 request with the given private key
64 fn mk_request(privkey: &PKey<Private>) -> Result<X509Req, ErrorStack> {
65 let mut req_builder = X509ReqBuilder::new()?;
66 req_builder.set_pubkey(&privkey)?;
67
68 let mut x509_name = X509NameBuilder::new()?;
69 x509_name.append_entry_by_text("C", "US")?;
70 x509_name.append_entry_by_text("ST", "TX")?;
71 x509_name.append_entry_by_text("O", "Some organization")?;
72 x509_name.append_entry_by_text("CN", "www.example.com")?;
73 let x509_name = x509_name.build();
74 req_builder.set_subject_name(&x509_name)?;
75
76 req_builder.sign(&privkey, MessageDigest::sha256())?;
77 let req = req_builder.build();
78 Ok(req)
79 }
80
81 /// Make a certificate and private key signed by the given CA cert and private key
82 fn mk_ca_signed_cert(
83 ca_cert: &X509Ref,
84 ca_privkey: &PKeyRef<Private>,
85 ) -> Result<(X509, PKey<Private>), ErrorStack> {
86 let rsa = Rsa::generate(2048)?;
87 let privkey = PKey::from_rsa(rsa)?;
88
89 let req = mk_request(&privkey)?;
90
91 let mut cert_builder = X509::builder()?;
92 cert_builder.set_version(2)?;
93 let serial_number = {
94 let mut serial = BigNum::new()?;
95 serial.rand(159, MsbOption::MAYBE_ZERO, false)?;
96 serial.to_asn1_integer()?
97 };
98 cert_builder.set_serial_number(&serial_number)?;
99 cert_builder.set_subject_name(req.subject_name())?;
100 cert_builder.set_issuer_name(ca_cert.subject_name())?;
101 cert_builder.set_pubkey(&privkey)?;
102 let not_before = Asn1Time::days_from_now(0)?;
103 cert_builder.set_not_before(&not_before)?;
104 let not_after = Asn1Time::days_from_now(365)?;
105 cert_builder.set_not_after(&not_after)?;
106
107 cert_builder.append_extension(BasicConstraints::new().build()?)?;
108
109 cert_builder.append_extension(
110 KeyUsage::new()
111 .critical()
112 .non_repudiation()
113 .digital_signature()
114 .key_encipherment()
115 .build()?,
116 )?;
117
118 let subject_key_identifier =
119 SubjectKeyIdentifier::new().build(&cert_builder.x509v3_context(Some(ca_cert), None))?;
120 cert_builder.append_extension(subject_key_identifier)?;
121
122 let auth_key_identifier = AuthorityKeyIdentifier::new()
123 .keyid(false)
124 .issuer(false)
125 .build(&cert_builder.x509v3_context(Some(ca_cert), None))?;
126 cert_builder.append_extension(auth_key_identifier)?;
127
128 let subject_alt_name = SubjectAlternativeName::new()
129 .dns("*.example.com")
130 .dns("hello.com")
131 .build(&cert_builder.x509v3_context(Some(ca_cert), None))?;
132 cert_builder.append_extension(subject_alt_name)?;
133
134 cert_builder.sign(&ca_privkey, MessageDigest::sha256())?;
135 let cert = cert_builder.build();
136
137 Ok((cert, privkey))
138 }
139
140 fn real_main() -> Result<(), ErrorStack> {
141 let (ca_cert, ca_privkey) = mk_ca_cert()?;
142 let (cert, _privkey) = mk_ca_signed_cert(&ca_cert, &ca_privkey)?;
143
144 // Verify that this cert was issued by this ca
145 match ca_cert.issued(&cert) {
146 X509VerifyResult::OK => println!("Certificate verified!"),
147 ver_err => println!("Failed to verify certificate: {}", ver_err),
148 };
149
150 Ok(())
151 }
152
153 fn main() {
154 match real_main() {
155 Ok(()) => println!("Finished."),
156 Err(e) => println!("Error: {}", e),
157 };
158 }