pkernel_jce 0.3 → 0.7.0
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 +5 -5
- data/.gitignore +3 -0
- data/Gemfile +0 -0
- data/LICENSE.txt +0 -0
- data/README.md +0 -0
- data/Rakefile +2 -0
- data/jars/bcmail-jdk15on-165.jar +0 -0
- data/jars/bcpg-jdk15on-165.jar +0 -0
- data/jars/bcpkix-jdk15on-165.jar +0 -0
- data/jars/bcprov-ext-jdk15on-165.jar +0 -0
- data/jars/bcprov-jdk15on-165.jar +0 -0
- data/jars/bctls-jdk15on-165.jar +0 -0
- data/lib/pkernel_jce.rb +16 -0
- data/lib/pkernel_jce/bc_helpers.rb +0 -0
- data/lib/pkernel_jce/certificate.rb +450 -30
- data/lib/pkernel_jce/certificate_owner.rb +0 -2
- data/lib/pkernel_jce/converter.rb +21 -0
- data/lib/pkernel_jce/crl.rb +0 -0
- data/lib/pkernel_jce/csr.rb +24 -0
- data/lib/pkernel_jce/error.rb +0 -0
- data/lib/pkernel_jce/global.rb +5 -1
- data/lib/pkernel_jce/identity.rb +557 -82
- data/lib/pkernel_jce/io_utils.rb +2 -0
- data/lib/pkernel_jce/jfile.rb +134 -0
- data/lib/pkernel_jce/jmembuf.rb +7 -0
- data/lib/pkernel_jce/keypair.rb +409 -91
- data/lib/pkernel_jce/ocsp.rb +0 -0
- data/lib/pkernel_jce/provider.rb +26 -4
- data/lib/pkernel_jce/rfc3161.rb +0 -0
- data/lib/pkernel_jce/utils.rb +0 -0
- data/lib/pkernel_jce/version.rb +1 -1
- data/pkernel_jce.gemspec +7 -4
- data/release.job +0 -0
- metadata +42 -27
- data/.ruby-version +0 -1
- data/Gemfile.lock +0 -56
- 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
@@ -1,7 +1,11 @@
|
|
1
1
|
|
2
2
|
|
3
3
|
module PkernelJce
|
4
|
+
#
|
5
|
+
# Common converter between different format
|
6
|
+
#
|
4
7
|
module Converter
|
8
|
+
|
5
9
|
def to_hex(bin)
|
6
10
|
String.from_java_bytes(org.bouncycastle.util.encoders.Hex.encode(bin))
|
7
11
|
end
|
@@ -21,9 +25,26 @@ module PkernelJce
|
|
21
25
|
java.util.Base64.decoder.decode(str)
|
22
26
|
end
|
23
27
|
# end from_b64
|
28
|
+
|
29
|
+
#
|
30
|
+
# Convert to MimeEncoder base64 format which limit per line 80 characters
|
31
|
+
#
|
32
|
+
def to_mb64(bin)
|
33
|
+
String.from_java_bytes(java.util.Base64.getMimeEncoder.encode(bin))
|
34
|
+
end
|
35
|
+
# end to_mb64
|
36
|
+
|
37
|
+
#
|
38
|
+
# Convert from MimeEncoder base64 format
|
39
|
+
#
|
40
|
+
def from_mb64(str)
|
41
|
+
java.util.Base64.getMimeDecoder.decode(str)
|
42
|
+
end
|
43
|
+
# end from_mb64
|
24
44
|
|
25
45
|
end
|
26
46
|
# module Converter
|
27
47
|
#
|
48
|
+
|
28
49
|
end
|
29
50
|
# module PkernelJce
|
data/lib/pkernel_jce/crl.rb
CHANGED
File without changes
|
data/lib/pkernel_jce/csr.rb
CHANGED
@@ -71,6 +71,18 @@ module PkernelJce
|
|
71
71
|
end
|
72
72
|
# end dump
|
73
73
|
|
74
|
+
def dump_to_file(csr, file, opts = { })
|
75
|
+
opts = { } if opts.nil?
|
76
|
+
raise PkernelJce::Error, "Option to dump CSR to file should be a hash" if not opts.is_a?(Hash)
|
77
|
+
dump(csr, opts.merge({ file: file }))
|
78
|
+
end
|
79
|
+
|
80
|
+
def dump_to_mem(csr, opts = { })
|
81
|
+
opts = { } if opts.nil?
|
82
|
+
raise PkernelJce::Error, "Option to dump CSR to memory should be a hash" if not opts.is_a?(Hash)
|
83
|
+
dump(csr, opts)
|
84
|
+
end
|
85
|
+
|
74
86
|
|
75
87
|
def load(options = {})
|
76
88
|
#todo is this content pem or binary?
|
@@ -98,6 +110,18 @@ module PkernelJce
|
|
98
110
|
end
|
99
111
|
# end load
|
100
112
|
|
113
|
+
def load_from_file(file, opts = { })
|
114
|
+
opts = { } if opts.nil?
|
115
|
+
raise PkernelJce::Error, "Option to load CSR from file should be a hash" if not opts.is_a?(Hash)
|
116
|
+
load(opts.merge({ file: file }))
|
117
|
+
end
|
118
|
+
|
119
|
+
def load_from_mem(bin, opts = { })
|
120
|
+
opts = { } if opts.nil?
|
121
|
+
raise PkernelJce::Error, "Option to load CSR from bin should be a hash" if not opts.is_a?(Hash)
|
122
|
+
load(opts.merge({ bin: bin }))
|
123
|
+
end
|
124
|
+
|
101
125
|
def is_signature_valid?(csr)
|
102
126
|
cvProv = org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder.new.build(csr.getSubjectPublicKeyInfo)
|
103
127
|
csr.isSignatureValid(cvProv)
|
data/lib/pkernel_jce/error.rb
CHANGED
File without changes
|
data/lib/pkernel_jce/global.rb
CHANGED
@@ -8,7 +8,11 @@ module PkernelJce
|
|
8
8
|
attr_reader :logger_params, :glog
|
9
9
|
def initialize
|
10
10
|
@logger_params = STDOUT
|
11
|
-
|
11
|
+
if ENV['PKERNEL_DEBUG'] == "true"
|
12
|
+
@glog = Tlogger::Tlogger.new(STDOUT)
|
13
|
+
else
|
14
|
+
@glog = Tlogger::Tlogger.new('pkernel.log',10,1024*1024*10)
|
15
|
+
end
|
12
16
|
@glog.tag = :pkernel_jce
|
13
17
|
@glog.show_source
|
14
18
|
end
|
data/lib/pkernel_jce/identity.rb
CHANGED
@@ -1,27 +1,31 @@
|
|
1
1
|
|
2
|
+
require 'pkernel'
|
3
|
+
|
2
4
|
require_relative 'provider'
|
3
5
|
require_relative 'csr'
|
4
6
|
|
5
|
-
|
7
|
+
require_relative 'keypair'
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
# @priv_key = opts[:priv_key]
|
15
|
-
# @cert = opts[:cert]
|
16
|
-
# @keystore = opts[:keystore]
|
17
|
-
# @chain = opts[:chain]
|
18
|
-
# end
|
19
|
-
#end
|
20
|
-
# end Identity
|
21
|
-
#
|
9
|
+
# Adding more functions to the parent class
|
10
|
+
#
|
11
|
+
# Identity
|
12
|
+
# Identity is abstraction consist of keypair + certificate, stored separately
|
13
|
+
#
|
14
|
+
module Pkernel
|
15
|
+
class Identity
|
22
16
|
|
23
|
-
|
24
|
-
|
17
|
+
def post_init(opts)
|
18
|
+
end
|
19
|
+
|
20
|
+
def certificate=(cert)
|
21
|
+
@certificate = cert
|
22
|
+
end
|
23
|
+
|
24
|
+
def chain=(val)
|
25
|
+
@chain = val
|
26
|
+
end
|
27
|
+
|
28
|
+
#alias_method :super_key=, :key=
|
25
29
|
def key=(val)
|
26
30
|
@key = val
|
27
31
|
if not @key.nil?
|
@@ -30,6 +34,7 @@ module PkernelJce
|
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
37
|
+
alias_method :super_key, :key
|
33
38
|
def key
|
34
39
|
if @key.nil?
|
35
40
|
if not @privKey.nil?
|
@@ -50,6 +55,44 @@ module PkernelJce
|
|
50
55
|
@key
|
51
56
|
end
|
52
57
|
|
58
|
+
def keypair=(val)
|
59
|
+
@keypair = val
|
60
|
+
end
|
61
|
+
|
62
|
+
def keypair
|
63
|
+
if @keypair.nil?
|
64
|
+
if not @key.nil? and @key.is_a?(java.security.KeyPair)
|
65
|
+
@keypair = @key
|
66
|
+
elsif not @key.nil? and @key.is_a?(java.security.PrivateKey)
|
67
|
+
@privKey = @key
|
68
|
+
if not @pubKey.nil?
|
69
|
+
@keypair = java.security.KeyPair.new(@pubKey,@privKey)
|
70
|
+
elsif not @certificate.nil?
|
71
|
+
@keypair = java.security.KeyPair.new(PkernelJce::Certificate.public_key(@certificate),@privKey)
|
72
|
+
else
|
73
|
+
# no public key available
|
74
|
+
end
|
75
|
+
else
|
76
|
+
|
77
|
+
if not @privKey.nil?
|
78
|
+
if not @pubKey.nil?
|
79
|
+
@keypair = java.security.KeyPair.new(@pubKey,@privKey)
|
80
|
+
elsif not @certificate.nil?
|
81
|
+
@keypair = java.security.KeyPair.new(@certificate.public_key,@privKey)
|
82
|
+
else
|
83
|
+
# no possible to generate without public key
|
84
|
+
end
|
85
|
+
else
|
86
|
+
# not possible to generate without private key
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
@keypair
|
93
|
+
end
|
94
|
+
|
95
|
+
alias_method :super_privKey, :privKey
|
53
96
|
def privKey
|
54
97
|
if @privKey.nil? and not @key.nil?
|
55
98
|
@privKey = PkernelJce::KeyPair.private_key(@key)
|
@@ -57,6 +100,7 @@ module PkernelJce
|
|
57
100
|
@privKey
|
58
101
|
end
|
59
102
|
|
103
|
+
alias_method :super_pubKey, :pubKey
|
60
104
|
def pubKey
|
61
105
|
if @pubKey.nil?
|
62
106
|
if not @key.nil?
|
@@ -65,13 +109,14 @@ module PkernelJce
|
|
65
109
|
@pubKey = PkernelJce::KeyPair.public_key(@certificate)
|
66
110
|
end
|
67
111
|
end
|
68
|
-
|
112
|
+
|
69
113
|
@pubKey
|
70
114
|
end
|
71
|
-
|
115
|
+
|
116
|
+
alias_method :super_cert, :certificate
|
72
117
|
def certificate
|
73
|
-
if not @certificate.nil?
|
74
|
-
@certificate = @certificate
|
118
|
+
if not @certificate.nil?
|
119
|
+
@certificate = Certificate.ensure_java_cert(@certificate)
|
75
120
|
end
|
76
121
|
@certificate
|
77
122
|
end
|
@@ -96,10 +141,17 @@ module PkernelJce
|
|
96
141
|
PkernelJce::GConf.instance.glog.debug "Provider is nil in Identity object. Setting it to default provider '#{PkernelJce::Provider::DefProvider.name}'"
|
97
142
|
@provider = PkernelJce::Provider.add_default
|
98
143
|
end
|
99
|
-
|
144
|
+
|
100
145
|
@provider
|
101
146
|
end
|
102
147
|
end
|
148
|
+
end
|
149
|
+
#
|
150
|
+
# Pkernel::Identity extension
|
151
|
+
#
|
152
|
+
|
153
|
+
|
154
|
+
module PkernelJce
|
103
155
|
|
104
156
|
#
|
105
157
|
# IdentityFactory
|
@@ -137,12 +189,200 @@ module PkernelJce
|
|
137
189
|
alias_method :build, :build_from_components
|
138
190
|
# end build_from_components
|
139
191
|
|
140
|
-
def dump(id, opts = {})
|
192
|
+
def dump(id, opts = {}, &block)
|
141
193
|
|
142
194
|
if id.nil?
|
143
195
|
raise PkernelJce::Error, "Identity object is nil in write to keystore"
|
144
196
|
end
|
145
197
|
|
198
|
+
result = { }
|
199
|
+
|
200
|
+
format = opts[:format]
|
201
|
+
case format
|
202
|
+
when :pkcs8, :pk8, :p8
|
203
|
+
|
204
|
+
res = dump_pk8(id, opts, &block)
|
205
|
+
|
206
|
+
# private key
|
207
|
+
file = opts[:file]
|
208
|
+
if file.nil? or file.empty?
|
209
|
+
result[:bin] = res[:bin]
|
210
|
+
else
|
211
|
+
ff = java.io.File.new(file)
|
212
|
+
ff.parent_file.mkdirs if not ff.parent_file.exists?
|
213
|
+
fos = java.io.FileOutputStream.new(ff)
|
214
|
+
fos.write res[:bin].to_java.getBytes
|
215
|
+
fos.flush
|
216
|
+
fos.close
|
217
|
+
|
218
|
+
result[:file] = file
|
219
|
+
end
|
220
|
+
|
221
|
+
# certificate
|
222
|
+
cfile = opts[:cert_file]
|
223
|
+
if not cfile.nil?
|
224
|
+
ff = java.io.File.new(cfile)
|
225
|
+
ff.parent_file.mkdirs if not ff.parent_file.exists?
|
226
|
+
fos = java.io.FileOutputStream.new(ff)
|
227
|
+
fos.write res[:cert_bin]
|
228
|
+
fos.flush
|
229
|
+
fos.close
|
230
|
+
result[:cert_file] = cfile
|
231
|
+
else
|
232
|
+
result[:cert_bin] = res[:cert_bin]
|
233
|
+
end
|
234
|
+
|
235
|
+
# cert chain
|
236
|
+
cafile = opts[:ca_file]
|
237
|
+
if not cafile.nil?
|
238
|
+
ff = java.io.File.new(cafile)
|
239
|
+
ff.parent_file.mkdirs if not ff.parent_file.exists?
|
240
|
+
fos = java.io.FileOutputStream.new(ff)
|
241
|
+
res[:ca_bin].each do |ca|
|
242
|
+
fos.write ca
|
243
|
+
end
|
244
|
+
fos.flush
|
245
|
+
fos.close
|
246
|
+
|
247
|
+
result[:ca_file] = cafile
|
248
|
+
else
|
249
|
+
result[:ca_bin] = res[:ca_bin]
|
250
|
+
end
|
251
|
+
|
252
|
+
result
|
253
|
+
|
254
|
+
when :pem
|
255
|
+
|
256
|
+
res = dump_pem(id, opts, &block)
|
257
|
+
|
258
|
+
# private key
|
259
|
+
file = opts[:file]
|
260
|
+
if file.nil? or file.empty?
|
261
|
+
result[:bin] = res[:bin]
|
262
|
+
else
|
263
|
+
ff = java.io.File.new(file)
|
264
|
+
ff.parent_file.mkdirs if not ff.parent_file.exists?
|
265
|
+
fos = java.io.FileOutputStream.new(ff)
|
266
|
+
fos.write res[:bin]
|
267
|
+
fos.flush
|
268
|
+
fos.close
|
269
|
+
|
270
|
+
result[:file] = file
|
271
|
+
end
|
272
|
+
|
273
|
+
# public key
|
274
|
+
cfile = opts[:pubKey_file]
|
275
|
+
if not cfile.nil?
|
276
|
+
ff = java.io.File.new(cfile)
|
277
|
+
ff.parent_file.mkdirs if not ff.parent_file.exists?
|
278
|
+
fos = java.io.FileOutputStream.new(ff)
|
279
|
+
fos.write res[:pubKey_bin]
|
280
|
+
fos.flush
|
281
|
+
fos.close
|
282
|
+
result[:pubKey_file] = cfile
|
283
|
+
else
|
284
|
+
result[:pubKey_bin] = res[:pubKey_bin]
|
285
|
+
end
|
286
|
+
|
287
|
+
# certificate
|
288
|
+
cfile = opts[:cert_file]
|
289
|
+
if not cfile.nil?
|
290
|
+
ff = java.io.File.new(cfile)
|
291
|
+
ff.parent_file.mkdirs if not ff.parent_file.exists?
|
292
|
+
fos = java.io.FileOutputStream.new(ff)
|
293
|
+
fos.write res[:cert_bin]
|
294
|
+
fos.flush
|
295
|
+
fos.close
|
296
|
+
result[:cert_file] = cfile
|
297
|
+
else
|
298
|
+
result[:cert_bin] = res[:cert_bin]
|
299
|
+
end
|
300
|
+
|
301
|
+
# cert chain
|
302
|
+
cafile = opts[:ca_file]
|
303
|
+
if not cafile.nil?
|
304
|
+
ff = java.io.File.new(cafile)
|
305
|
+
ff.parent_file.mkdirs if not ff.parent_file.exists?
|
306
|
+
fos = java.io.FileOutputStream.new(ff)
|
307
|
+
res[:ca_bin].each do |ca|
|
308
|
+
fos.write ca
|
309
|
+
end
|
310
|
+
fos.flush
|
311
|
+
fos.close
|
312
|
+
|
313
|
+
result[:ca_file] = cafile
|
314
|
+
else
|
315
|
+
result[:ca_bin] = res[:ca_bin]
|
316
|
+
end
|
317
|
+
|
318
|
+
result
|
319
|
+
|
320
|
+
|
321
|
+
else
|
322
|
+
# JCE/JCA keystore
|
323
|
+
rres = dump_keystore(id, opts, &block)
|
324
|
+
|
325
|
+
result.merge!(rres)
|
326
|
+
|
327
|
+
file = opts[:file]
|
328
|
+
if file.nil? or file.empty?
|
329
|
+
else
|
330
|
+
ff = java.io.File.new(file)
|
331
|
+
ff.parent_file.mkdirs if not ff.parent_file.exists?
|
332
|
+
fos = java.io.FileOutputStream.new(file)
|
333
|
+
fos.write result[:bin]
|
334
|
+
fos.flush
|
335
|
+
fos.close
|
336
|
+
|
337
|
+
result[:file] = file
|
338
|
+
end
|
339
|
+
|
340
|
+
result
|
341
|
+
end
|
342
|
+
|
343
|
+
end
|
344
|
+
|
345
|
+
def dump_to_file(id, file, opts = { }, &block)
|
346
|
+
opts = { } if opts.nil?
|
347
|
+
raise PkernelJce::Error, "Option for dump to file must be a hash" if not opts.is_a?(Hash)
|
348
|
+
dump(id, opts.merge({ file: file }), &block)
|
349
|
+
end
|
350
|
+
|
351
|
+
def dump_to_file_p8(id, idFile, certFile, caFile, password, opts = { }, &block)
|
352
|
+
opts = { } if opts.nil?
|
353
|
+
raise PkernelJce::Error, "Option for dump to file in pkcs8 format must be a hash" if not opts.is_a?(Hash)
|
354
|
+
|
355
|
+
raise PkernelJce::Error, "Identity file path cannot be empty" if empty?(idFile)
|
356
|
+
raise PkernelJce::Error, "Certificate file path cannot be empty" if empty?(certFile)
|
357
|
+
raise PkernelJce::Error, "CA chain file path cannot be empty" if empty?(caFile)
|
358
|
+
|
359
|
+
dump(id, opts.merge({ file: idFile, cert_file: certFile, ca_file: caFile, format: :pkcs8 }),&block)
|
360
|
+
end
|
361
|
+
|
362
|
+
def load(opts = {}, &block)
|
363
|
+
|
364
|
+
format = opts[:format]
|
365
|
+
case format
|
366
|
+
when :pk8, :p8, :pkcs8
|
367
|
+
res = load_pk8(opts, &block)
|
368
|
+
when :pem
|
369
|
+
res = load_pem(opts, &block)
|
370
|
+
else
|
371
|
+
res = load_keystore(opts, &block)
|
372
|
+
end
|
373
|
+
|
374
|
+
if res[:key].nil?
|
375
|
+
raise Pkernel::Error, "Failed to load key from the store."
|
376
|
+
end
|
377
|
+
|
378
|
+
Pkernel::Identity.new( { privKey: res[:key], certificate: res[:cert], chain: res[:chain] } )
|
379
|
+
end
|
380
|
+
# end load()
|
381
|
+
|
382
|
+
private
|
383
|
+
def dump_keystore(id, opts = { }, &block)
|
384
|
+
|
385
|
+
result = { }
|
146
386
|
prov = opts[:provider]
|
147
387
|
if prov.nil?
|
148
388
|
prov = PkernelJce::Provider.add_default
|
@@ -150,35 +390,45 @@ module PkernelJce
|
|
150
390
|
prov = PkernelJce::Provider.add_provider(prov)
|
151
391
|
end
|
152
392
|
|
153
|
-
|
154
|
-
format = :p12 if format.nil?
|
155
|
-
sFormat = format
|
156
|
-
case format
|
393
|
+
case opts[:format]
|
157
394
|
when :p12, :pkcs12
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
when :
|
162
|
-
|
163
|
-
ks = java.security.KeyStore.getInstance("JKS")
|
164
|
-
sFormat = :jks
|
395
|
+
stype = "PKCS12"
|
396
|
+
when :jks, :java
|
397
|
+
stype = "jks"
|
398
|
+
when :bks
|
399
|
+
stype = "bks"
|
165
400
|
else
|
166
|
-
PkernelJce::GConf.instance.glog.debug "
|
167
|
-
|
168
|
-
ks = java.security.KeyStore.getInstance(format)
|
169
|
-
else
|
170
|
-
ks = java.security.KeyStore.getInstance(format, prov)
|
171
|
-
end
|
172
|
-
sFormat = format
|
401
|
+
PkernelJce::GConf.instance.glog.debug "No keystore type given. Default to pkcs12 keystore"
|
402
|
+
stype = "PKCS12"
|
173
403
|
end
|
174
404
|
|
175
|
-
|
405
|
+
if prov.nil? or stype == "jks"
|
406
|
+
PkernelJce::GConf.instance.glog.debug "Loading #{stype} keystore with null provider"
|
407
|
+
ks = java.security.KeyStore.getInstance(stype)
|
408
|
+
else
|
409
|
+
PkernelJce::GConf.instance.glog.debug "Loading #{stype} keystore with provider #{prov.name}"
|
410
|
+
ks = java.security.KeyStore.getInstance(stype,prov)
|
411
|
+
end
|
412
|
+
|
176
413
|
pass = opts[:password]
|
177
414
|
if pass.nil? or pass.empty?
|
178
|
-
|
179
|
-
|
415
|
+
if block
|
416
|
+
pass = block.call(:prompt_pass)
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
passLen = opts[:password_length] || 8
|
421
|
+
# cannot be too small...
|
422
|
+
if (passLen/2) < 8
|
423
|
+
passLen = 8
|
424
|
+
else
|
425
|
+
passLen = passLen/2
|
426
|
+
end
|
427
|
+
|
428
|
+
if pass.nil? or pass.empty?
|
429
|
+
PkernelJce::GConf.instance.glog.warn "Password is not given to dump identity. Random password of #{passLen*2} characters shall be generated."
|
430
|
+
pass = SecureRandom.hex(passLen)
|
180
431
|
result[:password] = pass
|
181
|
-
#raise PkernelJce::Error, "Password should not be empty for identity storage"
|
182
432
|
end
|
183
433
|
|
184
434
|
chain = id.chain.map do |c|
|
@@ -189,50 +439,45 @@ module PkernelJce
|
|
189
439
|
end
|
190
440
|
end
|
191
441
|
|
192
|
-
name = opts[:key_name] ||
|
442
|
+
name = opts[:key_name] || opts[:keyName] || opts[:keyname] || Certificate.get_subject_fields(id.certificate,[:cn])[:cn][0]
|
193
443
|
|
194
444
|
ks.load(nil,nil)
|
195
445
|
ks.setKeyEntry(name, id.privKey, pass.to_java.toCharArray, chain.to_java(java.security.cert.Certificate))
|
196
|
-
baos = java.io.ByteArrayOutputStream.new
|
197
|
-
|
198
|
-
file = opts[:file]
|
199
|
-
if file.nil? or file.empty?
|
200
|
-
ks.store(baos, pass.to_java.toCharArray)
|
201
|
-
#baos.toByteArray
|
202
|
-
result[:bin] = baos.toByteArray
|
203
|
-
else
|
204
|
-
fos = java.io.FileOutputStream.new(file)
|
205
|
-
ks.store(fos, pass.to_java.toCharArray)
|
206
|
-
fos.flush
|
207
|
-
fos.close
|
208
|
-
|
209
|
-
result[:file] = file
|
210
|
-
end
|
211
446
|
|
447
|
+
baos = java.io.ByteArrayOutputStream.new
|
448
|
+
ks.store(baos, pass.to_java.toCharArray)
|
449
|
+
result[:bin] = baos.toByteArray
|
450
|
+
|
212
451
|
result
|
452
|
+
|
213
453
|
end
|
454
|
+
# dump_keystore
|
214
455
|
|
215
|
-
def
|
456
|
+
def load_keystore(opts = { }, &block)
|
457
|
+
|
458
|
+
result = { }
|
216
459
|
|
217
460
|
prov = opts[:provider]
|
218
|
-
if prov.nil?
|
219
|
-
prov = PkernelJce::Provider.add_default
|
220
|
-
else
|
461
|
+
if not prov.nil?
|
221
462
|
prov = PkernelJce::Provider.add_provider(prov)
|
222
463
|
end
|
223
464
|
|
224
465
|
format = opts[:format]
|
225
466
|
format = :p12 if format.nil?
|
226
467
|
sFormat = format
|
227
|
-
case format
|
468
|
+
case format.to_sym
|
228
469
|
when :p12, :pkcs12
|
229
470
|
PkernelJce::GConf.instance.glog.debug "Loading PKCS12 keystore"
|
230
|
-
|
231
|
-
|
471
|
+
pprov = PkernelJce::Provider.add_default
|
472
|
+
ks = java.security.KeyStore.getInstance("PKCS12",pprov)
|
473
|
+
result[:ks_format] = :p12
|
232
474
|
when :jks
|
233
475
|
PkernelJce::GConf.instance.glog.debug "Loading JKS keystore"
|
234
476
|
ks = java.security.KeyStore.getInstance("JKS")
|
235
|
-
|
477
|
+
result[:ks_format] = :jks
|
478
|
+
|
479
|
+
when :pk8, :pkcs8, :p8
|
480
|
+
|
236
481
|
else
|
237
482
|
PkernelJce::GConf.instance.glog.debug "Loading '#{format}' keystore"
|
238
483
|
if prov.nil?
|
@@ -240,33 +485,263 @@ module PkernelJce
|
|
240
485
|
else
|
241
486
|
ks = java.security.KeyStore.getInstance(format.to_s, prov)
|
242
487
|
end
|
488
|
+
|
489
|
+
result[:ks_format] = format
|
243
490
|
end
|
244
491
|
|
245
|
-
pass = opts[:password]
|
492
|
+
pass = opts[:password]
|
493
|
+
|
494
|
+
if (pass.nil? or pass.empty?) and block
|
495
|
+
pass = block.call(:prompt_pass)
|
496
|
+
end
|
246
497
|
|
247
498
|
file = opts[:file]
|
248
499
|
bin = opts[:bin]
|
249
500
|
baos = java.io.ByteArrayOutputStream.new
|
250
501
|
|
251
|
-
if not file.nil? or
|
502
|
+
if not (file.nil? or file.empty?)
|
252
503
|
fis = java.io.FileInputStream.new(file)
|
253
504
|
ks.load(fis,pass.to_java.toCharArray)
|
254
505
|
fis.close
|
255
|
-
elsif bin.nil?
|
506
|
+
elsif not bin.nil?
|
256
507
|
ks.load(java.io.ByteArrayInputStream.new(bin),pass.to_java.toCharArray)
|
257
508
|
else
|
258
|
-
raise PkernelJce::Error, "No file or bin is given to load identity"
|
509
|
+
raise PkernelJce::Error, "No file or bin in keystore format is given to load identity"
|
259
510
|
end
|
260
|
-
|
261
|
-
name = opts[:key_name] || ks.aliases.to_a[0]
|
262
|
-
|
263
|
-
key = ks.getKey(name,pass.to_java.toCharArray)
|
264
|
-
cert = ks.getCertificate(name)
|
265
|
-
chain = ks.getCertificateChain(name)
|
266
511
|
|
267
|
-
|
268
|
-
|
512
|
+
keyname = opts[:keyname] || opts[:keyName] || opts[:key_name]
|
513
|
+
|
514
|
+
if not (keyname.empty? or keyname.nil?)
|
515
|
+
result[:ks_alias] = keyname
|
516
|
+
else
|
517
|
+
aliases = ks.aliases.to_a
|
518
|
+
if aliases.length == 0
|
519
|
+
raise PkernelJce::Error, "No alias available from the keystore"
|
520
|
+
end
|
521
|
+
|
522
|
+
if aliases.length > 1
|
523
|
+
# more the 1 aliases
|
524
|
+
# to ensure the loading is correct, call block or error
|
525
|
+
if block
|
526
|
+
result[:ks_alias] = block.call(:multiple_aliases, aliases)
|
527
|
+
else
|
528
|
+
raise PkernelJce::Error, "Multiple aliases exist in the keystores. Please provide keyname to pick one or provide a block for processing"
|
529
|
+
end
|
530
|
+
else
|
531
|
+
result[:ks_alias] = aliases.first
|
532
|
+
end
|
533
|
+
end
|
534
|
+
|
535
|
+
result[:key] = ks.getKey(result[:ks_alias],pass.to_java.toCharArray)
|
536
|
+
result[:cert] = ks.getCertificate(result[:ks_alias])
|
537
|
+
result[:chain] = ks.getCertificateChain(result[:ks_alias])
|
538
|
+
|
539
|
+
result
|
540
|
+
end
|
541
|
+
# load_keystore
|
542
|
+
|
543
|
+
def dump_pem(id,opts,&block)
|
544
|
+
|
545
|
+
result = { }
|
546
|
+
baos = java.io.ByteArrayOutputStream.new
|
547
|
+
|
548
|
+
pass = opts[:password]
|
549
|
+
if (pass.nil? or pass.empty?) and block
|
550
|
+
pass = block.call(:prompt_pass)
|
551
|
+
end
|
552
|
+
|
553
|
+
PkernelJce::Provider.add_default
|
554
|
+
|
555
|
+
writer = org.bouncycastle.openssl.PEMWriter.new(java.io.OutputStreamWriter.new(baos))
|
556
|
+
if pass.nil? or pass.empty?
|
557
|
+
PkernelJce::GConf.instance.glog.debug "Constructing plain PEM..."
|
558
|
+
writer.writeObject(id.privKey)
|
559
|
+
else
|
560
|
+
PkernelJce::GConf.instance.glog.debug "Constructing encrypted PEM..."
|
561
|
+
encryptor = org.bouncycastle.openssl.jcajce.JcePEMEncryptorBuilder.new("AES-256-GCM").build(pass.to_java.toCharArray)
|
562
|
+
writer.writeObject(id.privKey,encryptor)
|
563
|
+
end
|
564
|
+
writer.flush
|
565
|
+
writer.close
|
566
|
+
result[:bin] = baos.toByteArray
|
567
|
+
|
568
|
+
baos.reset
|
569
|
+
writer = org.bouncycastle.openssl.PEMWriter.new(java.io.OutputStreamWriter.new(baos))
|
570
|
+
writer.writeObject(id.certificate)
|
571
|
+
writer.flush
|
572
|
+
writer.close
|
573
|
+
result[:cert_bin] = baos.toByteArray
|
574
|
+
|
575
|
+
baos.reset
|
576
|
+
writer = org.bouncycastle.openssl.PEMWriter.new(java.io.OutputStreamWriter.new(baos))
|
577
|
+
writer.writeObject(id.pubKey)
|
578
|
+
writer.flush
|
579
|
+
writer.close
|
580
|
+
result[:pubKey_bin] = baos.toByteArray
|
581
|
+
|
582
|
+
cc = []
|
583
|
+
id.chain.each do |c|
|
584
|
+
baos.reset
|
585
|
+
writer = org.bouncycastle.openssl.PEMWriter.new(java.io.OutputStreamWriter.new(baos))
|
586
|
+
writer.writeObject(c)
|
587
|
+
writer.flush
|
588
|
+
writer.close
|
589
|
+
cc << baos.toByteArray
|
590
|
+
end
|
591
|
+
result[:ca_bin] = cc
|
592
|
+
|
593
|
+
result
|
594
|
+
|
595
|
+
end
|
596
|
+
# dump_pem
|
597
|
+
|
598
|
+
def load_pem(opts, &block)
|
599
|
+
res = { }
|
600
|
+
file = opts[:file]
|
601
|
+
bin = opts[:bin]
|
602
|
+
|
603
|
+
prov = PkernelJce::Provider.add_default
|
604
|
+
|
605
|
+
converter = org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter.new.setProvider prov
|
606
|
+
|
607
|
+
if not (file.nil? or file.empty?)
|
608
|
+
reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.FileInputStream.new(file)))
|
609
|
+
elsif not (bin.nil? or bin.empty?)
|
610
|
+
reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.ByteArrayInputStream.new(IoUtils.ensure_java_bytes(bin))))
|
611
|
+
else
|
612
|
+
raise PkernelJce::Error, "No file or bin in PEM format is given to load identity"
|
613
|
+
end
|
614
|
+
|
615
|
+
obj = reader.readObject
|
616
|
+
if obj.java_kind_of? org.bouncycastle.openssl.PEMKeyPair
|
617
|
+
res[:keypair] = converter.getKeyPair(obj)
|
618
|
+
res[:key] = PkernelJce::KeyPair.private_key(res[:keypair])
|
619
|
+
|
620
|
+
elsif obj.java_kind_of? org.bouncycastle.openssl.PEMEncryptedKeyPair
|
621
|
+
|
622
|
+
PkernelJce::GConf.instance.glog.debug "Loading encrypted PEM..."
|
623
|
+
pass = opts[:password]
|
624
|
+
if (pass.nil? or pass.empty?) and block
|
625
|
+
pass = block.call(:prompt_pass)
|
626
|
+
end
|
627
|
+
|
628
|
+
if pass.nil? or pass.empty?
|
629
|
+
raise PkernelJce::Error, "The given key file to load is password protected but password is not given. Process shall abort."
|
630
|
+
end
|
631
|
+
|
632
|
+
decryptor = org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder.new.setProvider(prov).build(pass.to_java.toCharArray)
|
633
|
+
res[:keypair] = converter.getKeyPair(obj.decryptKeyPair(decryptor))
|
634
|
+
res[:key] = PkernelJce::KeyPair.private_key(res[:keypair])
|
635
|
+
|
636
|
+
elsif obj.java_kind_of? org.bouncycastle.asn1.pkcs.PrivateKeyInfo
|
637
|
+
res[:key] = converter.getPrivateKey obj
|
638
|
+
else
|
639
|
+
raise PkernelJce::Error, "Unknown object for further processing #{obj.class}"
|
640
|
+
end
|
641
|
+
|
642
|
+
if not (opts[:cert_file].nil? or opts[:cert_file].empty?)
|
643
|
+
reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.FileInputStream.new(opts[:cert_file])))
|
644
|
+
res[:cert] = reader.readObject
|
645
|
+
elsif not (opts[:cert_bin].nil? or opts[:cert_bin].empty?)
|
646
|
+
reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.ByteArrayInputStream.new(IoUtils.ensure_java_bytes(opts[:cert_bin]))))
|
647
|
+
res[:cert] = reader.readObject
|
648
|
+
end
|
649
|
+
|
650
|
+
if not (opts[:ca_file].nil? or opts[:ca_file].empty?)
|
651
|
+
reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.FileInputStream.new(opts[:ca_file])))
|
652
|
+
res[:chain] = []
|
653
|
+
o = reader.readObject
|
654
|
+
while(o != nil)
|
655
|
+
res[:chain] << o
|
656
|
+
o = reader.readObject
|
657
|
+
end
|
658
|
+
elsif not (opts[:ca_bin].nil? or opts[:ca_bin].empty?)
|
659
|
+
reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.ByteArrayInputStream.new(IoUtils.ensure_java_bytes(opts[:ca_bin]))))
|
660
|
+
res[:chain] = []
|
661
|
+
o = reader.readObject
|
662
|
+
while(o != nil)
|
663
|
+
res[:chain] << o
|
664
|
+
o = reader.readObject
|
665
|
+
end
|
666
|
+
end
|
667
|
+
|
668
|
+
res
|
669
|
+
|
670
|
+
end
|
671
|
+
# load_pem
|
672
|
+
|
673
|
+
# dump_pk8()
|
674
|
+
def dump_pk8(id, opts, &block)
|
675
|
+
|
676
|
+
PkernelJce::GConf.instance.glog.debug "Dump to PKCS8 format..."
|
677
|
+
|
678
|
+
result = { }
|
679
|
+
|
680
|
+
pass = opts[:password]
|
681
|
+
if (pass.nil? or pass.empty?) and block
|
682
|
+
pass = block.call(:prompt_pass)
|
683
|
+
end
|
684
|
+
|
685
|
+
prov = opts[:provider]
|
686
|
+
if not prov.nil?
|
687
|
+
prov = PkernelJce::Provider.add_provider(prov)
|
688
|
+
end
|
689
|
+
|
690
|
+
# private key only
|
691
|
+
# remove file parameter if given
|
692
|
+
# because we want the dump to be available here
|
693
|
+
keyDumpPara = opts.clone
|
694
|
+
keyDumpPara.delete(:file)
|
695
|
+
# KeyPair already using the PKCS8 format for output... might as well just reuse...
|
696
|
+
rres = PkernelJce::KeyPairEngine.dump(id.keypair, keyDumpPara, &block)
|
697
|
+
|
698
|
+
result[:bin] = rres
|
699
|
+
|
700
|
+
result[:cert_bin] = PkernelJce::CertificateEngine.dump(id.certificate, { outForm: :pem })
|
701
|
+
|
702
|
+
cc = []
|
703
|
+
id.chain.each do |c|
|
704
|
+
cc << PkernelJce::CertificateEngine.dump(c, { outForm: :pem })
|
705
|
+
end
|
706
|
+
|
707
|
+
result[:ca_bin] = cc
|
708
|
+
|
709
|
+
result
|
710
|
+
|
711
|
+
end
|
712
|
+
# dump_pk8
|
713
|
+
|
714
|
+
def load_pk8(opts, &block)
|
715
|
+
|
716
|
+
res = { }
|
717
|
+
pass = opts[:password]
|
718
|
+
if (pass.nil? or pass.empty?) and block
|
719
|
+
pass = block.call(:prompt_pass)
|
720
|
+
end
|
721
|
+
|
722
|
+
prov = opts[:provider]
|
723
|
+
if not prov.nil?
|
724
|
+
prov = PkernelJce::Provider.add_provider(prov)
|
725
|
+
end
|
726
|
+
|
727
|
+
key = PkernelJce::KeyPairEngine.load(opts)
|
728
|
+
|
729
|
+
res[:key] = key
|
730
|
+
|
731
|
+
certPara = { }
|
732
|
+
certPara[:file] = opts[:cert_file] if not (opts[:cert_file].nil? or opts[:cert_file].empty?)
|
733
|
+
certPara[:bin] = opts[:cert_bin] if not (opts[:cert_bin].nil? or opts[:cert_file].empty?)
|
734
|
+
res[:cert] = PkernelJce::CertificateEngine.load(certPara)
|
735
|
+
|
736
|
+
chainPara = { multiple: true }
|
737
|
+
chainPara[:file] = opts[:ca_file] if not (opts[:ca_file].nil? or opts[:ca_file].empty?)
|
738
|
+
chainPara[:bin] = opts[:ca_bin] if not (opts[:ca_bin].nil? or opts[:ca_bin].empty?)
|
739
|
+
res[:chain] = PkernelJce::CertificateEngine.load(chainPara)
|
740
|
+
|
741
|
+
res
|
742
|
+
|
269
743
|
end
|
744
|
+
# load_pk8
|
270
745
|
|
271
746
|
end
|
272
747
|
# end IdentityFactory
|