1 //! A program that generates ca certs, certs verified by the ca, and public
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}
;
10 use openssl
::x509
::extension
::{
11 AuthorityKeyIdentifier
, BasicConstraints
, KeyUsage
, SubjectAlternativeName
,
14 use openssl
::x509
::{X509NameBuilder, X509Ref, X509Req, X509ReqBuilder, X509VerifyResult, X509}
;
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
)?
;
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();
28 let mut cert_builder
= X509
::builder()?
;
29 cert_builder
.set_version(2)?
;
31 let mut serial
= BigNum
::new()?
;
32 serial
.rand(159, MsbOption
::MAYBE_ZERO
, false)?
;
33 serial
.to_asn1_integer()?
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(¬_before
)?
;
41 let not_after
= Asn1Time
::days_from_now(365)?
;
42 cert_builder
.set_not_after(¬_after
)?
;
44 cert_builder
.append_extension(BasicConstraints
::new().critical().ca().build()?
)?
;
45 cert_builder
.append_extension(
53 let subject_key_identifier
=
54 SubjectKeyIdentifier
::new().build(&cert_builder
.x509v3_context(None
, None
))?
;
55 cert_builder
.append_extension(subject_key_identifier
)?
;
57 cert_builder
.sign(&privkey
, MessageDigest
::sha256())?
;
58 let cert
= cert_builder
.build();
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
)?
;
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
)?
;
76 req_builder
.sign(&privkey
, MessageDigest
::sha256())?
;
77 let req
= req_builder
.build();
81 /// Make a certificate and private key signed by the given CA cert and private key
84 ca_privkey
: &PKeyRef
<Private
>,
85 ) -> Result
<(X509
, PKey
<Private
>), ErrorStack
> {
86 let rsa
= Rsa
::generate(2048)?
;
87 let privkey
= PKey
::from_rsa(rsa
)?
;
89 let req
= mk_request(&privkey
)?
;
91 let mut cert_builder
= X509
::builder()?
;
92 cert_builder
.set_version(2)?
;
94 let mut serial
= BigNum
::new()?
;
95 serial
.rand(159, MsbOption
::MAYBE_ZERO
, false)?
;
96 serial
.to_asn1_integer()?
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(¬_before
)?
;
104 let not_after
= Asn1Time
::days_from_now(365)?
;
105 cert_builder
.set_not_after(¬_after
)?
;
107 cert_builder
.append_extension(BasicConstraints
::new().build()?
)?
;
109 cert_builder
.append_extension(
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
)?
;
122 let auth_key_identifier
= AuthorityKeyIdentifier
::new()
125 .build(&cert_builder
.x509v3_context(Some(ca_cert
), None
))?
;
126 cert_builder
.append_extension(auth_key_identifier
)?
;
128 let subject_alt_name
= SubjectAlternativeName
::new()
129 .dns("*.example.com")
131 .build(&cert_builder
.x509v3_context(Some(ca_cert
), None
))?
;
132 cert_builder
.append_extension(subject_alt_name
)?
;
134 cert_builder
.sign(&ca_privkey
, MessageDigest
::sha256())?
;
135 let cert
= cert_builder
.build();
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
)?
;
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
),
155 Ok(()) => println
!("Finished."),
156 Err(e
) => println
!("Error: {}", e
),