r509
r509 is a wrapper for various OpenSSL functions to allow easy creation of CSRs, signing of certificates, and revocation via CRL.
Requirements/Installation
r509 requires the Ruby OpenSSL bindings as well as yaml support (present by default in modern Ruby builds).
To install the gem: gem install r509-(version).gem
Running Tests/Building Gem
If you want to run the tests for r509 you'll need rspec. Additionally, you may want to install rcov/simplecov (ruby 1.8/1.9 respectively) and yard for running the code coverage and documentation tasks in the Rakefile. rake -T for a complete list of rake tasks available.
Continuous Integration
We run continuous integration tests (using Travis-CI) against 1.8.7, 1.9.2, 1.9.3, ree, and ruby-head.
Executable
Inside the gem there is a bin directory that contains r509. You can use this in interactive mode to generate a CSR and (optionally) self-sign it.
Usage
CSR
To generate a 2048-bit RSA CSR
csr = R509::Csr.new( :subject => [ ['CN','somedomain.com'], ['O','My Org'], ['L','City'], ['ST','State'], ['C','US'] ] )
To load an existing CSR (without private key)
csr_pem = File.read("/path/to/csr") csr = R509::Csr.new(:csr => csr_pem)
To create a new CSR from the subject of a certificate
cert_pem = File.read("/path/to/cert") csr = R509::Csr.new(:cert => cert_pem)
To create a CSR with SAN names
csr = R509::Csr.new( :subject => [['CN','something.com']], :san_names => ["something2.com","something3.com"] )
Cert
To load an existing certificate
cert_pem = File.read("/path/to/cert") cert = R509::Cert.new(:cert => cert_pem)
Load a cert and key
cert_pem = File.read("/path/to/cert") key_pem = File.read("/path/to/key") cert = R509::Cert.new( :cert => cert_pem, :key => key_pem )
Load an encrypted private key
cert_pem = File.read("/path/to/cert") key_pem = File.read("/path/to/key") cert = R509::Cert.new( :cert => cert_pem, :key => key_pem, :password => "private_key_password" )
Load a PKCS12 file
pkcs12_der = File.read("/path/to/p12") cert = R509::Cert.new( :pkcs12 => pkcs12_der, :password => "password" )
Self-Signed Certificate
To create a self-signed certificate
not_before = Time.now.to_i not_after = Time.now.to_i+3600*24*7300 csr = R509::Csr.new( :subject => [['C','US'],['O','r509 LLC'],['CN','r509 Self-Signed CA Test']] ) ca = R509::CertificateAuthority::Signer.new cert = ca.selfsign( :csr => csr, :not_before => not_before, :not_after => not_after )
Config
Create a basic CaConfig object
cert_pem = File.read("/path/to/cert") key_pem = File.read("/path/to/key") cert = R509::Cert.new( :cert => cert_pem, :key => key_pem ) config = R509::Config::CaConfig.new( :ca_cert => cert )
Add a signing profile named "server" (CaProfile) to a config object
profile = R509::Config::CaProfile.new( :basic_constraints => "CA:FALSE", :key_usage => ["digitalSignature","keyEncipherment"], :extended_key_usage => ["serverAuth"], :certificate_policies => [ ["policyIdentifier=2.16.840.1.999999999.1.2.3.4.1", "CPS.1=http://example.com/cps"] ], :subject_item_policy => nil ) # config object from above assumed config.set_profile("server",profile)
Set up a subject item policy (required/optional). The keys must match OpenSSL's shortnames!
profile = R509::Config::CaProfile.new( :basic_constraints => "CA:FALSE", :key_usage => ["digitalSignature","keyEncipherment"], :extended_key_usage => ["serverAuth"], :certificate_policies => [ ["policyIdentifier=2.16.840.1.999999999.1.2.3.4.1", "CPS.1=http://example.com/cps"] ], :subject_item_policy => { "CN" => "required", "O" => "optional" } ) # config object from above assumed config.set_profile("server",profile)
Load CaConfig + Profile from YAML
config = R509::Config::CaConfig.from_yaml("test_ca", "config_test.yaml")
Example YAML (more options are supported than this example)
test_ca: {
ca_cert: {
cert: '/path/to/test_ca.cer',
key: '/path/to/test_ca.key'
},
crl_list: "crl_list_file.txt",
crl_number: "crl_number_file.txt",
cdp_location: 'URI:http://crl.domain.com/test_ca.crl',
crl_validity_hours: 168, #7 days
ocsp_location: 'URI:http://ocsp.domain.com',
message_digest: 'SHA1', #SHA1, SHA256, SHA512 supported. MD5 too, but you really shouldn't use that unless you have a good reason
profiles: {
server: {
basic_constraints: "CA:FALSE",
key_usage: [digitalSignature,keyEncipherment],
extended_key_usage: [serverAuth],
certificate_policies: [ [ "policyIdentifier=2.16.840.1.9999999999.1.2.3.4.1", "CPS.1=http://example.com/cps"] ],
subject_item_policy: {
"CN" : "required",
"O" : "optional",
"ST" : "required",
"C" : "required",
"OU" : "optional" }
}
}
}
Load multiple CaConfigs using a CaConfigPool
pool = R509::Config::CaConfigPool.from_yaml("certificate_authorities", "config_pool.yaml")
Example (Minimal) Config Pool YAML
certificate_authorities: {
test_ca: {
ca_cert: {
cert: 'test_ca.cer',
key: 'test_ca.key'
}
},
second_ca: {
ca_cert: {
cert: 'second_ca.cer',
key: 'second_ca.key'
}
}
}
CertificateAuthority
Sign a CSR
csr = R509::Csr.new( :subject => [ ['CN','somedomain.com'], ['O','My Org'], ['L','City'], ['ST','State'], ['C','US'] ] ) # assume config from yaml load above ca = R509::CertificateAuthority::Signer.new(config) cert = ca.sign( :profile_name => "server", :csr => csr )
Override a CSR's subject or SAN names when signing
csr = R509::Csr.new( :subject => [ ['CN','somedomain.com'], ['O','My Org'], ['L','City'], ['ST','State'], ['C','US'] ] ) data_hash = csr.to_hash data_hash[:san_names] = ["sannames.com","domain2.com"] data_hash[:subject]["CN"] = "newdomain.com" data_hash[:subejct]["O"] = "Org 2.0" # assume config from yaml load above ca = R509::CertificateAuthority::Signer.new(config) cert = ca.sign( :profile_name => "server", :csr => csr, :data_hash => data_hash )
Load Hardware Engines
The engine you want to load must already be available to OpenSSL. How to compile/install OpenSSL engines is outside the scope of this document.
OpenSSL::Engine.load("engine_name") engine = OpenSSL::Engine.by_id("engine_name") key = R509::PrivateKey( :engine => engine, :key_name => "my_key_name" )
You can then use this key for signing.
OID Mapping
Register one
R509::OidMapper.register("1.3.5.6.7.8.3.23.3","short_name","optional_long_name")
Register in batch
R509::OidMapper.batch_register([ {:oid => "1.3.5.6.7.8.3.23.3", :short_name => "short_name", :long_name => "optional_long_name"}, {:oid => "1.3.5.6.7.8.3.23.5", :short_name => "another_name"} ])
Documentation
There is (relatively) complete documentation available for every method and class in r509 available via yardoc. If you installed via gem it should be pre-generated in the doc directory. If you cloned this repo, just type rake yard with the yard gem installed. You will also need the redcarpet and github-markup gems to properly parse the Readme.md.
Thanks to...
License
See the LICENSE file. Licensed under the Apache 2.0 License