Skip to content

Instantly share code, notes, and snippets.

@konklone
Forked from pzb/sample-chain1.txt
Last active June 29, 2019 13:07
Show Gist options
  • Save konklone/dca3321759e29f9f23a96a97ca3013cd to your computer and use it in GitHub Desktop.
Save konklone/dca3321759e29f9f23a96a97ca3013cd to your computer and use it in GitHub Desktop.
generate a self-signed root, issuing intermediate, and end entity certificate and private key
#!/usr/bin/env ruby
# Forked from https://gist.github.com/pzb/84f867ed5a330093cfbf
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'openssl'
# Set up Names and Keys for all the certs
ROOT = [["C", "US", OpenSSL::ASN1::PRINTABLESTRING],
["ST", "New York", OpenSSL::ASN1::PRINTABLESTRING],
["L", "Catskill", OpenSSL::ASN1::PRINTABLESTRING],
["O", "Honest Eric's Honest CA", OpenSSL::ASN1::PRINTABLESTRING],
["CN", "Honest Eric's Honest CA - R4", OpenSSL::ASN1::PRINTABLESTRING]]
root_key = OpenSSL::PKey::RSA.new(2048)
SUBORDINATE = [["O", "Dr. Eggman", OpenSSL::ASN1::PRINTABLESTRING],
["OU", "Internet Authority 1A", OpenSSL::ASN1::PRINTABLESTRING]]
subordinate_key = OpenSSL::PKey::RSA.new(2048)
# PrintableString does not include '*', so use a different DirectoryString
# RFC 5280 s. 4.1.2.6 says to use UTF8String
# ("MUST use PrintableString or UTF8String")
END_ENTITY = [["CN", "*.isitchristmas.com", OpenSSL::ASN1::UTF8STRING]]
END_ENTITY_SANS = "DNS:*.isitchristmas.com, DNS:isitchristmas.com"
end_entity_key = OpenSSL::PKey::RSA.new(2048)
# Generate all the certs
root_cert = OpenSSL::X509::Certificate.new
root_cert.version = 0x2
root_cert.serial = 0x0
root_cert.not_before = Time.new(2004,01,01,00,00,01)
root_cert.not_after = Time.new(2028,12,31,23,59,59)
root_cert.subject = OpenSSL::X509::Name.new(ROOT)
root_cert.issuer = root_cert.subject
root_cert.public_key = root_key.public_key
ef = OpenSSL::X509::ExtensionFactory.new
ef.subject_certificate = root_cert
ef.issuer_certificate = root_cert
root_cert.add_extension(ef.create_extension("subjectKeyIdentifier", "hash", false))
root_cert.add_extension(ef.create_extension("basicConstraints", "CA:TRUE", true))
# DigitalSignature is needed to sign OCSP responses (http://goo.gl/DExis9)
root_cert.add_extension(ef.create_extension("keyUsage","digitalSignature, keyCertSign, cRLSign", true))
root_cert.sign(root_key, OpenSSL::Digest::SHA256.new)
# puts "Bytes: #{root_cert.to_der.length}"
# puts root_cert.to_text
# puts root_cert.to_pem
# puts ""
issuer_cert = OpenSSL::X509::Certificate.new
issuer_cert.version = 0x2
issuer_cert.serial = 0xa
issuer_cert.not_before = Time.new(2011,01,01,00,00,01)
issuer_cert.not_after = Time.new(2020,12,31,23,59,59)
issuer_cert.subject = OpenSSL::X509::Name.new(SUBORDINATE)
issuer_cert.issuer = root_cert.subject
issuer_cert.public_key = subordinate_key.public_key
ef = OpenSSL::X509::ExtensionFactory.new
# The CPS URI is Optional
ef.config = OpenSSL::Config.parse('
[polsect]
policyIdentifier = 2.5.29.32.0
CPS.1="http://a.b.cd.com/cps"
')
ef.subject_certificate = issuer_cert
ef.issuer_certificate = root_cert
issuer_cert.add_extension(ef.create_extension("subjectKeyIdentifier", "hash", false))
issuer_cert.add_extension(ef.create_extension("authorityKeyIdentifier", "keyid:always", false))
issuer_cert.add_extension(ef.create_extension("basicConstraints", "CA:TRUE, pathlen:0", true))
# Baseline Requirements 9.3.3 have MAY or MUST for certificatePolicies
# depending on relationship between Root and Subordinate CA
issuer_cert.add_extension(ef.create_extension("certificatePolicies","@polsect"))
# DigitalSignature is needed to sign OCSP responses (http://goo.gl/DExis9)
issuer_cert.add_extension(ef.create_extension("keyUsage","digitalSignature, keyCertSign, cRLSign", true))
issuer_cert.add_extension(ef.create_extension("authorityInfoAccess","caIssuers;URI:http://a.b.cd.com/r4.cer,OCSP;URI:http://a.b.cd.com"))
issuer_cert.add_extension(ef.create_extension("crlDistributionPoints","URI:http://a.b.cd.com/r4.crl"))
issuer_cert.sign(root_key, OpenSSL::Digest::SHA256.new)
# puts "Bytes: #{issuer_cert.to_der.length}"
# puts issuer_cert.to_text
# puts issuer_cert.to_pem
# puts ""
ee_cert = OpenSSL::X509::Certificate.new
ee_cert.version = 0x2
ee_cert.serial = OpenSSL::BN.rand(64, -1, 0)
ee_cert.not_before = Time.new(2016,02,26,16,00,00)
ee_cert.not_after = Time.new(2017,02,28,15,59,59)
ee_cert.subject = OpenSSL::X509::Name.new(END_ENTITY)
ee_cert.issuer = issuer_cert.subject
ee_cert.public_key = end_entity_key.public_key
ef = OpenSSL::X509::ExtensionFactory.new
# The CPS URI is Optional
ef.config = OpenSSL::Config.parse('
[polsect]
policyIdentifier = 2.23.140.1.2.1
CPS.1="http://a.b.cd.com/cps"
')
ef.subject_certificate = ee_cert
ef.issuer_certificate = issuer_cert
# Python skips the first extension when trying to find the SAN
# extension, so ensure SAN is not the first extension
# http://bugs.python.org/issue13034
ee_cert.add_extension(ef.create_extension("authorityKeyIdentifier", "keyid:always", false))
ee_cert.add_extension(ef.create_extension("certificatePolicies","@polsect"))
ee_cert.add_extension(ef.create_extension("subjectAltName",END_ENTITY_SANS))
# RSA can be used for both Identification and Key Exchange, so two usages are needed
ee_cert.add_extension(ef.create_extension("keyUsage","digitalSignature,keyEncipherment", true))
ee_cert.add_extension(ef.create_extension("extendedKeyUsage", "serverAuth, clientAuth"))
ee_cert.add_extension(ef.create_extension("crlDistributionPoints","URI:http://a.b.cd.com/1a.crl"))
ee_cert.add_extension(ef.create_extension("authorityInfoAccess","caIssuers;URI:http://a.b.cd.com/1a.cer,OCSP;URI:http://a.b.cd.com"))
ee_cert.sign(subordinate_key, OpenSSL::Digest::SHA256.new)
# puts "Bytes: #{ee_cert.to_der.length}"
#puts ee_cert.to_text
puts ee_cert.to_pem
puts issuer_cert.to_pem
puts root_cert.to_pem
puts ""
puts end_entity_key.to_pem
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment