pkernel_jce 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.ruby-version +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +56 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/jars/bcmail-jdk15on-157.jar +0 -0
- data/jars/bcpg-jdk15on-157.jar +0 -0
- data/jars/bcpkix-jdk15on-157.jar +0 -0
- data/jars/bcprov-ext-jdk15on-157.jar +0 -0
- data/jars/bcprov-jdk15on-157.jar +0 -0
- data/lib/pkernel_jce/bc_helpers.rb +51 -0
- data/lib/pkernel_jce/certificate.rb +467 -0
- data/lib/pkernel_jce/certificate_owner.rb +90 -0
- data/lib/pkernel_jce/crl.rb +221 -0
- data/lib/pkernel_jce/csr.rb +126 -0
- data/lib/pkernel_jce/error.rb +7 -0
- data/lib/pkernel_jce/global.rb +17 -0
- data/lib/pkernel_jce/identity.rb +333 -0
- data/lib/pkernel_jce/io_utils.rb +45 -0
- data/lib/pkernel_jce/keypair.rb +359 -0
- data/lib/pkernel_jce/ocsp.rb +415 -0
- data/lib/pkernel_jce/provider.rb +40 -0
- data/lib/pkernel_jce/rfc3161.rb +389 -0
- data/lib/pkernel_jce/utils.rb +59 -0
- data/lib/pkernel_jce/version.rb +3 -0
- data/lib/pkernel_jce.rb +102 -0
- data/pkernel_jce.gemspec +45 -0
- metadata +146 -0
@@ -0,0 +1,467 @@
|
|
1
|
+
|
2
|
+
require 'pkernel'
|
3
|
+
require_relative 'provider'
|
4
|
+
require_relative 'utils'
|
5
|
+
require_relative 'global'
|
6
|
+
require_relative 'error'
|
7
|
+
require_relative 'certificate_owner'
|
8
|
+
|
9
|
+
require 'active_support/core_ext/time'
|
10
|
+
|
11
|
+
|
12
|
+
module PkernelJce
|
13
|
+
module Certificate
|
14
|
+
|
15
|
+
module KeyUsage
|
16
|
+
# bouncycastle v1.57
|
17
|
+
DIGITAL_SIGNATURE = Java::OrgBouncycastleAsn1X509::KeyUsage::digitalSignature
|
18
|
+
NON_REPUDIATION = Java::OrgBouncycastleAsn1X509::KeyUsage::nonRepudiation
|
19
|
+
KEY_ENCIPHERMENT = Java::OrgBouncycastleAsn1X509::KeyUsage::keyEncipherment
|
20
|
+
DATA_ENCIPHERMENT = Java::OrgBouncycastleAsn1X509::KeyUsage::dataEncipherment
|
21
|
+
KEY_AGREEMENT = Java::OrgBouncycastleAsn1X509::KeyUsage::keyAgreement
|
22
|
+
KEY_CERT_SIGN = Java::OrgBouncycastleAsn1X509::KeyUsage::keyCertSign
|
23
|
+
CRL_SIGN = Java::OrgBouncycastleAsn1X509::KeyUsage::cRLSign
|
24
|
+
# only meaningful of KEY_AGREEMENT is set
|
25
|
+
ENCIPHER_ONLY = Java::OrgBouncycastleAsn1X509::KeyUsage::encipherOnly
|
26
|
+
DECIPHER_ONLY = Java::OrgBouncycastleAsn1X509::KeyUsage::decipherOnly
|
27
|
+
|
28
|
+
DEF_USER_IDENTITY = DIGITAL_SIGNATURE | NON_REPUDIATION | KEY_ENCIPHERMENT | KEY_AGREEMENT
|
29
|
+
DEF_USER_DATA_SEC = DATA_ENCIPHERMENT | ENCIPHER_ONLY | DECIPHER_ONLY
|
30
|
+
DEF_ISSUER = DIGITAL_SIGNATURE | NON_REPUDIATION | KEY_ENCIPHERMENT | CRL_SIGN | KEY_CERT_SIGN
|
31
|
+
end
|
32
|
+
# end module CertKeyUsage
|
33
|
+
|
34
|
+
module ExtKeyUsage
|
35
|
+
ANY_EXT_KEY_USAGE = org.bouncycastle.asn1.x509.KeyPurposeId::anyExtendedKeyUsage
|
36
|
+
TLS_SERVER_AUTH = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_serverAuth
|
37
|
+
TLS_CLIENT_AUTH = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_clientAuth
|
38
|
+
CODE_SIGNING = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_codeSigning
|
39
|
+
EMAIL_PROTECTION = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_emailProtection
|
40
|
+
TIMESTAMPING = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_timeStamping
|
41
|
+
OCSP_SIGNING = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_OCSPSigning
|
42
|
+
DVCS = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_dvcs
|
43
|
+
SPGP_CERT_AA_SERVER_AUTH = org.bouncycastle.asn1.x509.KeyPurposeId::id_kp_sbgpCertAAServerAuth
|
44
|
+
end
|
45
|
+
# end CertExtKeyUsage
|
46
|
+
|
47
|
+
|
48
|
+
def generate(params = {}, &block)
|
49
|
+
|
50
|
+
raise PkernelJce::Error, "Block is required for certificate generation function" if block.nil?
|
51
|
+
|
52
|
+
PkernelJce::GConf.instance.glog.debug "Certificate generate parameters: #{params.inspect}"
|
53
|
+
owner = params[:owner]
|
54
|
+
pubKey = params[:pubKey]
|
55
|
+
serial = params[:serial]
|
56
|
+
kProv = params[:keypair_provider]
|
57
|
+
cProv = params[:cert_provider]
|
58
|
+
issuer = params[:issuer]
|
59
|
+
matchIssuerValidity = params[:match_issuer_validity] || true
|
60
|
+
|
61
|
+
issuer = false if issuer.nil?
|
62
|
+
|
63
|
+
pubKey = PkernelJce::KeyPair.public_key(pubKey)
|
64
|
+
|
65
|
+
if cProv.nil?
|
66
|
+
cProv = PkernelJce::Provider.add_provider(PkernelJce::Provider::DefProvider)
|
67
|
+
else
|
68
|
+
cProv = PkernelJce::Provider.add_provider(cProv)
|
69
|
+
end
|
70
|
+
|
71
|
+
if kProv.nil?
|
72
|
+
kProv = PkernelJce::Provider.add_provider(PkernelJce::Provider::DefProvider)
|
73
|
+
else
|
74
|
+
kProv = PkernelJce::Provider.add_provider(kProv)
|
75
|
+
end
|
76
|
+
|
77
|
+
extUtils = org.bouncycastle.cert.bc.BcX509ExtensionUtils.new
|
78
|
+
|
79
|
+
if serial.nil? or serial.empty?
|
80
|
+
serial = block.call(:serial)
|
81
|
+
end
|
82
|
+
|
83
|
+
if serial.is_a?(java.math.BigInteger)
|
84
|
+
else
|
85
|
+
serial = java.math.BigInteger.new(serial,16)
|
86
|
+
end
|
87
|
+
|
88
|
+
signHash = block.call(:signHash)
|
89
|
+
issuerKey = block.call(:issuerKey)
|
90
|
+
issuerCert = block.call(:issuerCert)
|
91
|
+
|
92
|
+
issuerKey = PkernelJce::KeyPair.private_key(issuerKey)
|
93
|
+
if issuerKey.nil?
|
94
|
+
raise PkernelJce::Error, "Issuer key cannot be nil"
|
95
|
+
end
|
96
|
+
|
97
|
+
signAlgo = PkernelJce::KeyPair.derive_signing_algo(issuerKey, signHash)
|
98
|
+
signer = org.bouncycastle.operator.jcajce.JcaContentSignerBuilder.new(signAlgo).setProvider(kProv).build(issuerKey)
|
99
|
+
x500Name = owner.to_x500_subject
|
100
|
+
|
101
|
+
if not issuerCert.nil?
|
102
|
+
|
103
|
+
issuerCert = issuerCert.to_java_cert if issuerCert.java_kind_of?(org.bouncycastle.cert.X509CertificateHolder)
|
104
|
+
|
105
|
+
validFrom, validTo = calculate_validity(params) do |from, to|
|
106
|
+
if matchIssuerValidity
|
107
|
+
|
108
|
+
PkernelJce::GConf.instance.glog.debug "Match issuer validity against issuer certificate is activated."
|
109
|
+
PkernelJce::GConf.instance.glog.debug "Issuer Cert : #{issuerCert.subject_dn.to_s} / #{issuerCert.not_before} / #{issuerCert.not_after}"
|
110
|
+
|
111
|
+
if from.to_java_date.before(issuerCert.not_before)
|
112
|
+
PkernelJce::GConf.instance.glog.warn "Certificate valid from has adjusted to match issuer valid from: #{from} [User requested] / #{issuerCert.not_before} [Adjusted to issuer]"
|
113
|
+
from = issuerCert.not_before
|
114
|
+
end
|
115
|
+
|
116
|
+
if to.to_java_date.after(issuerCert.not_after)
|
117
|
+
PkernelJce::GConf.instance.glog.warn "Certificate valid to has adjusted to match issuer valid to: #{to} [User requested] / #{issuerCert.not_after} [Adjusted to issuer]"
|
118
|
+
to = issuerCert.not_after
|
119
|
+
end
|
120
|
+
|
121
|
+
[from, to]
|
122
|
+
else
|
123
|
+
[from, to]
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
certGen = org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder.new(issuerCert, serial, validFrom, validTo, x500Name, pubKey)
|
128
|
+
# generate authority key identifier
|
129
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo.getInstance(issuerCert.getPublicKey.getEncoded)))
|
130
|
+
else
|
131
|
+
|
132
|
+
validFrom, validTo = calculate_validity(params)
|
133
|
+
|
134
|
+
certGen = org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder.new(x500Name, serial, validFrom, validTo, x500Name, pubKey)
|
135
|
+
# generate authority key identifier
|
136
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo.getInstance(pubKey.getEncoded)))
|
137
|
+
end
|
138
|
+
|
139
|
+
keyUsage = block.call(:keyUsage)
|
140
|
+
if issuer
|
141
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::basicConstraints, true, org.bouncycastle.asn1.x509.BasicConstraints.new(true))
|
142
|
+
if not keyUsage.nil?
|
143
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::keyUsage, false, org.bouncycastle.asn1.x509.KeyUsage.new(keyUsage))
|
144
|
+
else
|
145
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::keyUsage, false, org.bouncycastle.asn1.x509.KeyUsage.new(KeyUsage::DEF_ISSUER))
|
146
|
+
end
|
147
|
+
else
|
148
|
+
if not keyUsage.nil?
|
149
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::keyUsage, false, org.bouncycastle.asn1.x509.KeyUsage.new(keyUsage))
|
150
|
+
else
|
151
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::keyUsage, false, org.bouncycastle.asn1.x509.KeyUsage.new(KeyUsage::DEF_USER_IDENTITY))
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
extKeyUsage = block.call(:extKeyUsage)
|
156
|
+
if not extKeyUsage.nil?
|
157
|
+
if extKeyUsage.is_a?(Hash)
|
158
|
+
# allow user to give eku -> true/false
|
159
|
+
# Since timestamping required this extension to be true, not sure others
|
160
|
+
extKeyUsage.each do |k,v|
|
161
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::extendedKeyUsage, v, org.bouncycastle.asn1.x509.ExtendedKeyUsage.new(k))
|
162
|
+
end
|
163
|
+
elsif extKeyUsage.is_a?(Array)
|
164
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::extendedKeyUsage, false, org.bouncycastle.asn1.x509.ExtendedKeyUsage.new(extKeyUsage.to_vector))
|
165
|
+
else
|
166
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::extendedKeyUsage, false, org.bouncycastle.asn1.x509.ExtendedKeyUsage.new([extKeyUsage].to_vector))
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
#
|
171
|
+
# handle alternative name
|
172
|
+
#
|
173
|
+
altName = []
|
174
|
+
if owner.emails.length > 0
|
175
|
+
owner.emails.each do |e|
|
176
|
+
altName << org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName::rfc822Name,e)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
owner.dns_names.each do |n|
|
181
|
+
altName << org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName::dNSName,n)
|
182
|
+
end
|
183
|
+
|
184
|
+
if altName.length > 0
|
185
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::subjectAlternativeName, false, org.bouncycastle.asn1.x509.GeneralNames.new(altName.to_java(org.bouncycastle.asn1.x509.GeneralName)) )
|
186
|
+
end
|
187
|
+
#
|
188
|
+
# Done alternative name
|
189
|
+
#
|
190
|
+
|
191
|
+
#
|
192
|
+
# handle CRL distribution point
|
193
|
+
#
|
194
|
+
crl = block.call(:crls)
|
195
|
+
if not crl.nil?
|
196
|
+
crls = []
|
197
|
+
if crl.is_a?(Array)
|
198
|
+
crl.each do |c|
|
199
|
+
crls << org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName::uniformResourceIdentifier, org.bouncycastle.asn1.DERIA5String.new(c));
|
200
|
+
end
|
201
|
+
gns = org.bouncycastle.asn1.x509.GeneralNames.new(crls.to_java(org.bouncycastle.asn1.x509.GeneralName));
|
202
|
+
else
|
203
|
+
gn = org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName::uniformResourceIdentifier, org.bouncycastle.asn1.DERIA5String.new(crl));
|
204
|
+
gns = org.bouncycastle.asn1.x509.GeneralNames.new(gn);
|
205
|
+
end
|
206
|
+
|
207
|
+
dpn = org.bouncycastle.asn1.x509.DistributionPointName.new(gns);
|
208
|
+
dp = org.bouncycastle.asn1.x509.DistributionPoint.new(dpn,nil,nil);
|
209
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.X509Extensions::CRLDistributionPoints,false,org.bouncycastle.asn1.DERSequence.new(dp));
|
210
|
+
end
|
211
|
+
# done adding CRL distribution point
|
212
|
+
|
213
|
+
|
214
|
+
#
|
215
|
+
# handle OCSP
|
216
|
+
#
|
217
|
+
ocsp = block.call(:ocsp)
|
218
|
+
if not ocsp.nil? and not ocsp.empty?
|
219
|
+
ocspName = org.bouncycastle.asn1.x509.GeneralName.new(org.bouncycastle.asn1.x509.GeneralName.uniformResourceIdentifier, ocsp);
|
220
|
+
authorityInformationAccess = org.bouncycastle.asn1.x509.AuthorityInformationAccess.new(org.bouncycastle.asn1.x509.X509ObjectIdentifiers.ocspAccessMethod, ocspName);
|
221
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.X509Extensions::AuthorityInfoAccess, false, authorityInformationAccess);
|
222
|
+
end
|
223
|
+
# done OCSP
|
224
|
+
|
225
|
+
# Let's generate subject key ID as default...
|
226
|
+
certGen.addExtension(org.bouncycastle.asn1.x509.Extension::subjectKeyIdentifier, false, extUtils.createSubjectKeyIdentifier(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo.getInstance(pubKey.getEncoded)))
|
227
|
+
|
228
|
+
cert = org.bouncycastle.cert.jcajce.JcaX509CertificateConverter.new().setProvider(cProv).getCertificate(certGen.build(signer))
|
229
|
+
cert
|
230
|
+
|
231
|
+
end
|
232
|
+
# end generate
|
233
|
+
|
234
|
+
def dump(cert, params = {})
|
235
|
+
if cert.nil?
|
236
|
+
raise PkernelJce::Error, "Certificate object to be written is nil"
|
237
|
+
end
|
238
|
+
|
239
|
+
file = params[:file]
|
240
|
+
baos = java.io.ByteArrayOutputStream.new
|
241
|
+
|
242
|
+
if not file.nil?
|
243
|
+
PkernelJce::GConf.instance.glog.debug "Dump certificate to file '#{file}'"
|
244
|
+
writer = org.bouncycastle.openssl.jcajce.JcaPEMWriter.new(java.io.OutputStreamWriter.new(java.io.FileOutputStream.new(file)))
|
245
|
+
else
|
246
|
+
PkernelJce::GConf.instance.glog.debug "Dump certificate to memory"
|
247
|
+
writer = org.bouncycastle.openssl.jcajce.JcaPEMWriter.new(java.io.OutputStreamWriter.new(baos))
|
248
|
+
end
|
249
|
+
|
250
|
+
begin
|
251
|
+
writer.writeObject(cert)
|
252
|
+
ensure
|
253
|
+
writer.flush
|
254
|
+
writer.close
|
255
|
+
end
|
256
|
+
|
257
|
+
if file.nil?
|
258
|
+
baos.toByteArray
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
262
|
+
# end write to
|
263
|
+
|
264
|
+
|
265
|
+
def load(options = {})
|
266
|
+
#is = options[:inputStream]
|
267
|
+
#if is.nil?
|
268
|
+
# raise PkernelJce::Error, "InputStream to load certificate is nil"
|
269
|
+
#end
|
270
|
+
|
271
|
+
file = options[:file]
|
272
|
+
bin = options[:bin]
|
273
|
+
baos = java.io.ByteArrayOutputStream.new
|
274
|
+
|
275
|
+
if not file.nil? and not file.empty?
|
276
|
+
PkernelJce::GConf.instance.glog.debug "Load certificate from #{file}"
|
277
|
+
f = java.io.File.new(file)
|
278
|
+
if f.exists?
|
279
|
+
b = Java::byte[f.length].new
|
280
|
+
dis = java.io.DataInputStream.new(java.io.FileInputStream.new(f))
|
281
|
+
dis.readFully(b)
|
282
|
+
dis.close
|
283
|
+
|
284
|
+
baos.write(b)
|
285
|
+
else
|
286
|
+
raise PkernelJce::Error, "File '#{f.absolute_path}' not found"
|
287
|
+
end
|
288
|
+
|
289
|
+
elsif not bin.nil?
|
290
|
+
PkernelJce::GConf.instance.glog.debug "Load certificate from memory"
|
291
|
+
baos.write(bin)
|
292
|
+
else
|
293
|
+
raise PkernelJce::Error, "No bin or file input is given to load"
|
294
|
+
end
|
295
|
+
|
296
|
+
reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.ByteArrayInputStream.new(baos.toByteArray)))
|
297
|
+
obj = reader.readObject
|
298
|
+
# object here shall be org.bouncycastle.cert.X509CertificateHolder
|
299
|
+
# Hence other place using Java Certificate object shall call to_java_cert on this object
|
300
|
+
obj
|
301
|
+
#org.bouncycastle.cert.jcajce.JcaX509CertificateConverter.new.setProvider(PkernelJce::Provider::DefProvider).getCertificate(obj)
|
302
|
+
end
|
303
|
+
# end read_from
|
304
|
+
|
305
|
+
def Certificate.is_self_signed?(cert)
|
306
|
+
if cert.nil?
|
307
|
+
false
|
308
|
+
else
|
309
|
+
begin
|
310
|
+
cert.verify(cert.public_key)
|
311
|
+
true
|
312
|
+
rescue Exception
|
313
|
+
false
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
def Certificate.is_issuer_cert?(cert)
|
319
|
+
if cert.nil?
|
320
|
+
false
|
321
|
+
else
|
322
|
+
cert = Certificate.ensure_java_cert(cert)
|
323
|
+
(cert.getKeyUsage[5] and cert.getBasicConstraints != -1)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
# end is_issuer_cert?
|
327
|
+
|
328
|
+
def Certificate.ensure_java_cert(cert)
|
329
|
+
if cert.nil?
|
330
|
+
raise PkernelJce::Error, "Certificate for conversion to java is nil"
|
331
|
+
else
|
332
|
+
case cert
|
333
|
+
when java.security.cert.Certificate
|
334
|
+
cert
|
335
|
+
when Java::OrgBouncycastleCert::X509CertificateHolder
|
336
|
+
cert.to_java_cert
|
337
|
+
else
|
338
|
+
raise PkernelJce::Error, "Unknown certificate type '#{cert.class}'"
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
Certificate.singleton_class.send(:alias_method, :to_java_cert, :ensure_java_cert)
|
343
|
+
# end ensure_java_cert
|
344
|
+
|
345
|
+
def Certificate.ensure_bc_cert(cert)
|
346
|
+
if cert.nil?
|
347
|
+
raise PkernelJce::Error, "Certificate for conversion to bc is nil"
|
348
|
+
else
|
349
|
+
if cert.is_a?(Array)
|
350
|
+
cert.map! do |c|
|
351
|
+
case c
|
352
|
+
when java.security.cert.Certificate
|
353
|
+
c.to_bc_cert_holder
|
354
|
+
when Java::OrgBouncycastleCert::X509CertificateHolder
|
355
|
+
c
|
356
|
+
else
|
357
|
+
raise PkernelJce::Error, "Unknown certificate type '#{c.class}'"
|
358
|
+
end
|
359
|
+
end
|
360
|
+
cert
|
361
|
+
else
|
362
|
+
case cert
|
363
|
+
when java.security.cert.Certificate
|
364
|
+
cert.to_bc_cert_holder
|
365
|
+
when Java::OrgBouncycastleCert::X509CertificateHolder
|
366
|
+
cert
|
367
|
+
else
|
368
|
+
raise PkernelJce::Error, "Unknown certificate type '#{cert.class}'"
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
373
|
+
Certificate.singleton_class.send(:alias_method, :to_bc_cert, :ensure_bc_cert)
|
374
|
+
# end ensure_bc_cert
|
375
|
+
#
|
376
|
+
|
377
|
+
def Certificate.public_key(cert)
|
378
|
+
if cert.nil?
|
379
|
+
raise PkernelJce::Error, "Object pass to public_key on certificate is nil"
|
380
|
+
end
|
381
|
+
|
382
|
+
case cert
|
383
|
+
when java.security.cert.Certificate
|
384
|
+
cert.public_key
|
385
|
+
when Java::OrgBouncycastleCert::X509CertificateHolder
|
386
|
+
PkernelJce::KeyPair.public_key(cert.subject_public_key_info)
|
387
|
+
else
|
388
|
+
raise PkernelJce::Error, "Unknown certificate type '#{cert.class}'"
|
389
|
+
end
|
390
|
+
|
391
|
+
end
|
392
|
+
|
393
|
+
def Certificate.is_cert_object?(obj)
|
394
|
+
if obj.nil?
|
395
|
+
false
|
396
|
+
else
|
397
|
+
case obj
|
398
|
+
when java.security.cert.Certificate, Java::OrgBouncycastleCert::X509CertificateHolder, Java::OrgBouncycastleJcajceProviderAsymmetricX509::X509CertificateObject
|
399
|
+
true
|
400
|
+
else
|
401
|
+
false
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
def Certificate.is_ext_key_usage_set?(cert, eku)
|
407
|
+
raise PkernelJce::Error, "Certificate not given to check eku." if cert.nil?
|
408
|
+
|
409
|
+
c = Certificate.to_bc_cert(cert)
|
410
|
+
ext = c.getExtension(org.bouncycastle.asn1.x509.Extension.extendedKeyUsage)
|
411
|
+
extKey = org.bouncycastle.asn1.x509.ExtendedKeyUsage.getInstance(ext.getParsedValue)
|
412
|
+
|
413
|
+
extKey.hasKeyPurposeId(eku)
|
414
|
+
end
|
415
|
+
|
416
|
+
private
|
417
|
+
#
|
418
|
+
# all date must be in Ruby datetime object?
|
419
|
+
#
|
420
|
+
def calculate_validity(params, &block)
|
421
|
+
validFrom = params[:validFrom]
|
422
|
+
validTo = params[:validTo]
|
423
|
+
validity = params[:validity] || 2
|
424
|
+
validityUnit = params[:validityUnit] || :years
|
425
|
+
|
426
|
+
validity = validity.to_i
|
427
|
+
|
428
|
+
if validFrom.nil?
|
429
|
+
raise PkernelJce::Error, "Valid from has to be given."
|
430
|
+
end
|
431
|
+
|
432
|
+
if validFrom.is_a?(Time) #or validFrom.is_a?(DateTime)
|
433
|
+
else
|
434
|
+
raise PkernelJce::Error, "Invalid valid from date object type : '#{validFrom.class}'"
|
435
|
+
end
|
436
|
+
|
437
|
+
if validTo.nil? or validTo.empty?
|
438
|
+
if (validity.nil?) and (validityUnit.nil?)
|
439
|
+
raise PkernelJce::Error, "Valid until and validity period both are not defined."
|
440
|
+
else
|
441
|
+
validTo = validFrom.advance( validityUnit => validity )
|
442
|
+
if block
|
443
|
+
# allow caller to check with issuer validity see if the valid to already surpass issuer's valid to
|
444
|
+
#validTo = block.call(validFrom, validTo)
|
445
|
+
validFrom, validTo = block.call(validFrom, validTo)
|
446
|
+
end
|
447
|
+
end
|
448
|
+
elsif validTo.is_a?(Time) or validTo.is_a?(DateTime)
|
449
|
+
else
|
450
|
+
raise PkernelJce::Error, "Invalid valid to date object type : '#{validTo.class}'"
|
451
|
+
end
|
452
|
+
|
453
|
+
[validFrom, validTo]
|
454
|
+
|
455
|
+
end
|
456
|
+
|
457
|
+
end
|
458
|
+
# end module certificate
|
459
|
+
|
460
|
+
|
461
|
+
class CertificateEngine
|
462
|
+
extend Certificate
|
463
|
+
end
|
464
|
+
|
465
|
+
|
466
|
+
end
|
467
|
+
|
@@ -0,0 +1,90 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
require 'pkernel'
|
6
|
+
require_relative 'csr'
|
7
|
+
require_relative 'global'
|
8
|
+
|
9
|
+
|
10
|
+
class Pkernel::Certificate::Owner
|
11
|
+
|
12
|
+
def to_x500_subject
|
13
|
+
|
14
|
+
PkernelJce::Provider.add_default
|
15
|
+
builder = Java::OrgBouncycastleAsn1X500::X500NameBuilder.new
|
16
|
+
builder.addRDN(Java::OrgBouncycastleAsn1X500Style::BCStyle::CN, @name)
|
17
|
+
|
18
|
+
builder.addRDN(Java::OrgBouncycastleAsn1X500Style::BCStyle::O, @org) if @org != nil and not @org.empty?
|
19
|
+
builder.addRDN(Java::OrgBouncycastleAsn1X500Style::BCStyle::OU, @orgUnit) if @orgUnit != nil and not @orgUnit.empty?
|
20
|
+
builder.addRDN(Java::OrgBouncycastleAsn1X500Style::BCStyle::SN, @serial) if @serial != nil and not @serial.empty?
|
21
|
+
|
22
|
+
# this should not be here...
|
23
|
+
if @emails.length > 0
|
24
|
+
builder.addRDN(Java::OrgBouncycastleAsn1X500Style::BCStyle::EmailAddress, @emails[0])
|
25
|
+
end
|
26
|
+
|
27
|
+
builder.build
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.parse_x500_subject(subject, &block)
|
32
|
+
if block
|
33
|
+
else
|
34
|
+
raise PkernelJce::Error, "Block required to parse x500 subject"
|
35
|
+
end
|
36
|
+
|
37
|
+
subject.getRDNs.each do |rd|
|
38
|
+
rd.getTypesAndValues.each do |tv|
|
39
|
+
case tv.type
|
40
|
+
when Java::OrgBouncycastleAsn1X500Style::BCStyle::CN
|
41
|
+
block.call(:cn, tv.value.string)
|
42
|
+
when Java::OrgBouncycastleAsn1X500Style::BCStyle::O
|
43
|
+
block.call(:o, tv.value.string)
|
44
|
+
when Java::OrgBouncycastleAsn1X500Style::BCStyle::OU
|
45
|
+
block.call(:ou, tv.value.string)
|
46
|
+
when Java::OrgBouncycastleAsn1X500Style::BCStyle::SN
|
47
|
+
block.call(:serial, tv.value.string)
|
48
|
+
when Java::OrgBouncycastleAsn1X500Style::BCStyle::EmailAddress
|
49
|
+
block.call(:email, tv.value.string)
|
50
|
+
else
|
51
|
+
PkernelJce::GConf.instance.glog.warn "Uncaught key-value in subject parsing '#{tv.type}-#{tv.value}'"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
# from_x500_subject
|
57
|
+
|
58
|
+
# assumption: CSR here already in object of PKCS10CertificationRequest
|
59
|
+
def self.from_p10(csr)
|
60
|
+
if csr.nil?
|
61
|
+
raise PkernelJce::Error, "Cannot load CSR from nil"
|
62
|
+
end
|
63
|
+
|
64
|
+
if PkernelJce::CSRProxy.is_signature_valid?(csr)
|
65
|
+
owner = Pkernel::Certificate::Owner.new
|
66
|
+
parse_x500_subject(csr.subject) do |k,v|
|
67
|
+
case k
|
68
|
+
when :cn
|
69
|
+
owner.name = v
|
70
|
+
when :o
|
71
|
+
owner.org = v
|
72
|
+
when :ou
|
73
|
+
owner.orgUnit = v
|
74
|
+
when :serial
|
75
|
+
owner.serial = v
|
76
|
+
when :email
|
77
|
+
owner.emails << v
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
owner
|
82
|
+
else
|
83
|
+
raise PkernelJce::Error, "Signature of CSR is not valid"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
# load_from_csr
|
87
|
+
|
88
|
+
end
|
89
|
+
# end class Owner
|
90
|
+
|