r509 0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (162) hide show
  1. data/README.md +447 -0
  2. data/Rakefile +38 -0
  3. data/bin/r509 +96 -0
  4. data/bin/r509-parse +35 -0
  5. data/doc/R509.html +154 -0
  6. data/doc/R509/Cert.html +3954 -0
  7. data/doc/R509/Cert/Extensions.html +360 -0
  8. data/doc/R509/Cert/Extensions/AuthorityInfoAccess.html +391 -0
  9. data/doc/R509/Cert/Extensions/AuthorityKeyIdentifier.html +148 -0
  10. data/doc/R509/Cert/Extensions/BasicConstraints.html +482 -0
  11. data/doc/R509/Cert/Extensions/CrlDistributionPoints.html +316 -0
  12. data/doc/R509/Cert/Extensions/ExtendedKeyUsage.html +780 -0
  13. data/doc/R509/Cert/Extensions/KeyUsage.html +1230 -0
  14. data/doc/R509/Cert/Extensions/SubjectAlternativeName.html +467 -0
  15. data/doc/R509/Cert/Extensions/SubjectKeyIdentifier.html +216 -0
  16. data/doc/R509/CertificateAuthority.html +126 -0
  17. data/doc/R509/CertificateAuthority/Signer.html +855 -0
  18. data/doc/R509/Config.html +127 -0
  19. data/doc/R509/Config/CaConfig.html +2144 -0
  20. data/doc/R509/Config/CaConfigPool.html +599 -0
  21. data/doc/R509/Config/CaProfile.html +656 -0
  22. data/doc/R509/Config/SubjectItemPolicy.html +578 -0
  23. data/doc/R509/Crl.html +126 -0
  24. data/doc/R509/Crl/Administrator.html +2077 -0
  25. data/doc/R509/Crl/Parser.html +1224 -0
  26. data/doc/R509/Csr.html +2248 -0
  27. data/doc/R509/IOHelpers.html +564 -0
  28. data/doc/R509/MessageDigest.html +396 -0
  29. data/doc/R509/NameSanitizer.html +319 -0
  30. data/doc/R509/Ocsp.html +128 -0
  31. data/doc/R509/Ocsp/Request.html +126 -0
  32. data/doc/R509/Ocsp/Request/Nonce.html +160 -0
  33. data/doc/R509/Ocsp/Response.html +837 -0
  34. data/doc/R509/OidMapper.html +393 -0
  35. data/doc/R509/PrivateKey.html +1647 -0
  36. data/doc/R509/R509Error.html +134 -0
  37. data/doc/R509/Spki.html +1424 -0
  38. data/doc/R509/Subject.html +836 -0
  39. data/doc/R509/Validity.html +160 -0
  40. data/doc/R509/Validity/Checker.html +320 -0
  41. data/doc/R509/Validity/DefaultChecker.html +283 -0
  42. data/doc/R509/Validity/DefaultWriter.html +330 -0
  43. data/doc/R509/Validity/Status.html +561 -0
  44. data/doc/R509/Validity/Writer.html +394 -0
  45. data/doc/_index.html +501 -0
  46. data/doc/class_list.html +53 -0
  47. data/doc/css/common.css +1 -0
  48. data/doc/css/full_list.css +57 -0
  49. data/doc/css/style.css +328 -0
  50. data/doc/file.README.html +534 -0
  51. data/doc/file.r509.html +149 -0
  52. data/doc/file_list.html +58 -0
  53. data/doc/frames.html +28 -0
  54. data/doc/index.html +534 -0
  55. data/doc/js/app.js +208 -0
  56. data/doc/js/full_list.js +173 -0
  57. data/doc/js/jquery.js +4 -0
  58. data/doc/methods_list.html +1932 -0
  59. data/doc/top-level-namespace.html +112 -0
  60. data/lib/r509.rb +22 -0
  61. data/lib/r509/cert.rb +414 -0
  62. data/lib/r509/cert/extensions.rb +309 -0
  63. data/lib/r509/certificateauthority.rb +290 -0
  64. data/lib/r509/config.rb +407 -0
  65. data/lib/r509/crl.rb +379 -0
  66. data/lib/r509/csr.rb +324 -0
  67. data/lib/r509/exceptions.rb +5 -0
  68. data/lib/r509/io_helpers.rb +52 -0
  69. data/lib/r509/messagedigest.rb +49 -0
  70. data/lib/r509/ocsp.rb +85 -0
  71. data/lib/r509/oidmapper.rb +32 -0
  72. data/lib/r509/privatekey.rb +185 -0
  73. data/lib/r509/spki.rb +112 -0
  74. data/lib/r509/subject.rb +133 -0
  75. data/lib/r509/validity.rb +92 -0
  76. data/lib/r509/version.rb +4 -0
  77. data/r509.yaml +73 -0
  78. data/spec/cert/extensions_spec.rb +632 -0
  79. data/spec/cert_spec.rb +321 -0
  80. data/spec/certificate_authority_spec.rb +260 -0
  81. data/spec/config_spec.rb +349 -0
  82. data/spec/crl_spec.rb +215 -0
  83. data/spec/csr_spec.rb +302 -0
  84. data/spec/fixtures.rb +233 -0
  85. data/spec/fixtures/cert1.der +0 -0
  86. data/spec/fixtures/cert1.pem +24 -0
  87. data/spec/fixtures/cert1_public_key_modulus.txt +1 -0
  88. data/spec/fixtures/cert3.p12 +0 -0
  89. data/spec/fixtures/cert3.pem +28 -0
  90. data/spec/fixtures/cert3_key.pem +27 -0
  91. data/spec/fixtures/cert3_key_des3.pem +30 -0
  92. data/spec/fixtures/cert4.pem +14 -0
  93. data/spec/fixtures/cert5.pem +30 -0
  94. data/spec/fixtures/cert6.pem +26 -0
  95. data/spec/fixtures/cert_expired.pem +26 -0
  96. data/spec/fixtures/cert_not_yet_valid.pem +26 -0
  97. data/spec/fixtures/cert_san.pem +27 -0
  98. data/spec/fixtures/cert_san2.pem +22 -0
  99. data/spec/fixtures/config_pool_test_minimal.yaml +15 -0
  100. data/spec/fixtures/config_test.yaml +41 -0
  101. data/spec/fixtures/config_test_engine_key.yaml +7 -0
  102. data/spec/fixtures/config_test_engine_no_key_name.yaml +6 -0
  103. data/spec/fixtures/config_test_minimal.yaml +7 -0
  104. data/spec/fixtures/config_test_password.yaml +7 -0
  105. data/spec/fixtures/config_test_various.yaml +100 -0
  106. data/spec/fixtures/crl_list_file.txt +1 -0
  107. data/spec/fixtures/crl_with_reason.pem +17 -0
  108. data/spec/fixtures/csr1.der +0 -0
  109. data/spec/fixtures/csr1.pem +17 -0
  110. data/spec/fixtures/csr1_key.der +0 -0
  111. data/spec/fixtures/csr1_key.pem +27 -0
  112. data/spec/fixtures/csr1_key_encrypted_des3.pem +30 -0
  113. data/spec/fixtures/csr1_newlines.pem +32 -0
  114. data/spec/fixtures/csr1_no_begin_end.pem +15 -0
  115. data/spec/fixtures/csr1_public_key_modulus.txt +1 -0
  116. data/spec/fixtures/csr2.pem +15 -0
  117. data/spec/fixtures/csr2_key.pem +27 -0
  118. data/spec/fixtures/csr3.pem +16 -0
  119. data/spec/fixtures/csr4.pem +25 -0
  120. data/spec/fixtures/csr_dsa.pem +15 -0
  121. data/spec/fixtures/csr_invalid_signature.pem +13 -0
  122. data/spec/fixtures/dsa_key.pem +20 -0
  123. data/spec/fixtures/key4.pem +27 -0
  124. data/spec/fixtures/key4_encrypted_des3.pem +30 -0
  125. data/spec/fixtures/missing_key_identifier_ca.cer +21 -0
  126. data/spec/fixtures/missing_key_identifier_ca.key +27 -0
  127. data/spec/fixtures/ocsptest.r509.local.pem +27 -0
  128. data/spec/fixtures/ocsptest.r509.local_ocsp_request.der +0 -0
  129. data/spec/fixtures/ocsptest2.r509.local.pem +27 -0
  130. data/spec/fixtures/second_ca.cer +26 -0
  131. data/spec/fixtures/second_ca.key +27 -0
  132. data/spec/fixtures/spkac.der +0 -0
  133. data/spec/fixtures/spkac.txt +1 -0
  134. data/spec/fixtures/spkac_dsa.txt +1 -0
  135. data/spec/fixtures/stca.pem +22 -0
  136. data/spec/fixtures/stca_ocsp_request.der +0 -0
  137. data/spec/fixtures/stca_ocsp_response.der +0 -0
  138. data/spec/fixtures/test1.csr +17 -0
  139. data/spec/fixtures/test_ca.cer +22 -0
  140. data/spec/fixtures/test_ca.key +28 -0
  141. data/spec/fixtures/test_ca.p12 +0 -0
  142. data/spec/fixtures/test_ca_des3.key +30 -0
  143. data/spec/fixtures/test_ca_ocsp.cer +26 -0
  144. data/spec/fixtures/test_ca_ocsp.key +27 -0
  145. data/spec/fixtures/test_ca_ocsp.p12 +0 -0
  146. data/spec/fixtures/test_ca_ocsp_chain.txt +48 -0
  147. data/spec/fixtures/test_ca_ocsp_response.der +0 -0
  148. data/spec/fixtures/test_ca_subroot.cer +26 -0
  149. data/spec/fixtures/test_ca_subroot.key +27 -0
  150. data/spec/fixtures/test_ca_subroot_ocsp.cer +25 -0
  151. data/spec/fixtures/test_ca_subroot_ocsp.key +27 -0
  152. data/spec/fixtures/test_ca_subroot_ocsp_response.der +0 -0
  153. data/spec/fixtures/unknown_oid.csr +17 -0
  154. data/spec/message_digest_spec.rb +89 -0
  155. data/spec/ocsp_spec.rb +111 -0
  156. data/spec/oid_mapper_spec.rb +31 -0
  157. data/spec/privatekey_spec.rb +198 -0
  158. data/spec/spec_helper.rb +14 -0
  159. data/spec/spki_spec.rb +157 -0
  160. data/spec/subject_spec.rb +203 -0
  161. data/spec/validity_spec.rb +98 -0
  162. metadata +257 -0
