mk_certs.rs 5.4 KB

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