r509 0.8.1 → 0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (203) hide show
  1. data/README.md +343 -151
  2. data/Rakefile +26 -23
  3. data/bin/r509 +126 -112
  4. data/bin/r509-parse +24 -24
  5. data/doc/R509.html +169 -7
  6. data/doc/R509/ASN1.html +370 -0
  7. data/doc/R509/ASN1/GeneralName.html +1121 -0
  8. data/doc/R509/ASN1/GeneralNames.html +843 -0
  9. data/doc/R509/ASN1/NoticeReference.html +392 -0
  10. data/doc/R509/ASN1/PolicyInformation.html +387 -0
  11. data/doc/R509/ASN1/PolicyQualifiers.html +455 -0
  12. data/doc/R509/ASN1/UserNotice.html +386 -0
  13. data/doc/R509/{Crl.html → CRL.html} +7 -7
  14. data/doc/R509/CRL/Administrator.html +1559 -0
  15. data/doc/R509/{Crl/Parser.html → CRL/SignedList.html} +501 -210
  16. data/doc/R509/{Csr.html → CSR.html} +444 -314
  17. data/doc/R509/Cert.html +866 -617
  18. data/doc/R509/Cert/Extensions.html +52 -41
  19. data/doc/R509/Cert/Extensions/AuthorityInfoAccess.html +70 -35
  20. data/doc/R509/Cert/Extensions/AuthorityKeyIdentifier.html +387 -4
  21. data/doc/R509/Cert/Extensions/BasicConstraints.html +61 -25
  22. data/doc/R509/Cert/Extensions/CRLDistributionPoints.html +354 -0
  23. data/doc/R509/Cert/Extensions/CertificatePolicies.html +340 -0
  24. data/doc/R509/Cert/Extensions/ExtendedKeyUsage.html +440 -49
  25. data/doc/R509/Cert/Extensions/{CrlDistributionPoints.html → InhibitAnyPolicy.html} +52 -35
  26. data/doc/R509/Cert/Extensions/KeyUsage.html +247 -121
  27. data/doc/R509/Cert/Extensions/NameConstraints.html +445 -0
  28. data/doc/R509/Cert/Extensions/OCSPNoCheck.html +239 -0
  29. data/doc/R509/Cert/Extensions/PolicyConstraints.html +424 -0
  30. data/doc/R509/Cert/Extensions/SubjectAlternativeName.html +437 -62
  31. data/doc/R509/Cert/Extensions/SubjectKeyIdentifier.html +52 -10
  32. data/doc/R509/CertificateAuthority.html +4 -4
  33. data/doc/R509/CertificateAuthority/Signer.html +154 -187
  34. data/doc/R509/Config.html +6 -6
  35. data/doc/R509/Config/{CaConfig.html → CAConfig.html} +451 -348
  36. data/doc/R509/Config/{CaConfigPool.html → CAConfigPool.html} +47 -47
  37. data/doc/R509/Config/CAProfile.html +1015 -0
  38. data/doc/R509/Config/SubjectItemPolicy.html +86 -86
  39. data/doc/R509/IOHelpers.html +22 -22
  40. data/doc/R509/MessageDigest.html +14 -14
  41. data/doc/R509/NameSanitizer.html +53 -53
  42. data/doc/R509/{Ocsp.html → OCSP.html} +9 -9
  43. data/doc/R509/{Ocsp → OCSP}/Request.html +7 -7
  44. data/doc/R509/{Ocsp → OCSP}/Request/Nonce.html +56 -11
  45. data/doc/R509/{Ocsp → OCSP}/Response.html +44 -44
  46. data/doc/R509/{OidMapper.html → OIDMapper.html} +23 -39
  47. data/doc/R509/PrivateKey.html +415 -168
  48. data/doc/R509/R509Error.html +3 -3
  49. data/doc/R509/{Spki.html → SPKI.html} +354 -192
  50. data/doc/R509/Subject.html +224 -113
  51. data/doc/R509/Validity.html +27 -5
  52. data/doc/R509/Validity/Checker.html +13 -13
  53. data/doc/R509/Validity/DefaultChecker.html +13 -13
  54. data/doc/R509/Validity/DefaultWriter.html +14 -14
  55. data/doc/R509/Validity/Status.html +39 -39
  56. data/doc/R509/Validity/Writer.html +18 -18
  57. data/doc/_index.html +138 -35
  58. data/doc/class_list.html +1 -1
  59. data/doc/css/style.css +10 -0
  60. data/doc/file.README.html +368 -171
  61. data/doc/file.r509.html +92 -69
  62. data/doc/frames.html +1 -1
  63. data/doc/index.html +368 -171
  64. data/doc/method_list.html +910 -390
  65. data/doc/top-level-namespace.html +3 -3
  66. data/lib/r509.rb +32 -16
  67. data/lib/r509/asn1.rb +375 -0
  68. data/lib/r509/cert.rb +381 -364
  69. data/lib/r509/cert/extensions.rb +443 -76
  70. data/lib/r509/certificate_authority.rb +407 -0
  71. data/lib/r509/config.rb +547 -351
  72. data/lib/r509/crl.rb +336 -366
  73. data/lib/r509/csr.rb +278 -289
  74. data/lib/r509/ec-hack.rb +37 -0
  75. data/lib/r509/exceptions.rb +3 -3
  76. data/lib/r509/io_helpers.rb +44 -44
  77. data/lib/r509/message_digest.rb +53 -0
  78. data/lib/r509/ocsp.rb +80 -70
  79. data/lib/r509/oid_mapper.rb +32 -0
  80. data/lib/r509/private_key.rb +228 -0
  81. data/lib/r509/spki.rb +145 -93
  82. data/lib/r509/subject.rb +203 -110
  83. data/lib/r509/validity.rb +70 -68
  84. data/lib/r509/version.rb +2 -2
  85. data/r509.yaml +92 -69
  86. data/spec/asn1_spec.rb +402 -0
  87. data/spec/cert/extensions_spec.rb +957 -494
  88. data/spec/cert_spec.rb +382 -307
  89. data/spec/certificate_authority_spec.rb +668 -250
  90. data/spec/config_spec.rb +515 -302
  91. data/spec/crl_spec.rb +197 -198
  92. data/spec/csr_spec.rb +334 -289
  93. data/spec/fixtures.rb +247 -171
  94. data/spec/fixtures/cert1.der +0 -0
  95. data/spec/fixtures/cert1.pem +0 -0
  96. data/spec/fixtures/cert1_public_key_modulus.txt +0 -0
  97. data/spec/fixtures/cert3.p12 +0 -0
  98. data/spec/fixtures/cert3.pem +0 -0
  99. data/spec/fixtures/cert3_key.pem +0 -0
  100. data/spec/fixtures/cert3_key_des3.pem +0 -0
  101. data/spec/fixtures/cert4.pem +0 -0
  102. data/spec/fixtures/cert5.pem +0 -0
  103. data/spec/fixtures/cert6.pem +0 -0
  104. data/spec/fixtures/cert_expired.pem +0 -0
  105. data/spec/fixtures/cert_inhibit.pem +24 -0
  106. data/spec/fixtures/cert_name_constraints.pem +29 -0
  107. data/spec/fixtures/cert_not_yet_valid.pem +0 -0
  108. data/spec/fixtures/cert_ocsp_no_check.pem +18 -0
  109. data/spec/fixtures/cert_policy_constraints.pem +31 -0
  110. data/spec/fixtures/cert_san.pem +0 -0
  111. data/spec/fixtures/cert_san2.pem +0 -0
  112. data/spec/fixtures/cert_unknown_extension.pem +28 -0
  113. data/spec/fixtures/config_pool_test_minimal.yaml +11 -11
  114. data/spec/fixtures/config_test.yaml +54 -36
  115. data/spec/fixtures/config_test_dsa.yaml +35 -0
  116. data/spec/fixtures/config_test_ec.yaml +35 -0
  117. data/spec/fixtures/config_test_engine_key.yaml +5 -5
  118. data/spec/fixtures/config_test_engine_no_key_name.yaml +4 -4
  119. data/spec/fixtures/config_test_minimal.yaml +4 -4
  120. data/spec/fixtures/config_test_password.yaml +5 -5
  121. data/spec/fixtures/config_test_various.yaml +111 -74
  122. data/spec/fixtures/crl_list_file.txt +0 -0
  123. data/spec/fixtures/crl_with_reason.pem +0 -0
  124. data/spec/fixtures/csr1.der +0 -0
  125. data/spec/fixtures/csr1.pem +0 -0
  126. data/spec/fixtures/csr1_key.der +0 -0
  127. data/spec/fixtures/csr1_key.pem +0 -0
  128. data/spec/fixtures/csr1_key_encrypted_des3.pem +0 -0
  129. data/spec/fixtures/csr1_newlines.pem +0 -0
  130. data/spec/fixtures/csr1_no_begin_end.pem +0 -0
  131. data/spec/fixtures/csr1_public_key_modulus.txt +0 -0
  132. data/spec/fixtures/csr2.pem +0 -0
  133. data/spec/fixtures/csr2_key.pem +0 -0
  134. data/spec/fixtures/csr3.pem +0 -0
  135. data/spec/fixtures/csr4.pem +0 -0
  136. data/spec/fixtures/csr_dsa.pem +0 -0
  137. data/spec/fixtures/csr_invalid_signature.pem +0 -0
  138. data/spec/fixtures/dsa_key.pem +0 -0
  139. data/spec/fixtures/dsa_root.cer +28 -0
  140. data/spec/fixtures/dsa_root.key +20 -0
  141. data/spec/fixtures/ec_csr2.der +0 -0
  142. data/spec/fixtures/ec_csr2.pem +8 -0
  143. data/spec/fixtures/ec_key1.der +0 -0
  144. data/spec/fixtures/ec_key1.pem +6 -0
  145. data/spec/fixtures/ec_key1_encrypted.pem +9 -0
  146. data/spec/fixtures/ec_key2.pem +6 -0
  147. data/spec/fixtures/hmacsha1.sig +1 -0
  148. data/spec/fixtures/hmacsha512.sig +1 -0
  149. data/spec/fixtures/key4.pem +0 -0
  150. data/spec/fixtures/key4_encrypted_des3.pem +0 -0
  151. data/spec/fixtures/missing_key_identifier_ca.cer +0 -0
  152. data/spec/fixtures/missing_key_identifier_ca.key +0 -0
  153. data/spec/fixtures/ocsptest.r509.local.pem +0 -0
  154. data/spec/fixtures/ocsptest.r509.local_ocsp_request.der +0 -0
  155. data/spec/fixtures/ocsptest2.r509.local.pem +0 -0
  156. data/spec/fixtures/second_ca.cer +0 -0
  157. data/spec/fixtures/second_ca.key +0 -0
  158. data/spec/fixtures/spkac.der +0 -0
  159. data/spec/fixtures/spkac.txt +0 -0
  160. data/spec/fixtures/spkac_dsa.txt +1 -1
  161. data/spec/fixtures/spkac_dsa_no_verify.txt +1 -0
  162. data/spec/fixtures/spkac_ec.txt +1 -0
  163. data/spec/fixtures/spkac_rsa_newlines.txt +13 -0
  164. data/spec/fixtures/stca.pem +0 -0
  165. data/spec/fixtures/stca_ocsp_request.der +0 -0
  166. data/spec/fixtures/stca_ocsp_response.der +0 -0
  167. data/spec/fixtures/test1.csr +0 -0
  168. data/spec/fixtures/test_ca.cer +0 -0
  169. data/spec/fixtures/test_ca.key +0 -0
  170. data/spec/fixtures/test_ca.p12 +0 -0
  171. data/spec/fixtures/test_ca_des3.key +0 -0
  172. data/spec/fixtures/test_ca_ec.cer +14 -0
  173. data/spec/fixtures/test_ca_ec.key +6 -0
  174. data/spec/fixtures/test_ca_ec_ee.cer +22 -0
  175. data/spec/fixtures/test_ca_ec_ee.key +6 -0
  176. data/spec/fixtures/test_ca_ocsp.cer +0 -0
  177. data/spec/fixtures/test_ca_ocsp.key +0 -0
  178. data/spec/fixtures/test_ca_ocsp.p12 +0 -0
  179. data/spec/fixtures/test_ca_ocsp_chain.txt +0 -0
  180. data/spec/fixtures/test_ca_ocsp_response.der +0 -0
  181. data/spec/fixtures/test_ca_subroot.cer +0 -0
  182. data/spec/fixtures/test_ca_subroot.key +0 -0
  183. data/spec/fixtures/test_ca_subroot_ocsp.cer +0 -0
  184. data/spec/fixtures/test_ca_subroot_ocsp.key +0 -0
  185. data/spec/fixtures/test_ca_subroot_ocsp_response.der +0 -0
  186. data/spec/fixtures/unknown_oid.csr +0 -0
  187. data/spec/message_digest_spec.rb +104 -84
  188. data/spec/ocsp_spec.rb +105 -105
  189. data/spec/oid_mapper_spec.rb +21 -21
  190. data/spec/private_key_spec.rb +275 -0
  191. data/spec/r509_spec.rb +35 -0
  192. data/spec/spec_helper.rb +15 -6
  193. data/spec/spki_spec.rb +221 -142
  194. data/spec/subject_spec.rb +232 -164
  195. data/spec/validity_spec.rb +91 -91
  196. metadata +79 -25
  197. data/doc/R509/Config/CaProfile.html +0 -651
  198. data/doc/R509/Crl/Administrator.html +0 -2073
  199. data/lib/r509/certificateauthority.rb +0 -290
  200. data/lib/r509/messagedigest.rb +0 -49
  201. data/lib/r509/oidmapper.rb +0 -32
  202. data/lib/r509/privatekey.rb +0 -185
  203. 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 wrapper for various OpenSSL functions to allow easy creation of CSRs, signing of certificates, and revocation via CRL. 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 certificate authority for use in production environments.
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/Installation
4
+ ##Requirements
5
5
 
