Find file
4063f1f Jun 16, 2013
97 lines (81 sloc) 3.83 KB
# This is not for the faint of heart.
# TODO: Add a ton of explanation here.
require "openssl"
# Generating the CA is a one time only operation. Once you have the private
# key and certificate files, you will reuse those for future signing
# operations
ca_passphrase = "verysecret"
ca_keypair ="/tmp/ca.pem", "w+") do |f|
f.write ca_keypair.to_pem("AES-128-CBC"), ca_passphrase)
ca_cert =
ca_cert.not_before =
ca_cert.subject =[
["C", "NO"],
["ST", "Oslo"],
["L", "Oslo"],
["CN", "August Lilleaas"]
ca_cert.issuer = ca_cert.subject
# All issued certs will be unusuable after this time.
ca_cert.not_after = + 1000000000 # 40 or so years
ca_cert.serial = 1
ca_cert.public_key = ca_keypair.public_key
ef =
ef.subject_certificate = ca_cert
ef.issuer_certificate = ca_cert
# Read more about the various extensions here:
ca_cert.add_extension(ef.create_extension("basicConstraints", "CA:TRUE", true))
ca_cert.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
ca_cert.add_extension(ef.create_extension("subjectKeyIdentifier", "hash", false))
ca_cert.add_extension(ef.create_extension("authorityKeyIdentifier", "keyid:always", false))
ca_cert.sign(ca_keypair,"/tmp/ca.crt", "w+") do |f|
f.write ca_cert.to_pem
# ... or if you've already generated the CA, open it
ca_keypair ="/tmp/ca.pem"), ca_passphrase)
ca_cert ="/tmp/ca.crt"))
# Signing a certificate with a CA is very similar to the steps above, since
# the only difference between a CA and a signed certificate is that the latter
# is, well, signed.
our_cert_keypair =
# Signing requests are what you deliver to a CA for signing. Usually, the CA
# and the requester isn't in the same process like in this demo. The signing
# request contains the public key and the metadata you want to have for your
# certificate.
our_cert_req =
our_cert_req.subject =[
["C", "NO"],
["ST", "Oslo"],
["L", "Oslo"],
["O", "August Lilleaas"],
["CN", "*"]
our_cert_req.public_key = our_cert_keypair.public_key
our_cert_req.sign our_cert_keypair,
# The CN (Common Name) is what browsers use to validate which domain names the
# certificate is valid for. If you aren't going to use the certificate for web
# servers, the contents of the CN field is of no technical significance. It's
# just metadata.
# At this point you typically save the our_cert_req.to_pem to a file, and send
# it to the CA. Since we're both the issuer and the requester, we'll do it inline
# right away for convenience, instead of via files.
our_cert =
our_cert.subject = our_cert_req.subject
our_cert.issuer = ca_cert.subject
our_cert.not_before =
our_cert.not_after = + 100000000 # 3 or so years.
our_cert.serial = 123 # Should be an unique number, the CA probably has a database.
our_cert.public_key = our_cert_req.public_key
# To make the certificate valid for both wildcard and top level domain name, we need an extension.
ef =
ef.subject_certificate = our_cert
ef.issuer_certificate = ca_cert
our_cert.add_extension(ef.create_extension("subjectAltName", ", DNS:*", false))
our_cert.sign ca_keypair,
# You now have a certificate signed by another certificate, in other words you
# created your own certificate authority. Congrats! Use our_cert.to_pem and write
# it to a file in order to ship it to the certificate requester.