r509 0.8.1 → 0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +343 -151
- data/Rakefile +26 -23
- data/bin/r509 +126 -112
- data/bin/r509-parse +24 -24
- data/doc/R509.html +169 -7
- data/doc/R509/ASN1.html +370 -0
- data/doc/R509/ASN1/GeneralName.html +1121 -0
- data/doc/R509/ASN1/GeneralNames.html +843 -0
- data/doc/R509/ASN1/NoticeReference.html +392 -0
- data/doc/R509/ASN1/PolicyInformation.html +387 -0
- data/doc/R509/ASN1/PolicyQualifiers.html +455 -0
- data/doc/R509/ASN1/UserNotice.html +386 -0
- data/doc/R509/{Crl.html → CRL.html} +7 -7
- data/doc/R509/CRL/Administrator.html +1559 -0
- data/doc/R509/{Crl/Parser.html → CRL/SignedList.html} +501 -210
- data/doc/R509/{Csr.html → CSR.html} +444 -314
- data/doc/R509/Cert.html +866 -617
- data/doc/R509/Cert/Extensions.html +52 -41
- data/doc/R509/Cert/Extensions/AuthorityInfoAccess.html +70 -35
- data/doc/R509/Cert/Extensions/AuthorityKeyIdentifier.html +387 -4
- data/doc/R509/Cert/Extensions/BasicConstraints.html +61 -25
- data/doc/R509/Cert/Extensions/CRLDistributionPoints.html +354 -0
- data/doc/R509/Cert/Extensions/CertificatePolicies.html +340 -0
- data/doc/R509/Cert/Extensions/ExtendedKeyUsage.html +440 -49
- data/doc/R509/Cert/Extensions/{CrlDistributionPoints.html → InhibitAnyPolicy.html} +52 -35
- data/doc/R509/Cert/Extensions/KeyUsage.html +247 -121
- data/doc/R509/Cert/Extensions/NameConstraints.html +445 -0
- data/doc/R509/Cert/Extensions/OCSPNoCheck.html +239 -0
- data/doc/R509/Cert/Extensions/PolicyConstraints.html +424 -0
- data/doc/R509/Cert/Extensions/SubjectAlternativeName.html +437 -62
- data/doc/R509/Cert/Extensions/SubjectKeyIdentifier.html +52 -10
- data/doc/R509/CertificateAuthority.html +4 -4
- data/doc/R509/CertificateAuthority/Signer.html +154 -187
- data/doc/R509/Config.html +6 -6
- data/doc/R509/Config/{CaConfig.html → CAConfig.html} +451 -348
- data/doc/R509/Config/{CaConfigPool.html → CAConfigPool.html} +47 -47
- data/doc/R509/Config/CAProfile.html +1015 -0
- data/doc/R509/Config/SubjectItemPolicy.html +86 -86
- data/doc/R509/IOHelpers.html +22 -22
- data/doc/R509/MessageDigest.html +14 -14
- data/doc/R509/NameSanitizer.html +53 -53
- data/doc/R509/{Ocsp.html → OCSP.html} +9 -9
- data/doc/R509/{Ocsp → OCSP}/Request.html +7 -7
- data/doc/R509/{Ocsp → OCSP}/Request/Nonce.html +56 -11
- data/doc/R509/{Ocsp → OCSP}/Response.html +44 -44
- data/doc/R509/{OidMapper.html → OIDMapper.html} +23 -39
- data/doc/R509/PrivateKey.html +415 -168
- data/doc/R509/R509Error.html +3 -3
- data/doc/R509/{Spki.html → SPKI.html} +354 -192
- data/doc/R509/Subject.html +224 -113
- data/doc/R509/Validity.html +27 -5
- data/doc/R509/Validity/Checker.html +13 -13
- data/doc/R509/Validity/DefaultChecker.html +13 -13
- data/doc/R509/Validity/DefaultWriter.html +14 -14
- data/doc/R509/Validity/Status.html +39 -39
- data/doc/R509/Validity/Writer.html +18 -18
- data/doc/_index.html +138 -35
- data/doc/class_list.html +1 -1
- data/doc/css/style.css +10 -0
- data/doc/file.README.html +368 -171
- data/doc/file.r509.html +92 -69
- data/doc/frames.html +1 -1
- data/doc/index.html +368 -171
- data/doc/method_list.html +910 -390
- data/doc/top-level-namespace.html +3 -3
- data/lib/r509.rb +32 -16
- data/lib/r509/asn1.rb +375 -0
- data/lib/r509/cert.rb +381 -364
- data/lib/r509/cert/extensions.rb +443 -76
- data/lib/r509/certificate_authority.rb +407 -0
- data/lib/r509/config.rb +547 -351
- data/lib/r509/crl.rb +336 -366
- data/lib/r509/csr.rb +278 -289
- data/lib/r509/ec-hack.rb +37 -0
- data/lib/r509/exceptions.rb +3 -3
- data/lib/r509/io_helpers.rb +44 -44
- data/lib/r509/message_digest.rb +53 -0
- data/lib/r509/ocsp.rb +80 -70
- data/lib/r509/oid_mapper.rb +32 -0
- data/lib/r509/private_key.rb +228 -0
- data/lib/r509/spki.rb +145 -93
- data/lib/r509/subject.rb +203 -110
- data/lib/r509/validity.rb +70 -68
- data/lib/r509/version.rb +2 -2
- data/r509.yaml +92 -69
- data/spec/asn1_spec.rb +402 -0
- data/spec/cert/extensions_spec.rb +957 -494
- data/spec/cert_spec.rb +382 -307
- data/spec/certificate_authority_spec.rb +668 -250
- data/spec/config_spec.rb +515 -302
- data/spec/crl_spec.rb +197 -198
- data/spec/csr_spec.rb +334 -289
- data/spec/fixtures.rb +247 -171
- data/spec/fixtures/cert1.der +0 -0
- data/spec/fixtures/cert1.pem +0 -0
- data/spec/fixtures/cert1_public_key_modulus.txt +0 -0
- data/spec/fixtures/cert3.p12 +0 -0
- data/spec/fixtures/cert3.pem +0 -0
- data/spec/fixtures/cert3_key.pem +0 -0
- data/spec/fixtures/cert3_key_des3.pem +0 -0
- data/spec/fixtures/cert4.pem +0 -0
- data/spec/fixtures/cert5.pem +0 -0
- data/spec/fixtures/cert6.pem +0 -0
- data/spec/fixtures/cert_expired.pem +0 -0
- data/spec/fixtures/cert_inhibit.pem +24 -0
- data/spec/fixtures/cert_name_constraints.pem +29 -0
- data/spec/fixtures/cert_not_yet_valid.pem +0 -0
- data/spec/fixtures/cert_ocsp_no_check.pem +18 -0
- data/spec/fixtures/cert_policy_constraints.pem +31 -0
- data/spec/fixtures/cert_san.pem +0 -0
- data/spec/fixtures/cert_san2.pem +0 -0
- data/spec/fixtures/cert_unknown_extension.pem +28 -0
- data/spec/fixtures/config_pool_test_minimal.yaml +11 -11
- data/spec/fixtures/config_test.yaml +54 -36
- data/spec/fixtures/config_test_dsa.yaml +35 -0
- data/spec/fixtures/config_test_ec.yaml +35 -0
- data/spec/fixtures/config_test_engine_key.yaml +5 -5
- data/spec/fixtures/config_test_engine_no_key_name.yaml +4 -4
- data/spec/fixtures/config_test_minimal.yaml +4 -4
- data/spec/fixtures/config_test_password.yaml +5 -5
- data/spec/fixtures/config_test_various.yaml +111 -74
- data/spec/fixtures/crl_list_file.txt +0 -0
- data/spec/fixtures/crl_with_reason.pem +0 -0
- data/spec/fixtures/csr1.der +0 -0
- data/spec/fixtures/csr1.pem +0 -0
- data/spec/fixtures/csr1_key.der +0 -0
- data/spec/fixtures/csr1_key.pem +0 -0
- data/spec/fixtures/csr1_key_encrypted_des3.pem +0 -0
- data/spec/fixtures/csr1_newlines.pem +0 -0
- data/spec/fixtures/csr1_no_begin_end.pem +0 -0
- data/spec/fixtures/csr1_public_key_modulus.txt +0 -0
- data/spec/fixtures/csr2.pem +0 -0
- data/spec/fixtures/csr2_key.pem +0 -0
- data/spec/fixtures/csr3.pem +0 -0
- data/spec/fixtures/csr4.pem +0 -0
- data/spec/fixtures/csr_dsa.pem +0 -0
- data/spec/fixtures/csr_invalid_signature.pem +0 -0
- data/spec/fixtures/dsa_key.pem +0 -0
- data/spec/fixtures/dsa_root.cer +28 -0
- data/spec/fixtures/dsa_root.key +20 -0
- data/spec/fixtures/ec_csr2.der +0 -0
- data/spec/fixtures/ec_csr2.pem +8 -0
- data/spec/fixtures/ec_key1.der +0 -0
- data/spec/fixtures/ec_key1.pem +6 -0
- data/spec/fixtures/ec_key1_encrypted.pem +9 -0
- data/spec/fixtures/ec_key2.pem +6 -0
- data/spec/fixtures/hmacsha1.sig +1 -0
- data/spec/fixtures/hmacsha512.sig +1 -0
- data/spec/fixtures/key4.pem +0 -0
- data/spec/fixtures/key4_encrypted_des3.pem +0 -0
- data/spec/fixtures/missing_key_identifier_ca.cer +0 -0
- data/spec/fixtures/missing_key_identifier_ca.key +0 -0
- data/spec/fixtures/ocsptest.r509.local.pem +0 -0
- data/spec/fixtures/ocsptest.r509.local_ocsp_request.der +0 -0
- data/spec/fixtures/ocsptest2.r509.local.pem +0 -0
- data/spec/fixtures/second_ca.cer +0 -0
- data/spec/fixtures/second_ca.key +0 -0
- data/spec/fixtures/spkac.der +0 -0
- data/spec/fixtures/spkac.txt +0 -0
- data/spec/fixtures/spkac_dsa.txt +1 -1
- data/spec/fixtures/spkac_dsa_no_verify.txt +1 -0
- data/spec/fixtures/spkac_ec.txt +1 -0
- data/spec/fixtures/spkac_rsa_newlines.txt +13 -0
- data/spec/fixtures/stca.pem +0 -0
- data/spec/fixtures/stca_ocsp_request.der +0 -0
- data/spec/fixtures/stca_ocsp_response.der +0 -0
- data/spec/fixtures/test1.csr +0 -0
- data/spec/fixtures/test_ca.cer +0 -0
- data/spec/fixtures/test_ca.key +0 -0
- data/spec/fixtures/test_ca.p12 +0 -0
- data/spec/fixtures/test_ca_des3.key +0 -0
- data/spec/fixtures/test_ca_ec.cer +14 -0
- data/spec/fixtures/test_ca_ec.key +6 -0
- data/spec/fixtures/test_ca_ec_ee.cer +22 -0
- data/spec/fixtures/test_ca_ec_ee.key +6 -0
- data/spec/fixtures/test_ca_ocsp.cer +0 -0
- data/spec/fixtures/test_ca_ocsp.key +0 -0
- data/spec/fixtures/test_ca_ocsp.p12 +0 -0
- data/spec/fixtures/test_ca_ocsp_chain.txt +0 -0
- data/spec/fixtures/test_ca_ocsp_response.der +0 -0
- data/spec/fixtures/test_ca_subroot.cer +0 -0
- data/spec/fixtures/test_ca_subroot.key +0 -0
- data/spec/fixtures/test_ca_subroot_ocsp.cer +0 -0
- data/spec/fixtures/test_ca_subroot_ocsp.key +0 -0
- data/spec/fixtures/test_ca_subroot_ocsp_response.der +0 -0
- data/spec/fixtures/unknown_oid.csr +0 -0
- data/spec/message_digest_spec.rb +104 -84
- data/spec/ocsp_spec.rb +105 -105
- data/spec/oid_mapper_spec.rb +21 -21
- data/spec/private_key_spec.rb +275 -0
- data/spec/r509_spec.rb +35 -0
- data/spec/spec_helper.rb +15 -6
- data/spec/spki_spec.rb +221 -142
- data/spec/subject_spec.rb +232 -164
- data/spec/validity_spec.rb +91 -91
- metadata +79 -25
- data/doc/R509/Config/CaProfile.html +0 -651
- data/doc/R509/Crl/Administrator.html +0 -2073
- data/lib/r509/certificateauthority.rb +0 -290
- data/lib/r509/messagedigest.rb +0 -49
- data/lib/r509/oidmapper.rb +0 -32
- data/lib/r509/privatekey.rb +0 -185
- data/spec/privatekey_spec.rb +0 -198
data/README.md
CHANGED
@@ -1,59 +1,83 @@
|
|
1
1
|
#r509 [![Build Status](https://secure.travis-ci.org/reaperhulk/r509.png)](http://travis-ci.org/reaperhulk/r509)
|
2
|
-
r509 is a
|
2
|
+
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](https://github.com/reaperhulk/r509-ocsp-responder) and [r509-ca-http](https://github.com/sirsean/r509-ca-http) it is intended to be a complete [RFC 5280](http://www.ietf.org/rfc/rfc5280.txt)-compliant certificate authority for use in production environments.
|
3
3
|
|
4
|
-
##Requirements
|
4
|
+
##Requirements
|
5
5
|
|
6
|
-
r509 requires the Ruby OpenSSL bindings as well as yaml support (present by default in modern Ruby builds).
|
7
|
-
|
6
|
+
r509 requires the Ruby OpenSSL bindings as well as yaml support (present by default in modern Ruby builds). It is recommended that you compile Ruby against OpenSSL 1.0.0+ (with elliptic curve support enabled). Red Hat-derived distributions ship with EC disabled in OpenSSL, so if you need EC support you will need to recompile.
|
7
|
+
|
8
|
+
##Installation
|
9
|
+
You can install via rubygems with ```gem install r509```
|
10
|
+
|
11
|
+
To install the gem from your own clone (you will need to satisfy the dependencies via ```bundle install``` or other means):
|
12
|
+
|
13
|
+
```bash
|
14
|
+
rake gem:build
|
15
|
+
rake gem:install
|
16
|
+
```
|
8
17
|
|
9
18
|
##Running Tests/Building Gem
|
10
19
|
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.
|
11
20
|
|
12
21
|
##Continuous Integration
|
13
|
-
We run continuous integration tests (using Travis-CI) against 1.
|
22
|
+
We run continuous integration tests (using Travis-CI) against 1.9.3, 2.0.0, ruby-head, and rubinius(rbx) 2.0 in 1.9 mode. 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.
|
14
23
|
|
15
24
|
##Executable
|
16
25
|
|
17
|
-
Inside the gem there is a
|
26
|
+
Inside the gem there is a binary named ```r509```. Type ```r509 -h``` to see a list of options.
|
27
|
+
|
28
|
+
##Basic Certificate Authority Howto
|
29
|
+
[This guide](http://langui.sh/2012/11/02/building-a-ca-r509-howto/) provides instructions on building a basic CA using r509, [r509-ca-http](https://github.com/sirsean/r509-ca-http), and [r509-ocsp-responder](https://github.com/reaperhulk/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.
|
18
30
|
|
19
31
|
##Usage
|
20
32
|
###CSR
|
21
33
|
To generate a 2048-bit RSA CSR
|
22
34
|
|
23
35
|
```ruby
|
24
|
-
csr = R509::
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
36
|
+
csr = R509::CSR.new(
|
37
|
+
:subject => [
|
38
|
+
['CN','somedomain.com'],
|
39
|
+
['O','My Org'],
|
40
|
+
['L','City'],
|
41
|
+
['ST','State'],
|
42
|
+
['C','US']
|
43
|
+
]
|
32
44
|
)
|
33
45
|
```
|
34
46
|
|
47
|
+
Another way to build the subject:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
subject = R509::Subject.new
|
51
|
+
subject.CN="somedomain.com"
|
52
|
+
subject.O="My Org"
|
53
|
+
subject.L="City"
|
54
|
+
subject.ST="State"
|
55
|
+
subject.C="US"
|
56
|
+
csr = R509::CSR.new( :subject => subject )
|
57
|
+
```
|
58
|
+
|
35
59
|
To load an existing CSR (without private key)
|
36
60
|
|
37
61
|
```ruby
|
38
62
|
csr_pem = File.read("/path/to/csr")
|
39
|
-
csr = R509::
|
63
|
+
csr = R509::CSR.new(:csr => csr_pem)
|
40
64
|
# or
|
41
|
-
csr = R509::
|
65
|
+
csr = R509::CSR.load_from_file("/path/to/csr")
|
42
66
|
```
|
43
67
|
|
44
68
|
To create a new CSR from the subject of a certificate
|
45
69
|
|
46
70
|
```ruby
|
47
71
|
cert_pem = File.read("/path/to/cert")
|
48
|
-
csr = R509::
|
72
|
+
csr = R509::CSR.new(:cert => cert_pem)
|
49
73
|
```
|
50
74
|
|
51
75
|
To create a CSR with SAN names
|
52
76
|
|
53
77
|
```ruby
|
54
|
-
csr = R509::
|
55
|
-
|
56
|
-
|
78
|
+
csr = R509::CSR.new(
|
79
|
+
:subject => [['CN','something.com']],
|
80
|
+
:san_names => ["something2.com","something3.com"]
|
57
81
|
)
|
58
82
|
```
|
59
83
|
|
@@ -73,8 +97,8 @@ Load a cert and key
|
|
73
97
|
cert_pem = File.read("/path/to/cert")
|
74
98
|
key_pem = File.read("/path/to/key")
|
75
99
|
cert = R509::Cert.new(
|
76
|
-
|
77
|
-
|
100
|
+
:cert => cert_pem,
|
101
|
+
:key => key_pem
|
78
102
|
)
|
79
103
|
```
|
80
104
|
|
@@ -84,9 +108,9 @@ Load an encrypted private key
|
|
84
108
|
cert_pem = File.read("/path/to/cert")
|
85
109
|
key_pem = File.read("/path/to/key")
|
86
110
|
cert = R509::Cert.new(
|
87
|
-
|
88
|
-
|
89
|
-
|
111
|
+
:cert => cert_pem,
|
112
|
+
:key => key_pem,
|
113
|
+
:password => "private_key_password"
|
90
114
|
)
|
91
115
|
```
|
92
116
|
|
@@ -95,53 +119,98 @@ Load a PKCS12 file
|
|
95
119
|
```ruby
|
96
120
|
pkcs12_der = File.read("/path/to/p12")
|
97
121
|
cert = R509::Cert.new(
|
98
|
-
|
99
|
-
|
122
|
+
:pkcs12 => pkcs12_der,
|
123
|
+
:password => "password"
|
100
124
|
)
|
101
125
|
```
|
102
126
|
|
127
|
+
###PrivateKey
|
128
|
+
Generate a 1536-bit RSA key
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
key = R509::PrivateKey.new(:type => :rsa, :bit_strength => 1536)
|
132
|
+
```
|
133
|
+
|
134
|
+
Encrypt the private key
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
key = R509::PrivateKey.new(:type => :rsa, :bit_strength => 2048)
|
138
|
+
encrypted_pem = key.to_encrypted_pem("aes256","my-password")
|
139
|
+
# or write it to disk
|
140
|
+
key.write_encrypted_pem("/tmp/path","aes256","my-password")
|
141
|
+
```
|
142
|
+
|
143
|
+
####Load Hardware Engines in PrivateKey
|
144
|
+
|
145
|
+
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.
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
OpenSSL::Engine.load("engine_name")
|
149
|
+
engine = OpenSSL::Engine.by_id("engine_name")
|
150
|
+
key = R509::PrivateKey(
|
151
|
+
:engine => engine,
|
152
|
+
:key_name => "my_key_name"
|
153
|
+
)
|
154
|
+
```
|
155
|
+
|
156
|
+
You can then use this key for signing.
|
157
|
+
|
158
|
+
###SPKI/SPKAC
|
159
|
+
To generate a 2048-bit RSA SPKI
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
key = R509::PrivateKey.new(:type => :rsa, :bit_strength => 1024)
|
163
|
+
spki = R509::SPKI.new(:key => key)
|
164
|
+
```
|
165
|
+
|
103
166
|
###Self-Signed Certificate
|
104
167
|
To create a self-signed certificate
|
105
168
|
|
106
169
|
```ruby
|
107
170
|
not_before = Time.now.to_i
|
108
171
|
not_after = Time.now.to_i+3600*24*7300
|
109
|
-
csr = R509::
|
110
|
-
|
172
|
+
csr = R509::CSR.new(
|
173
|
+
:subject => [['C','US'],['O','r509 LLC'],['CN','r509 Self-Signed CA Test']]
|
111
174
|
)
|
112
175
|
ca = R509::CertificateAuthority::Signer.new
|
113
176
|
cert = ca.selfsign(
|
114
|
-
|
115
|
-
|
116
|
-
|
177
|
+
:csr => csr,
|
178
|
+
:not_before => not_before,
|
179
|
+
:not_after => not_after
|
117
180
|
)
|
118
181
|
```
|
119
182
|
|
120
183
|
###Config
|
121
184
|
|
122
|
-
Create a basic
|
185
|
+
Create a basic CAConfig object
|
123
186
|
|
124
187
|
```ruby
|
125
188
|
cert_pem = File.read("/path/to/cert")
|
126
189
|
key_pem = File.read("/path/to/key")
|
127
190
|
cert = R509::Cert.new(
|
128
|
-
|
129
|
-
|
191
|
+
:cert => cert_pem,
|
192
|
+
:key => key_pem
|
130
193
|
)
|
131
|
-
config = R509::Config::
|
132
|
-
|
194
|
+
config = R509::Config::CAConfig.new(
|
195
|
+
:ca_cert => cert
|
133
196
|
)
|
134
197
|
```
|
135
198
|
|
136
|
-
Add a signing profile named "server" (
|
199
|
+
Add a signing profile named "server" (CAProfile) to a config object
|
137
200
|
|
138
201
|
```ruby
|
139
|
-
profile = R509::Config::
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
202
|
+
profile = R509::Config::CAProfile.new(
|
203
|
+
:basic_constraints => {"ca" : false},
|
204
|
+
:key_usage => ["digitalSignature","keyEncipherment"],
|
205
|
+
:extended_key_usage => ["serverAuth"],
|
206
|
+
:certificate_policies => [
|
207
|
+
{ "policy_identifier" => "2.16.840.1.99999.21.234",
|
208
|
+
"cps_uris" => ["http://example.com/cps","http://haha.com"],
|
209
|
+
"user_notices" => [ { "explicit_text" => "this is a great thing", "organization" => "my org", "notice_numbers" => "1,2,3" } ]
|
210
|
+
}
|
211
|
+
],
|
212
|
+
:subject_item_policy => nil,
|
213
|
+
:ocsp_no_check => false # this should only be true if you are setting OCSPSigning EKU
|
145
214
|
)
|
146
215
|
# config object from above assumed
|
147
216
|
config.set_profile("server",profile)
|
@@ -150,79 +219,88 @@ config.set_profile("server",profile)
|
|
150
219
|
Set up a subject item policy (required/optional). The keys must match OpenSSL's shortnames!
|
151
220
|
|
152
221
|
```ruby
|
153
|
-
profile = R509::Config::
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
}
|
222
|
+
profile = R509::Config::CAProfile.new(
|
223
|
+
:basic_constraints => {"ca" : false},
|
224
|
+
:key_usage => ["digitalSignature","keyEncipherment"],
|
225
|
+
:extended_key_usage => ["serverAuth"],
|
226
|
+
:subject_item_policy => {
|
227
|
+
"CN" => "required",
|
228
|
+
"O" => "optional"
|
229
|
+
}
|
162
230
|
)
|
163
231
|
# config object from above assumed
|
164
232
|
config.set_profile("server",profile)
|
165
233
|
```
|
166
234
|
|
167
|
-
Load
|
235
|
+
Load CAConfig + Profile from YAML
|
168
236
|
|
169
237
|
```ruby
|
170
|
-
config = R509::Config::
|
238
|
+
config = R509::Config::CAConfig.from_yaml("test_ca", "config_test.yaml")
|
171
239
|
```
|
172
240
|
|
173
241
|
Example YAML (more options are supported than this example)
|
174
242
|
|
175
243
|
```yaml
|
176
244
|
test_ca: {
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
245
|
+
ca_cert: {
|
246
|
+
cert: '/path/to/test_ca.cer',
|
247
|
+
key: '/path/to/test_ca.key'
|
248
|
+
},
|
249
|
+
crl_list: "crl_list_file.txt",
|
250
|
+
crl_number: "crl_number_file.txt",
|
251
|
+
cdp_location: ['http://crl.domain.com/test_ca.crl'],
|
252
|
+
crl_validity_hours: 168, #7 days
|
253
|
+
ocsp_location: ['http://ocsp.domain.com'],
|
254
|
+
ca_issuers_location: ['http://www.domain.com/my_roots.html'],
|
255
|
+
message_digest: 'SHA1', #SHA1, SHA224, SHA256, SHA384, SHA512 supported. MD5 too, but you really shouldn't use that unless you have a good reason
|
256
|
+
profiles: {
|
257
|
+
server: {
|
258
|
+
basic_constraints: {"ca" : false},
|
259
|
+
key_usage: [digitalSignature,keyEncipherment],
|
260
|
+
extended_key_usage: [serverAuth],
|
261
|
+
certificate_policies: [
|
262
|
+
{ policy_identifier: "2.16.840.1.99999.21.234",
|
263
|
+
cps_uris: ["http://example.com/cps","http://haha.com"],
|
264
|
+
user_notices: [ { explicit_text: "this is a great thing", organization: "my org", notice_numbers: "1,2,3" } ]
|
265
|
+
},
|
266
|
+
{ policy_identifier: "2.16.840.1.99999.21.235",
|
267
|
+
cps_uris: ["http://example.com/cps2"],
|
268
|
+
user_notices: [ { explicit_text: "this is a bad thing", organization: "another org", notice_numbers: "3,2,1" },{ explicit_text: "another user notice"} ]
|
199
269
|
}
|
270
|
+
],
|
271
|
+
subject_item_policy: {
|
272
|
+
"CN" : "required",
|
273
|
+
"O" : "optional",
|
274
|
+
"ST" : "required",
|
275
|
+
"C" : "required",
|
276
|
+
"OU" : "optional" }
|
200
277
|
}
|
278
|
+
}
|
201
279
|
}
|
202
280
|
```
|
203
281
|
|
204
|
-
Load multiple
|
282
|
+
Load multiple CAConfigs using a CAConfigPool
|
205
283
|
|
206
284
|
```ruby
|
207
|
-
pool = R509::Config::
|
285
|
+
pool = R509::Config::CAConfigPool.from_yaml("certificate_authorities", "config_pool.yaml")
|
208
286
|
```
|
209
287
|
|
210
288
|
Example (Minimal) Config Pool YAML
|
211
289
|
|
212
290
|
```yaml
|
213
291
|
certificate_authorities: {
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
}
|
219
|
-
},
|
220
|
-
second_ca: {
|
221
|
-
ca_cert: {
|
222
|
-
cert: 'second_ca.cer',
|
223
|
-
key: 'second_ca.key'
|
224
|
-
}
|
292
|
+
test_ca: {
|
293
|
+
ca_cert: {
|
294
|
+
cert: 'test_ca.cer',
|
295
|
+
key: 'test_ca.key'
|
225
296
|
}
|
297
|
+
},
|
298
|
+
second_ca: {
|
299
|
+
ca_cert: {
|
300
|
+
cert: 'second_ca.cer',
|
301
|
+
key: 'second_ca.key'
|
302
|
+
}
|
303
|
+
}
|
226
304
|
}
|
227
305
|
```
|
228
306
|
|
@@ -231,85 +309,119 @@ certificate_authorities: {
|
|
231
309
|
Sign a CSR
|
232
310
|
|
233
311
|
```ruby
|
234
|
-
csr = R509::
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
312
|
+
csr = R509::CSR.new(
|
313
|
+
:subject => [
|
314
|
+
['CN','somedomain.com'],
|
315
|
+
['O','My Org'],
|
316
|
+
['L','City'],
|
317
|
+
['ST','State'],
|
318
|
+
['C','US']
|
319
|
+
]
|
242
320
|
)
|
243
321
|
# assume config from yaml load above
|
244
322
|
ca = R509::CertificateAuthority::Signer.new(config)
|
245
323
|
cert = ca.sign(
|
246
|
-
|
247
|
-
|
324
|
+
:profile_name => "server",
|
325
|
+
:csr => csr
|
248
326
|
)
|
249
327
|
```
|
250
328
|
|
251
329
|
Override a CSR's subject or SAN names when signing
|
252
330
|
|
253
331
|
```ruby
|
254
|
-
csr = R509::
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
332
|
+
csr = R509::CSR.new(
|
333
|
+
:subject => [
|
334
|
+
['CN','somedomain.com'],
|
335
|
+
['O','My Org'],
|
336
|
+
['L','City'],
|
337
|
+
['ST','State'],
|
338
|
+
['C','US']
|
339
|
+
]
|
262
340
|
)
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
341
|
+
subject = csr.subject.dup
|
342
|
+
san_names = ["sannames.com","domain2.com","128.128.128.128"]
|
343
|
+
subject.common_name = "newdomain.com"
|
344
|
+
subject.organization = "Org 2.0"
|
267
345
|
# assume config from yaml load above
|
268
346
|
ca = R509::CertificateAuthority::Signer.new(config)
|
269
347
|
cert = ca.sign(
|
270
|
-
|
271
|
-
|
272
|
-
|
348
|
+
:profile_name => "server",
|
349
|
+
:csr => csr,
|
350
|
+
:subject => subject,
|
351
|
+
:san_names => san_names
|
273
352
|
)
|
274
353
|
```
|
275
354
|
|
276
|
-
|
277
|
-
|
278
|
-
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.
|
355
|
+
Sign an SPKI/SPKAC object
|
279
356
|
|
280
357
|
```ruby
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
358
|
+
key = R509::PrivateKey.new(:type => :rsa, :bit_strength => 2048)
|
359
|
+
spki = R509::SPKI.new(:key => key)
|
360
|
+
# SPKI objects do not contain subject or san name data so it must be specified
|
361
|
+
subject = R509::Subject.new
|
362
|
+
subject.CN = "mydomain.com"
|
363
|
+
subject.L = "Locality"
|
364
|
+
subject.ST = "State"
|
365
|
+
subject.C = "US"
|
366
|
+
san_names = ["domain2.com","128.128.128.128"]
|
367
|
+
# assume config from yaml load above
|
368
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
369
|
+
cert = ca.sign(
|
370
|
+
:profile_name => "server",
|
371
|
+
:spki => spki,
|
372
|
+
:subject => subject,
|
373
|
+
:san_names => san_names
|
286
374
|
)
|
287
|
-
```
|
288
|
-
|
289
|
-
You can then use this key for signing.
|
290
375
|
|
376
|
+
```
|
291
377
|
|
292
378
|
###OID Mapping
|
293
379
|
|
294
380
|
Register one
|
295
381
|
|
296
382
|
```ruby
|
297
|
-
R509::
|
383
|
+
R509::OIDMapper.register("1.3.5.6.7.8.3.23.3","short_name","optional_long_name")
|
298
384
|
```
|
299
385
|
|
300
386
|
Register in batch
|
301
387
|
|
302
388
|
```ruby
|
303
|
-
R509::
|
304
|
-
|
305
|
-
|
389
|
+
R509::OIDMapper.batch_register([
|
390
|
+
{:oid => "1.3.5.6.7.8.3.23.3", :short_name => "short_name", :long_name => "optional_long_name"},
|
391
|
+
{:oid => "1.3.5.6.7.8.3.23.5", :short_name => "another_name"}
|
306
392
|
])
|
307
393
|
```
|
308
394
|
|
309
|
-
|
395
|
+
###Alternate Key Algorithms
|
396
|
+
In addition to the default RSA objects that are created above, r509 supports DSA and elliptic curve (EC). EC support is present only if Ruby has been linked against a version of OpenSSL compiled with EC enabled. This excludes Red Hat-based distributions at this time (unless you build it yourself). Take a look at the documentation for R509::PrivateKey, R509::Cert, and R509::CSR to see how to create DSA and EC types. You can test if elliptic curve support is available in your Ruby with:
|
397
|
+
|
398
|
+
```ruby
|
399
|
+
R509.ec_supported?
|
400
|
+
```
|
401
|
+
|
402
|
+
####NIST Recommended Elliptic Curves
|
403
|
+
These curves are set via ```:curve_name```. The system defaults to using ```secp384r1```
|
404
|
+
|
405
|
+
* secp224r1 -- NIST/SECG curve over a 224 bit prime field
|
406
|
+
* secp384r1 -- NIST/SECG curve over a 384 bit prime field
|
407
|
+
* secp521r1 -- NIST/SECG curve over a 521 bit prime field
|
408
|
+
* prime192v1 -- NIST/X9.62/SECG curve over a 192 bit prime field
|
409
|
+
* sect163k1 -- NIST/SECG/WTLS curve over a 163 bit binary field
|
410
|
+
* sect163r2 -- NIST/SECG curve over a 163 bit binary field
|
411
|
+
* sect233k1 -- NIST/SECG/WTLS curve over a 233 bit binary field
|
412
|
+
* sect233r1 -- NIST/SECG/WTLS curve over a 233 bit binary field
|
413
|
+
* sect283k1 -- NIST/SECG curve over a 283 bit binary field
|
414
|
+
* sect283r1 -- NIST/SECG curve over a 283 bit binary field
|
415
|
+
* sect409k1 -- NIST/SECG curve over a 409 bit binary field
|
416
|
+
* sect409r1 -- NIST/SECG curve over a 409 bit binary field
|
417
|
+
* sect571k1 -- NIST/SECG curve over a 571 bit binary field
|
418
|
+
* sect571r1 -- NIST/SECG curve over a 571 bit binary field
|
310
419
|
|
311
|
-
|
420
|
+
##Documentation
|
421
|
+
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. Alternately you can view pre-generated documentation at [r509.org](http://r509.org)
|
312
422
|
|
423
|
+
##Created by...
|
424
|
+
[Paul Kehrer](https://github.com/reaperhulk)
|
313
425
|
|
314
426
|
##Thanks to...
|
315
427
|
* [Sean Schulte](https://github.com/sirsean)
|
@@ -319,14 +431,14 @@ There is (relatively) complete documentation available for every method and clas
|
|
319
431
|
See the LICENSE file. Licensed under the Apache 2.0 License.
|
320
432
|
|
321
433
|
#YAML Config Options
|
322
|
-
r509 configs are nested hashes of key:values that define the behavior of each CA. See r509.yaml for a full example config.
|
434
|
+
r509 configs are nested hashes of key:values that define the behavior of each CA. See r509.yaml for a full example config. These options can also be defined programmatically via R509::CAConfig and R509::CAProfile.
|
323
435
|
|
324
436
|
##ca\_name
|
325
437
|
###ca\_cert
|
326
438
|
This hash defines the certificate + key that will be used to sign for the ca\_name. Depending on desired configuration various elements are optional. You can even supply just __cert__ (for example, if you are using an ocsp\_cert hash and only using the configured CA for OCSP responses)
|
327
439
|
|
328
440
|
* cert (cannot use with pkcs12)
|
329
|
-
* key (cannot use with
|
441
|
+
* key (optional, cannot use with pkcs12)
|
330
442
|
* engine (optional, cannot be used with key or pkcs12)
|
331
443
|
* key\_name (required when using engine)
|
332
444
|
* pkcs12 (optional, cannot be used with key or cert)
|
@@ -336,16 +448,18 @@ This hash defines the certificate + key that will be used to sign for the ca\_na
|
|
336
448
|
This hash defines the certificate + key that will be used to sign for OCSP responses. OCSP responses cannot be directly created with r509, but require the ancillary gem [r509-ocsp-responder](https://github.com/reaperhulk/r509-ocsp-responder). This hash is optional and if not provided r509 will automatically use the ca\_cert as the OCSP certificate.
|
337
449
|
|
338
450
|
* cert (cannot use with pkcs12)
|
339
|
-
* key (cannot use with
|
451
|
+
* key (optional, cannot use with pkcs12)
|
340
452
|
* engine (optional, cannot be used with key or pkcs12)
|
341
453
|
* key\_name (required when using engine)
|
342
454
|
* pkcs12 (optional, cannot be used with key or cert)
|
343
455
|
* password (optional, used for pkcs12 or passworded private key)
|
344
456
|
|
345
457
|
###cdp\_location
|
346
|
-
|
458
|
+
An array of CRL distribution points for certificates issued from this CA.
|
347
459
|
|
348
|
-
|
460
|
+
```yaml
|
461
|
+
['http://crl.r509.org/myca.crl']
|
462
|
+
```
|
349
463
|
|
350
464
|
###crl\_list
|
351
465
|
The path on the filesystem of the list of revoked certificates for this CA.
|
@@ -361,9 +475,18 @@ Example: '/path/to/my\_ca\_crl\_number.txt'
|
|
361
475
|
Integer hours for CRL validity.
|
362
476
|
|
363
477
|
###ocsp\_location
|
364
|
-
|
478
|
+
An array of URIs for client OCSP checks. These strings will be scanned and automatically processed to determine their proper type in the certificate.
|
365
479
|
|
366
|
-
|
480
|
+
```yaml
|
481
|
+
['http://ocsp.r509.org']
|
482
|
+
```
|
483
|
+
|
484
|
+
###ca\_issuers\_location
|
485
|
+
An array of ca issuer locations. These strings will be scanned and automatically processed to determine their proper type in the certificate.
|
486
|
+
|
487
|
+
```yaml
|
488
|
+
['http://www.r509.org/some_roots.html']
|
489
|
+
```
|
367
490
|
|
368
491
|
###ocsp\_chain
|
369
492
|
An optional path to a concatenated text file of PEMs that should be attached to OCSP responses
|
@@ -378,7 +501,9 @@ Integer seconds to skew back the "thisUpdate" field. This prevents issues where
|
|
378
501
|
String value of the message digest to use for signing (both CRL and certificates). Allowed values are:
|
379
502
|
|
380
503
|
* SHA1 (default)
|
504
|
+
* SHA224
|
381
505
|
* SHA256
|
506
|
+
* SHA384
|
382
507
|
* SHA512
|
383
508
|
* MD5 (Don't use this unless you have a really, really good reason. Even then, you shouldn't)
|
384
509
|
|
@@ -386,10 +511,22 @@ String value of the message digest to use for signing (both CRL and certificates
|
|
386
511
|
Each CA can have an arbitrary number of issuance profiles (with arbitrary names). For example, a CA named __test\_ca__ might have 3 issuance profiles: server, email, clientserver. Each of these profiles then has a set of options that define the encoded data in the certificate for that profile. If no profiles are defined the root cannot issue certs, but can still issue CRLs.
|
387
512
|
|
388
513
|
####basic\_constraints
|
389
|
-
All basic constraints are encoded with the critical bit set to true.
|
514
|
+
All basic constraints are encoded with the critical bit set to true. The basic constraints config expects a hash with between one and two keys.
|
515
|
+
|
516
|
+
#####ca
|
517
|
+
The ca key is required and must be set to true (for an issuing CA) or false (everything else).
|
518
|
+
|
519
|
+
#####path\_length
|
520
|
+
This option is only allowed if ca is set to TRUE. path_length allows you to define the maximum number of non-self-issued intermediate certificates that may follow this certificate in a valid certification path. For example, if you set this value to 0 then the certificate issued can only issue end entity certificates, not additional subroots. This must be a non-negative integer (>=0).
|
521
|
+
|
522
|
+
```yaml
|
523
|
+
{ca : true}
|
524
|
+
{ca : false}
|
525
|
+
{ca : true, path_length: 3}
|
526
|
+
```
|
390
527
|
|
391
528
|
####key\_usage
|
392
|
-
An array of strings that conform to the OpenSSL naming scheme for available key usage OIDs.
|
529
|
+
An array of strings that conform to the OpenSSL naming scheme for available key usage OIDs.
|
393
530
|
|
394
531
|
* digitalSignature
|
395
532
|
* nonRepudiation
|
@@ -410,24 +547,79 @@ An array of strings that conform to the OpenSSL naming scheme for available EKU
|
|
410
547
|
* emailProtection
|
411
548
|
* OCSPSigning
|
412
549
|
* timeStamping
|
413
|
-
* msCodeInd
|
414
|
-
* msCodeCom
|
415
|
-
* msCTLSign
|
416
|
-
* msSGC
|
417
|
-
* msEFS
|
418
|
-
* nsSGC
|
550
|
+
* msCodeInd (not part of RFC 5280)
|
551
|
+
* msCodeCom (not part of RFC 5280)
|
552
|
+
* msCTLSign (not part of RFC 5280)
|
553
|
+
* msSGC (not part of RFC 5280)
|
554
|
+
* msEFS (not part of RFC 5280)
|
555
|
+
* nsSGC (not part of RFC 5280)
|
419
556
|
|
420
557
|
####certificate\_policies
|
421
|
-
An array of
|
558
|
+
An array of hashes containing policy identifiers, CPS URI(s), and user notice(s)
|
422
559
|
|
423
560
|
```yaml
|
424
|
-
[
|
561
|
+
[
|
562
|
+
{ policy_identifier: "2.16.840.1.99999.21.234",
|
563
|
+
cps_uris: ["http://example.com/cps"]
|
564
|
+
}
|
565
|
+
]
|
425
566
|
```
|
426
567
|
|
427
568
|
or
|
428
569
|
|
429
570
|
```yaml
|
430
|
-
[
|
571
|
+
[
|
572
|
+
{ policy_identifier: "2.16.840.1.99999.21.234",
|
573
|
+
cps_uris: ["http://example.com/cps","http://haha.com"],
|
574
|
+
user_notices: [ { explicit_text: "this is a great thing", organization: "my org", notice_numbers: "1,2,3" } ]
|
575
|
+
},
|
576
|
+
{ policy_identifier: "2.16.840.1.99999.21.235",
|
577
|
+
cps_uris: ["http://example.com/cps2"],
|
578
|
+
user_notices: [ { explicit_text: "this is a bad thing", organization: "another org", notice_numbers: "3,2,1" },{ explicit_text: "another user notice"} ]
|
579
|
+
}
|
580
|
+
]
|
581
|
+
```
|
582
|
+
|
583
|
+
####ocsp\_no\_check
|
584
|
+
This is a boolean option that determines whether the OCSPNoCheck extension should be encoded in certificates issued by the profile. This flag is _only_ meaningful on certificates that contain the OCSPSigning EKU.
|
585
|
+
|
586
|
+
####inhibit\_any\_policy
|
587
|
+
A non-negative integer value. From RFC 5280: "The inhibit anyPolicy extension can be used in certificates issued to CAs. The inhibit anyPolicy extension indicates that the special anyPolicy OID, with the value { 2 5 29 32 0 }, is not considered an explicit match for other certificate policies except when it appears in an intermediate self-issued CA certificate."
|
588
|
+
|
589
|
+
####policy\_constraints
|
590
|
+
A hash with two optional keys (one or both may be present). From RFC 5280: "The policy constraints extension can be used in certificates issued to CAs. The policy constraints extension constrains path validation in two ways. It can be used to prohibit policy mapping or require that each certificate in a path contain an acceptable policy identifier"
|
591
|
+
|
592
|
+
```yaml
|
593
|
+
{ require_explicit_policy: 0, inhibit_policy_mapping: 0 }
|
594
|
+
```
|
595
|
+
|
596
|
+
or if you only need one of the keys
|
597
|
+
|
598
|
+
```yaml
|
599
|
+
{ inhibit_policy_mapping: 0 }
|
600
|
+
```
|
601
|
+
|
602
|
+
###name\_constraints
|
603
|
+
From RFC 5280: "The name constraints extension, which MUST be used only in a CA certificate, indicates a name space within which all subject names in subsequent certificates in a certification path MUST be located. Restrictions apply to the subject distinguished name and apply to subject alternative names. Restrictions apply only when the specified name form is present. If no name of the type is in the certificate, the certificate is acceptable.".
|
604
|
+
|
605
|
+
This section is made up of a hash that contains permitted and excluded keys. Each (optional) key in turn has an array of hashes that declare a type and value. Types allowed are defined by R509::ASN1::GeneralName.map_type_to_tag. (examples: DNS, URI, IP, email, dirName)
|
606
|
+
|
607
|
+
Notes:
|
608
|
+
* When supplying IP you _must_ supply a full netmask in addition to an IP.
|
609
|
+
* When supplying dirName the value is an array of arrays structured the same way as input to :subject in R509::CSR.new
|
610
|
+
|
611
|
+
```yaml
|
612
|
+
{
|
613
|
+
permitted: [
|
614
|
+
{type: "IP", value: "192.168.0.0/255.255.0.0"},
|
615
|
+
{type: "dirName", value: [['CN','myCN'],['O','Org']]}
|
616
|
+
],
|
617
|
+
excluded: [
|
618
|
+
{type: "email", value: "domain.com"},
|
619
|
+
{type: "URI", value: ".net"},
|
620
|
+
{type: "DNS", value: "test.us"}
|
621
|
+
]
|
622
|
+
}
|
431
623
|
```
|
432
624
|
|
433
625
|
####subject\_item\_policy
|
@@ -444,4 +636,4 @@ L: "required",
|
|
444
636
|
emailAddress: "optional"
|
445
637
|
```
|
446
638
|
|
447
|
-
If you use the R509::
|
639
|
+
If you use the R509::OIDMapper you can create new shortnames that are allowed within this directive.
|