6
- r509 requires the Ruby OpenSSL bindings as well as yaml support (present by default in modern Ruby builds).
7
- To install the gem: ```gem install r509-(version).gem```
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.8.7, 1.9.2, 1.9.3, ree, ruby-head, and rubinius(rbx) 2.0 in 1.9 mode.
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 bin directory that contains ```r509```. You can use this in interactive mode to generate a CSR and (optionally) self-sign it.
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::Csr.new(
25
- :subject => [
26
- ['CN','somedomain.com'],
27
- ['O','My Org'],
28
- ['L','City'],
29
- ['ST','State'],
30
- ['C','US']
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::Csr.new(:csr => csr_pem)
63
+ csr = R509::CSR.new(:csr => csr_pem)
40
64
  # or
41
- csr = R509::Csr.load_from_file("/path/to/csr")
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::Csr.new(:cert => cert_pem)
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::Csr.new(
55
- :subject => [['CN','something.com']],
56
- :san_names => ["something2.com","something3.com"]
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
- :cert => cert_pem,
77
- :key => key_pem
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
- :cert => cert_pem,
88
- :key => key_pem,
89
- :password => "private_key_password"
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
- :pkcs12 => pkcs12_der,
99
- :password => "password"
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::Csr.new(
110
- :subject => [['C','US'],['O','r509 LLC'],['CN','r509 Self-Signed CA Test']]
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
- :csr => csr,
115
- :not_before => not_before,
116
- :not_after => not_after
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 CaConfig object
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
- :cert => cert_pem,
129
- :key => key_pem
191
+ :cert => cert_pem,
192
+ :key => key_pem
130
193
  )
131
- config = R509::Config::CaConfig.new(
132
- :ca_cert => cert
194
+ config = R509::Config::CAConfig.new(
195
+ :ca_cert => cert
133
196
  )
134
197
  ```
135
198
 
136
- Add a signing profile named "server" (CaProfile) to a config object
199
+ Add a signing profile named "server" (CAProfile) to a config object
137
200
 
138
201
  ```ruby
139
- profile = R509::Config::CaProfile.new(
140
- :basic_constraints => "CA:FALSE",
141
- :key_usage => ["digitalSignature","keyEncipherment"],
142
- :extended_key_usage => ["serverAuth"],
143
- :certificate_policies => [ ["policyIdentifier=2.16.840.1.999999999.1.2.3.4.1", "CPS.1=http://example.com/cps"] ],
144
- :subject_item_policy => nil
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::CaProfile.new(
154
- :basic_constraints => "CA:FALSE",
155
- :key_usage => ["digitalSignature","keyEncipherment"],
156
- :extended_key_usage => ["serverAuth"],
157
- :certificate_policies => [ ["policyIdentifier=2.16.840.1.999999999.1.2.3.4.1", "CPS.1=http://example.com/cps"] ],
158
- :subject_item_policy => {
159
- "CN" => "required",
160
- "O" => "optional"
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 CaConfig + Profile from YAML
235
+ Load CAConfig + Profile from YAML
168
236
 
169
237
  ```ruby
170
- config = R509::Config::CaConfig.from_yaml("test_ca", "config_test.yaml")
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
- ca_cert: {
178
- cert: '/path/to/test_ca.cer',
179
- key: '/path/to/test_ca.key'
180
- },
181
- crl_list: "crl_list_file.txt",
182
- crl_number: "crl_number_file.txt",
183
- cdp_location: 'URI:http://crl.domain.com/test_ca.crl',
184
- crl_validity_hours: 168, #7 days
185
- ocsp_location: 'URI:http://ocsp.domain.com',
186
- message_digest: 'SHA1', #SHA1, SHA256, SHA512 supported. MD5 too, but you really shouldn't use that unless you have a good reason
187
- profiles: {
188
- server: {
189
- basic_constraints: "CA:FALSE",
190
- key_usage: [digitalSignature,keyEncipherment],
191
- extended_key_usage: [serverAuth],
192
- certificate_policies: [ [ "policyIdentifier=2.16.840.1.9999999999.1.2.3.4.1", "CPS.1=http://example.com/cps"] ],
193
- subject_item_policy: {
194
- "CN" : "required",
195
- "O" : "optional",
196
- "ST" : "required",
197
- "C" : "required",
198
- "OU" : "optional" }
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 CaConfigs using a CaConfigPool
282
+ Load multiple CAConfigs using a CAConfigPool
205
283
 
206
284
  ```ruby
207
- pool = R509::Config::CaConfigPool.from_yaml("certificate_authorities", "config_pool.yaml")
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
- test_ca: {
215
- ca_cert: {
216
- cert: 'test_ca.cer',
217
- key: 'test_ca.key'
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::Csr.new(
235
- :subject => [
236
- ['CN','somedomain.com'],
237
- ['O','My Org'],
238
- ['L','City'],
239
- ['ST','State'],
240
- ['C','US']
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
- :profile_name => "server",
247
- :csr => csr
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::Csr.new(
255
- :subject => [
256
- ['CN','somedomain.com'],
257
- ['O','My Org'],
258
- ['L','City'],
259
- ['ST','State'],
260
- ['C','US']
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
- data_hash = csr.to_hash
264
- data_hash[:san_names] = ["sannames.com","domain2.com"]
265
- data_hash[:subject]["CN"] = "newdomain.com"
266
- data_hash[:subject]["O"] = "Org 2.0"
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
- :profile_name => "server",
271
- :csr => csr,
272
- :data_hash => data_hash
348
+ :profile_name => "server",
349
+ :csr => csr,
350
+ :subject => subject,
351
+ :san_names => san_names
273
352
  )
274
353
  ```
275
354
 
276
- ###Load Hardware Engines
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
- OpenSSL::Engine.load("engine_name")
282
- engine = OpenSSL::Engine.by_id("engine_name")
283
- key = R509::PrivateKey(
284
- :engine => engine,
285
- :key_name => "my_key_name"
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::OidMapper.register("1.3.5.6.7.8.3.23.3","short_name","optional_long_name")
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::OidMapper.batch_register([
304
- {:oid => "1.3.5.6.7.8.3.23.3", :short_name => "short_name", :long_name => "optional_long_name"},
305
- {:oid => "1.3.5.6.7.8.3.23.5", :short_name => "another_name"}
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
- ##Documentation
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
- 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.
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 key)
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 key)
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
- The CRL distribution point for certificates issued from this CA.
458
+ An array of CRL distribution points for certificates issued from this CA.
347
459
 
348
- Example: 'URI:http://crl.r509.org/myca.crl'
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
- The OCSP AIA extension value for certificates issued from this CA.
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
- Example: 'URI:http://ocsp.r509.org'
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. In general you should only pass "CA:TRUE" (for an issuing CA) or "CA:FALSE" for everything else with this flag.
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. TODO: Document whether arbitrary OIDs can be passed here.
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 arrays containing policy identifiers and CPS URIs. For example:
558
+ An array of hashes containing policy identifiers, CPS URI(s), and user notice(s)
422
559
 
423
560
  ```yaml
424
- [ [ "policyIdentifier=2.16.840.1.9999999.1.2.3.4.2","CPS.1=http://r509.org/cps" ] ]
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
- [ ["policyIdentifier=2.16.840.1.999999.0"], [ "policyIdentifier=2.16.840.1.9999999.1.2.3.4.2","CPS.1=http://r509.org/cps" ] ]
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::OidMapper you can create new shortnames that are allowed within this directive.
639
+ If you use the R509::OIDMapper you can create new shortnames that are allowed within this directive.