@@ -0,0 +1,112 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+ <title>
7
+ Top Level Namespace
8
+
9
+ &mdash; Documentation by YARD 0.8.0
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ hasFrames = window.top.frames.main ? true : false;
19
+ relpath = '';
20
+ framesUrl = "frames.html#!" + escape(window.location.href);
21
+ </script>
22
+
23
+
24
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
25
+
26
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
27
+
28
+
29
+ </head>
30
+ <body>
31
+ <div id="header">
32
+ <div id="menu">
33
+
34
+ <a href="_index.html">Index</a> &raquo;
35
+
36
+
37
+ <span class="title">Top Level Namespace</span>
38
+
39
+
40
+ <div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
41
+ </div>
42
+
43
+ <div id="search">
44
+
45
+ <a class="full_list_link" id="class_list_link"
46
+ href="class_list.html">
47
+ Class List
48
+ </a>
49
+
50
+ <a class="full_list_link" id="method_list_link"
51
+ href="method_list.html">
52
+ Method List
53
+ </a>
54
+
55
+ <a class="full_list_link" id="file_list_link"
56
+ href="file_list.html">
57
+ File List
58
+ </a>
59
+
60
+ </div>
61
+ <div class="clear"></div>
62
+ </div>
63
+
64
+ <iframe id="search_frame"></iframe>
65
+
66
+ <div id="content"><h1>Top Level Namespace
67
+
68
+
69
+
70
+ </h1>
71
+
72
+ <dl class="box">
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+ </dl>
82
+ <div class="clear"></div>
83
+
84
+ <h2>Defined Under Namespace</h2>
85
+ <p class="children">
86
+
87
+
88
+ <strong class="modules">Modules:</strong> <span class='object_link'><a href="R509.html" title="R509 (module)">R509</a></span>
89
+
90
+
91
+
92
+
93
+ </p>
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+ </div>
104
+
105
+ <div id="footer">
106
+ Generated on Tue Oct 23 22:48:01 2012 by
107
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
108
+ 0.8.0 (ruby-1.9.3).
109
+ </div>
110
+
111
+ </body>
112
+ </html>
data/lib/r509.rb ADDED
@@ -0,0 +1,22 @@
1
+ # A module for building an easy to use CA. Includes CSR, Certificate, and CRL support.
2
+ module R509
3
+ require('r509/certificateauthority.rb')
4
+ require('r509/csr.rb')
5
+ require('r509/spki.rb')
6
+ require('r509/cert.rb')
7
+ require('r509/crl.rb')
8
+ require('r509/oidmapper.rb')
9
+ require('r509/ocsp.rb')
10
+ require('r509/config.rb')
11
+ require('r509/privatekey.rb')
12
+ require('r509/messagedigest.rb')
13
+ require('r509/subject.rb')
14
+ require('r509/validity.rb')
15
+ end
16
+
17
+ #add some global mappings we want available throughout r509
18
+ R509::OidMapper.batch_register([
19
+ { :oid => "2.5.4.15", :short_name => "businessCategory" },
20
+ { :oid => "1.3.6.1.4.1.311.60.2.1.2", :short_name => "jurisdictionOfIncorporationStateOrProvinceName" },
21
+ { :oid => "1.3.6.1.4.1.311.60.2.1.3", :short_name => "jurisdictionOfIncorporationCountryName" }
22
+ ])
data/lib/r509/cert.rb ADDED
@@ -0,0 +1,414 @@
1
+ require 'openssl'
2
+ require 'r509/exceptions'
3
+ require 'r509/io_helpers'
4
+ require 'r509/cert/extensions'
5
+
6
+ module R509
7
+ # The primary certificate object.
8
+ class Cert
9
+ include R509::IOHelpers
10
+
11
+ attr_reader :cert, :key
12
+
13
+ # @option opts [String,OpenSSL::X509::Certificate] :cert a cert
14
+ # @option opts [R509::PrivateKey,String] :key optional private key to supply. either an unencrypted PEM/DER string or an R509::PrivateKey object (use the latter if you need password/hardware support)
15
+ # @option opts [String] :pkcs12 a PKCS12 object containing both key and cert
16
+ # @option opts [String] :password password for PKCS12 or private key (if supplied)
17
+ def initialize(opts={})
18
+ if not opts.kind_of?(Hash)
19
+ raise ArgumentError, 'Must provide a hash of options'
20
+ end
21
+ if opts.has_key?(:pkcs12) and ( opts.has_key?(:key) or opts.has_key?(:cert) )
22
+ raise ArgumentError, "When providing pkcs12, do not pass cert or key"
23
+ elsif opts.has_key?(:pkcs12)
24
+ pkcs12 = OpenSSL::PKCS12.new( opts[:pkcs12], opts[:password] )
25
+ parse_certificate(pkcs12.certificate)
26
+ @key = R509::PrivateKey.new( :key => pkcs12.key )
27
+ elsif not opts.has_key?(:cert)
28
+ raise ArgumentError, 'Must provide :cert or :pkcs12'
29
+ else
30
+ csr_check(opts[:cert])
31
+ parse_certificate(opts[:cert])
32
+ end
33
+
34
+ if opts.has_key?(:key)
35
+ if opts[:key].kind_of?(R509::PrivateKey)
36
+ @key = opts[:key]
37
+ else
38
+ @key = R509::PrivateKey.new( :key => opts[:key], :password => opts[:password] )
39
+ end
40
+ end
41
+ if not @key.nil?
42
+ if not @cert.public_key.to_s == @key.public_key.to_s then
43
+ raise R509Error, 'Key does not match cert.'
44
+ end
45
+ end
46
+ end
47
+
48
+ # Helper method to quickly load a cert from the filesystem
49
+ #
50
+ # @param [String] filename Path to file you want to load
51
+ # @return [R509::Cert] cert object
52
+ def self.load_from_file( filename )
53
+ return R509::Cert.new(:cert => IOHelpers.read_data(filename) )
54
+ end
55
+
56
+
57
+
58
+ # Converts the Cert into the PEM format
59
+ #
60
+ # @return [String] the Cert converted into PEM format.
61
+ def to_pem
62
+ if @cert.kind_of?(OpenSSL::X509::Certificate)
63
+ return @cert.to_pem.chomp
64
+ end
65
+ end
66
+
67
+ alias :to_s :to_pem
68
+
69
+ # Converts the Cert into the DER format
70
+ #
71
+ # @return [String] the Cert converted into DER format.
72
+ def to_der
73
+ if @cert.kind_of?(OpenSSL::X509::Certificate)
74
+ return @cert.to_der
75
+ end
76
+ end
77
+
78
+ # Returns beginning (notBefore) of certificate validity period
79
+ #
80
+ # @return [Time] time object
81
+ def not_before
82
+ @cert.not_before
83
+ end
84
+
85
+ # Returns the serial number of the certificate in decimal form
86
+ #
87
+ # @return [Integer]
88
+ def serial
89
+ @cert.serial.to_i
90
+ end
91
+
92
+ # Returns ending (notAfter) of certificate validity period
93
+ #
94
+ # @return [Time] time object
95
+ def not_after
96
+ @cert.not_after
97
+ end
98
+
99
+ # Returns the certificate public key
100
+ #
101
+ # @return [OpenSSL::PKey::RSA] public key object
102
+ def public_key
103
+ @cert.public_key
104
+ end
105
+
106
+ # Returns the issuer
107
+ #
108
+ # @return [OpenSSL::X509::Name] issuer object. Can be parsed as string easily
109
+ def issuer
110
+ @cert.issuer
111
+ end
112
+
113
+ # @return [String] The common name (CN) component of the issuer
114
+ def issuer_cn
115
+ return nil if self.issuer.nil?
116
+
117
+ self.issuer.to_a.each do |part, value, length|
118
+ return value if part.upcase == 'CN'
119
+ end
120
+
121
+ # return nil if we didn't find a CN part
122
+ return nil
123
+ end
124
+
125
+ # Returns the certificate fingerprint with the specified algorithm (default sha1)
126
+ #
127
+ # @param [String] algorithm Which algorithm to use for the fingerprint. See R509::MessageDigest for supported algorithm names
128
+ # @return [String] hex digest of the certificate
129
+ def fingerprint(algorithm='sha1')
130
+ message_digest = R509::MessageDigest.new(algorithm)
131
+ md = message_digest.digest
132
+ md.update(@cert.to_der)
133
+ md.to_s
134
+ end
135
+
136
+ # Returns whether the current time is between the notBefore and notAfter times in
137
+ # the certificate.
138
+ #
139
+ # @return [Boolean]
140
+ def valid?
141
+ valid_at?(Time.now)
142
+ end
143
+
144
+ # Returns whether the certificate was between its notBefore and notAfter at the time provided
145
+ #
146
+ # @param [Time,Integer] time Time object or integer timestamp
147
+ # @return [Boolean]
148
+ def valid_at?(time)
149
+ if time.kind_of?(Integer)
150
+ time = Time.at(time)
151
+ end
152
+
153
+ if (self.not_after < time) or (self.not_before > time)
154
+ false
155
+ else
156
+ true
157
+ end
158
+ end
159
+
160
+ # Returns the subject
161
+ #
162
+ # @return [OpenSSL::X509::Name] subject object. Can be parsed as string easily
163
+ def subject
164
+ @cert.subject
165
+ end
166
+
167
+ # @return [Boolean] Boolean of whether the object contains a private key
168
+ def has_private_key?
169
+ if not @key.nil?
170
+ true
171
+ else
172
+ false
173
+ end
174
+ end
175
+
176
+ # @return [Array] list of SAN DNS names
177
+ def san_names
178
+ if self.subject_alternative_name.nil?
179
+ return []
180
+ else
181
+ return self.subject_alternative_name.dns_names
182
+ end
183
+ end
184
+
185
+ # Returns the CN component, if any, of the subject
186
+ #
187
+ # @return [String]
188
+ def subject_cn()
189
+ return self.subject_component('CN')
190
+ end
191
+
192
+ # Returns subject component
193
+ #
194
+ # @return [String] value of the subject component requested
195
+ def subject_component short_name
196
+ match = @cert.subject.to_a.find { |x| x[0] == short_name }
197
+ return nil if match.nil?
198
+ return match[1]
199
+ end
200
+
201
+ # Return the CN, as well as all the subject alternative names (SANs).
202
+ #
203
+ # @return [Array] the array of names. Returns an empty array if
204
+ # there are no names, at all.
205
+ def subject_names
206
+ ret = []
207
+ ret << subject_cn unless subject_cn.nil?
208
+ ret.concat( self.san_names )
209
+
210
+ return ret.sort.uniq
211
+ end
212
+
213
+ # Returns whether the public key is RSA
214
+ #
215
+ # @return [Boolean] true if the public key is RSA, false otherwise
216
+ def rsa?
217
+ @cert.public_key.kind_of?(OpenSSL::PKey::RSA)
218
+ end
219
+
220
+ # Returns whether the public key is DSA
221
+ #
222
+ # @return [Boolean] true if the public key is DSA, false otherwise
223
+ def dsa?
224
+ @cert.public_key.kind_of?(OpenSSL::PKey::DSA)
225
+ end
226
+
227
+ # Returns the bit strength of the key used to create the certificate
228
+ #
229
+ # @return [Integer] integer value of bit strength
230
+ def bit_strength
231
+ if self.rsa?
232
+ return @cert.public_key.n.num_bits
233
+ elsif self.dsa?
234
+ return @cert.public_key.p.num_bits
235
+ end
236
+ end
237
+
238
+ # Returns signature algorithm
239
+ #
240
+ # @return [String] value of the signature algorithm. E.g. sha1WithRSAEncryption, sha256WithRSAEncryption, md5WithRSAEncryption
241
+ def signature_algorithm
242
+ @cert.signature_algorithm
243
+ end
244
+
245
+ # Returns key algorithm (RSA or DSA)
246
+ #
247
+ # @return [String] value of the key algorithm. RSA or DSA
248
+ def key_algorithm
249
+ if self.rsa?
250
+ "RSA"
251
+ elsif self.dsa?
252
+ "DSA"
253
+ end
254
+ end
255
+
256
+ # Writes the Cert into the PEM format
257
+ # @param [String, #write] filename_or_io Either a string of the path for
258
+ # the file that you'd like to write, or an IO-like object.
259
+ def write_pem(filename_or_io)
260
+ write_data(filename_or_io, @cert.to_pem)
261
+ end
262
+
263
+ # Writes the Cert into the DER format
264
+ # @param [String, #write] filename_or_io Either a string of the path for
265
+ # the file that you'd like to write, or an IO-like object.
266
+ def write_der(filename_or_io)
267
+ write_data(filename_or_io, @cert.to_der)
268
+ end
269
+
270
+ # Writes cert and key into PKCS12 format using OpenSSL defaults for encryption (des3)
271
+ # @param [String, #write] filename_or_io Either a string of the path for
272
+ # the file that you'd like to write, or an IO-like object.
273
+ # @param [String] password password
274
+ # @param [String] friendly_name An optional string to encode in the PKCS12 for friendlyName. defaults to "r509 pkcs12"
275
+ def write_pkcs12(filename_or_io,password,friendly_name='r509 pkcs12')
276
+ if @key.nil?
277
+ raise R509::R509Error, "Writing a PKCS12 requires both key and cert"
278
+ end
279
+ pkcs12 = OpenSSL::PKCS12.create(password,friendly_name,@key.key,@cert)
280
+ write_data(filename_or_io, pkcs12.to_der)
281
+ end
282
+
283
+ # Checks the given CRL for this certificate's serial number. Note that this does NOT
284
+ # check to verify that the CRL you're checking is signed by the same CA as the cert
285
+ # so do that check yourself
286
+ #
287
+ # @param [R509::Crl] r509_crl A CRL from the CA that issued this certificate.
288
+ def is_revoked_by_crl?( r509_crl )
289
+ return r509_crl.revoked?( self.serial )
290
+ end
291
+
292
+ # Return the certificate extensions
293
+ #
294
+ # @return [Array] an array of hashes representing the extensions in the cert
295
+ def extensions
296
+ if @extensions.nil?
297
+ @extensions = Hash.new
298
+ @cert.extensions.each { |extension|
299
+ hash = {'value' => extension.value, 'critical' => extension.critical?}
300
+ @extensions[extension.oid] = hash
301
+ }
302
+ end
303
+ @extensions
304
+ end
305
+
306
+ # Returns the certificate extensions as a hash of R509::Cert::Extensions
307
+ # specific objects.
308
+ #
309
+ # @return [Hash] A hash, in which the values are classes from the
310
+ # R509::Cert::Extensions module, each specific to the extension. The hash
311
+ # is keyed with the R509 extension class. Extensions without an R509
312
+ # implementation are ignored (see #get_unknown_extensions).
313
+ def r509_extensions
314
+ if @r509_extensions.nil?
315
+ @r509_extensions = Extensions.wrap_openssl_extensions( self.cert.extensions )
316
+ end
317
+
318
+ return @r509_extensions
319
+ end
320
+
321
+ # Returns an array of OpenSSL::X509::Extension objects representing the
322
+ # extensions that do not have R509 implementations.
323
+ #
324
+ # @return [Array] An array of OpenSSL::X509::Extension objects.
325
+ def unknown_extensions
326
+ return Extensions.get_unknown_extensions( self.cert.extensions )
327
+ end
328
+
329
+ #
330
+ # Shortcuts to extensions
331
+ #
332
+
333
+ # Returns this object's BasicConstraints extension as an R509 extension
334
+ #
335
+ # @return [R509::Cert::Extensions::BasicConstraints] The object, or nil
336
+ # if this cert does not have a BasicConstraints extension.
337
+ def basic_constraints
338
+ return r509_extensions[R509::Cert::Extensions::BasicConstraints]
339
+ end
340
+
341
+ # Returns this object's KeyUsage extension as an R509 extension
342
+ #
343
+ # @return [R509::Cert::Extensions::KeyUsage] The object, or nil
344
+ # if this cert does not have a KeyUsage extension.
345
+ def key_usage
346
+ return r509_extensions[R509::Cert::Extensions::KeyUsage]
347
+ end
348
+
349
+ # Returns this object's ExtendedKeyUsage extension as an R509 extension
350
+ #
351
+ # @return [R509::Cert::Extensions::ExtendedKeyUsage] The object, or nil
352
+ # if this cert does not have a ExtendedKeyUsage extension.
353
+ def extended_key_usage
354
+ return r509_extensions[R509::Cert::Extensions::ExtendedKeyUsage]
355
+ end
356
+
357
+ # Returns this object's SubjectKeyIdentifier extension as an R509 extension
358
+ #
359
+ # @return [R509::Cert::Extensions::SubjectKeyIdentifier] The object, or nil
360
+ # if this cert does not have a SubjectKeyIdentifier extension.
361
+ def subject_key_identifier
362
+ return r509_extensions[R509::Cert::Extensions::SubjectKeyIdentifier]
363
+ end
364
+
365
+ # Returns this object's AuthorityKeyIdentifier extension as an R509 extension
366
+ #
367
+ # @return [R509::Cert::Extensions::AuthorityKeyIdentifier] The object, or nil
368
+ # if this cert does not have a AuthorityKeyIdentifier extension.
369
+ def authority_key_identifier
370
+ return r509_extensions[R509::Cert::Extensions::AuthorityKeyIdentifier]
371
+ end
372
+
373
+ # Returns this object's SubjectAlternativeName extension as an R509 extension
374
+ #
375
+ # @return [R509::Cert::Extensions::SubjectAlternativeName] The object, or nil
376
+ # if this cert does not have a SubjectAlternativeName extension.
377
+ def subject_alternative_name
378
+ return r509_extensions[R509::Cert::Extensions::SubjectAlternativeName]
379
+ end
380
+
381
+ # Returns this object's AuthorityInfoAccess extension as an R509 extension
382
+ #
383
+ # @return [R509::Cert::Extensions::AuthorityInfoAccess] The object, or nil
384
+ # if this cert does not have a AuthorityInfoAccess extension.
385
+ def authority_info_access
386
+ return r509_extensions[R509::Cert::Extensions::AuthorityInfoAccess]
387
+ end
388
+
389
+ # Returns this object's CrlDistributionPoints extension as an R509 extension
390
+ #
391
+ # @return [R509::Cert::Extensions::CrlDistributionPoints] The object, or nil
392
+ # if this cert does not have a CrlDistributionPoints extension.
393
+ def crl_distribution_points
394
+ return r509_extensions[R509::Cert::Extensions::CrlDistributionPoints]
395
+ end
396
+
397
+ private
398
+ # This method exists only to provide a friendlier error msg if you attempt to
399
+ # parse a CSR as a certificate. All for Sean
400
+ def csr_check(cert)
401
+ begin
402
+ csr = OpenSSL::X509::Request.new cert
403
+ raise R509Error, 'Cert provided is actually a certificate signing request.'
404
+ rescue OpenSSL::X509::RequestError
405
+ # do nothing, it shouldn't be a CSR anyway!
406
+ end
407
+ end
408
+
409
+ def parse_certificate(cert)
410
+ @cert = OpenSSL::X509::Certificate.new cert
411
+ end
412
+
413
+ end
414
+ end