SkillAgentSearch skills...

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/R509
About this skill

Quality Score

0/100

Category

Operations

Supported Platforms

Universal

README

r509 Build Status Coverage Status

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

View on GitHub
GitHub Stars128
CategoryOperations
Updated6mo ago
Forks40

Languages

Ruby

Security Score

72/100

Audited on Sep 6, 2025

No findings