R509
r509 is a Ruby gem built using OpenSSL that simplifies management of a public key infrastructure. The r509 API helps with CSR creation, signing/parsing of certificates, revocation (CRL/OCSP), and much more. Along with projects like r509-ocsp-responder & r509-ca-http it is a (RFC 5280) certificate authority suitable for production environments.
Install / Use
/learn @r509/R509README
r509

r509 is a Ruby gem built using OpenSSL that is designed to ease management of a public key infrastructure. The r509 API facilitates easy creation of CSRs, signing of certificates, revocation (CRL/OCSP), and much more. Together with projects like r509-ocsp-responder and r509-ca-http it is intended to be a complete RFC 5280-compliant certificate authority for use in production environments.
Why?
Certificates are hard, and the Ruby OpenSSL APIs aren't easy to use (because they hew closely to OpenSSL itself). Additionally, as SSL/TLS has aged a variety of best practices and workarounds around certificate issuance have grown up around it that are not easy to discover. r509 is an attempt to build a straightforward API that allows you to do things as simple as parsing a certificate all the way up to operating an entire certificate authority.
Requirements
r509 requires Ruby 2.0.0+ compiled with OpenSSL and YAML support (this is a typical default). It is recommended that you compile Ruby against OpenSSL 1.0.1+ (with elliptic curve support enabled). Red Hat-derived distributions prior to RHEL/CentOS 6.5 ship with EC disabled in OpenSSL, so if you need EC support you will need to recompile.
Installation
You can install via rubygems with gem install r509
To install the gem from your own clone (you will need to satisfy the dependencies via bundle install or other means):
rake gem:build
rake gem:install
Documentation
There is 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.
Changelog
1.0.1
- Support Rubies compiled against OpenSSL 1.1.0.
Support
You can file bugs to get support from the community.
Running Tests/Building Gem
If you want to run the tests for r509 you'll need rspec. Additionally, you should install simplecov 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 2.2, 2.3, and 2.4. 1.8.7 is no longer a supported configuration due to issues with its elliptic curve methods. 0.8.1 was the last official r509 release with 1.8.7 support.
Executables
r509 ships with a binary named r509 that can generate CSRs, keys, and create self-signed certificates. Type r509 -h to see a list of options.
Basic Certificate Authority Tutorial
This guide provides instructions on building a basic CA using r509, r509-ca-http, and r509-ocsp-responder. In it you will learn how to create a root, set up the configuration profiles, issue certificates, revoke certificates, and see responses from an OCSP responder.
Quick Start
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']
]
)
# alternately
csr = R509::CSR.new(
:subject => {
:CN => 'somedomain.com',
:O => 'My Org',
:L => 'City',
:ST => 'State',
:C => 'US'
}
)
Another way to build the subject:
subject = R509::Subject.new
subject.CN="somedomain.com"
subject.O="My Org"
subject.L="City"
subject.ST="State"
subject.C="US"
csr = R509::CSR.new( :subject => subject )
To load an existing CSR (without private key)
csr_pem = File.read("/path/to/csr")
csr = R509::CSR.new(:csr => csr_pem)
# or
csr = R509::CSR.load_from_file("/path/to/csr")
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)
# or
cert = R509::Cert.load_from_file("/path/to/cert")
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"
)
PrivateKey
Generate a 1536-bit RSA key
key = R509::PrivateKey.new(:type => "RSA", :bit_length => 1536)
Encrypt a private key
key = R509::PrivateKey.new(:type => "RSA", :bit_length => 2048)
encrypted_pem = key.to_encrypted_pem("aes256","my-password")
# or write it to disk
key.write_encrypted_pem("/tmp/path","aes256","my-password")
Load Hardware Engines in PrivateKey
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.
engine = R509::Engine.instance.load(:so_path => "/usr/lib64/openssl/engines/libchil.so", :id => "chil")
key = R509::PrivateKey(
:engine => engine,
:key_name => "my_key_name"
)
You can then use this key for signing.
SPKI/SPKAC
To generate a 2048-bit RSA SPKI
key = R509::PrivateKey.new(:type => "RSA", :bit_length => 1024)
spki = R509::SPKI.new(:key => key)
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']]
)
# if you do not pass :extensions it will add basic constraints CA:TRUE, a SubjectKeyIdentifier, and an AuthorityKeyIdentifier
cert = R509::CertificateAuthority::Signer.selfsign(
:csr => csr,
:not_before => not_before,
:not_after => not_after
)
Config
CAConfig
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
)
SubjectItemPolicy
Subject Item Policy allows you to define what subject fields are allowed in a certificate. Required means that field must be supplied, optional means it will be encoded if provided, and match means the field must be present and must match the value specified. The keys must match OpenSSL's short names.
sip = 509::Config::SubjectItemPolicy.new(
"CN" => {:policy => "required"},
"O" => {:policy => "optional"},
"OU" => {:policy => "match", :value => "Engineering" }
)
CertProfile
Certificate profiles hold extensions you want to put in a certificate, allowed/default message digests, and subject item policies. You can build them programmatically or load them via YAML. When building programmatically you can also serialize to YAML for future use. This is the preferred way to build the YAML.
The CertProfile object can either take objects or the hash that would build those objects.
Objects:
profile = R509::Config::CertProfile.new(
:basic_constraints => R509::Cert::Extensions::BasicConstraints.new(
:ca => false
),
:key_usage => R509::Cert::Extensions::KeyUsage.new(
:value => ['digitalSignature','keyEncipherment']
),
:extended_key_usage => R509::Cert::Extensions::ExtendedKeyUsage.new(
:value => ['serverAuth','clientAuth']
),
:authority_info_access => R509::Cert::Extensions::AuthorityInfoAccess.new(
:ocsp_location => [{:type => 'URI', :value => 'http://ocsp.myca.net'}]
),
:certificate_policies => R509::Cert::Extensions::CertificatePolicies.new(
:value => [{:policy_identifier => '1.23.3.4.4.5.56'}]
),
:crl_distribution_points => R509::Cert::Extensions::CRLDistributionPoints.new(
:value => [{:type => 'URI', :value => 'http://crl.myca.net/ca.crl'}]
),
:inhibit_any_policy => R509::Cert::Extensions::InhibitAnyPolicy.new(
:value => 0
),
:name_constraints => R509::Cert::Extensions::NameConstraints.new(
:permitted => [{:type => 'dirName', :value => { :CN => 'test' } }]
),
:ocsp_no_check => R509::Cert::Extensions::OCSPNoCheck.new(:value => true),
:policy_constraints => R509::Cert::Extensions::PolicyConstraints.new(
:require_explicit_policy=> 1
),
:subject_item_policy => R509::Config::SubjectItemPolicy.new(
"CN" => {:policy => "required"},
"O" => {:policy => "optional"},
"OU" => {:policy => "match", :value => "Engineering" }
),
:default_md => "SHA256",
:allowed_mds => ["SHA256","SHA512"]
)
Hashes:
profile = R509::Config::CertProfile.new(
:basic_constraints => {:ca => false},
:key_usage => { :value => ["digitalSignature","keyEncipherment"] },
:extended_key_usage => { :value => ["serverAuth"] },
:certificate_policies => [
{ :policy_identifier => "2.16.840.1.99999.21.234",
:cps_uris => ["http://example.com/cps","http://haha.com"],
:user_notices => [ { :explicit_text => "this is a great thing", :organization => "my org", :notice_numbers => [1,2,3] } ]
}
],
:subject
Related Skills
tmux
342.0kRemote-control tmux sessions for interactive CLIs by sending keystrokes and scraping pane output.
blogwatcher
342.0kMonitor blogs and RSS/Atom feeds for updates using the blogwatcher CLI.
product
Cloud-agnostic Kubernetes infrastructure with Terraform & Helm for homelabs, edge, and production clusters.
Unla
2.1k🧩 MCP Gateway - A lightweight gateway service that instantly transforms existing MCP Servers and APIs into MCP servers with zero code changes. Features Docker deployment and management UI, requiring no infrastructure modifications.
