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.
@@ -0,0 +1,45 @@
1
+
2
+ module PkernelJce
3
+ module IoUtils
4
+
5
+ def IoUtils.file_to_memory_byte_array(path)
6
+ if path.nil? or path.empty?
7
+ raise PkernelJce::Error, "Given path '#{path}' to load to memory is nil or empty"
8
+ else
9
+ f = java.io.File.new(path)
10
+ b = Java::byte[f.length].new
11
+ dis = java.io.DataInputStream.new(java.io.FileInputStream.new(f))
12
+ dis.readFully(b)
13
+ dis.close
14
+
15
+ b
16
+ end
17
+ end
18
+ # end file_to_memory_byte_array
19
+ #
20
+
21
+ def IoUtils.ensure_java_bytes(bin)
22
+ if not bin.java_kind_of?(Java::byte[])
23
+ bin.to_java_bytes
24
+ else
25
+ bin
26
+ end
27
+ end
28
+ # end ensure_java_bytes
29
+ #
30
+
31
+ def IoUtils.to_hex(bin)
32
+ String.from_java_bytes(org.bouncycastle.util.encoders.Hex.encode(bin))
33
+ end
34
+
35
+ def IoUtils.from_hex(str)
36
+ org.bouncycastle.util.encoders.Hex.decode(str)
37
+ end
38
+
39
+ end
40
+ # end IoUtils
41
+ #
42
+
43
+ end
44
+ # end PkernelJce
45
+ #
@@ -0,0 +1,359 @@
1
+
2
+ require 'pkernel'
3
+
4
+ require_relative 'provider'
5
+ require_relative 'global'
6
+
7
+ module PkernelJce
8
+ module KeyPair
9
+
10
+ def generate(algo, conf = {})
11
+
12
+ log = conf[:log]
13
+ if log.nil?
14
+ log = GConf.instance.glog
15
+ end
16
+
17
+ prov = conf[:provider]
18
+ #log.debug "Provider is #{prov == nil ? 'nil' : prov.name}"
19
+
20
+ case algo.to_s.upcase
21
+ when "RSA"
22
+ len = conf[:len] || 2048
23
+ log.debug "Generating RSA #{len} bits with provider #{prov == nil ? 'default' : prov.name}"
24
+ if prov.nil?
25
+ kpg = java.security.KeyPairGenerator.getInstance("RSA")
26
+ else
27
+ PkernelJce::Provider.add_provider(prov)
28
+ kpg = java.security.KeyPairGenerator.getInstance("RSA", prov)
29
+ end
30
+
31
+ kpg.java_send :initialize, [Java::int], len
32
+ kpg.generate_key_pair
33
+ when "DSA"
34
+ len = conf[:len] || 2048
35
+ log.debug "Generating DSA #{len} bits with provider #{prov == nil ? 'default' : prov.name}"
36
+ if prov.nil?
37
+ kpg = java.security.KeyPairGenerator.getInstance("DSA")
38
+ else
39
+ PkernelJce::Provider.add_provider(prov)
40
+ kpg = java.security.KeyPairGenerator.getInstance("DSA", prov)
41
+ end
42
+ kpg.java_send :initialize, [Java::int], len
43
+ kpg.generate_key_pair
44
+ when "ECC","EC"
45
+ # this only supported by bc?
46
+ curve = conf[:curve] || "prime256v1"
47
+ if prov.nil?
48
+ #kpg = java.security.KeyPairGenerator.getInstance("ECDSA")
49
+ # default Java does not have ECDSA yet as of Java 8
50
+ prov = PkernelJce::Provider.add_default
51
+ end
52
+ log.debug "Generating ECC curve '#{curve}' with provider #{prov == nil ? 'default' : prov.name}"
53
+
54
+ PkernelJce::Provider.add_provider(prov)
55
+ kpg = java.security.KeyPairGenerator.getInstance("ECDSA", prov)
56
+ kpg.java_send :initialize, [java.security.spec.AlgorithmParameterSpec, java.security.SecureRandom], java.security.spec.ECGenParameterSpec.new(curve), java.security.SecureRandom.new
57
+ kpg.generate_key_pair
58
+ else
59
+ log.error "Unknown '#{algo}' for java keypair"
60
+ raise PkernelJce::Error, "Unknown algo '#{algo}' for java keypair"
61
+ end
62
+ end
63
+ # end generate
64
+ #
65
+
66
+ def KeyPair.key_type(key)
67
+ if key.java_kind_of?(java.security.KeyPair)
68
+ privKey = key.getPrivate
69
+ else
70
+ # given is private key
71
+ privKey = key
72
+ end
73
+
74
+ case privKey
75
+ when java.security.interfaces.RSAPrivateCrtKey
76
+ Pkernel::KeyPair::RSA_KEY_NAME
77
+ when Java::sun.security.provider.DSAPrivateKey, org.bouncycastle.jcajce.provider.asymmetric.dsa.BCDSAPrivateKey
78
+ Pkernel::KeyPair::DSA_KEY_NAME
79
+ when org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey
80
+ Pkernel::KeyPair::EC_KEY_NAME
81
+ else
82
+ raise PkernelJce::Error, "Unknown priv key type '#{privKey.class}'"
83
+ end
84
+ end
85
+ #
86
+ # end get_key_type
87
+ #
88
+
89
+ def KeyPair.pub_key_type(key)
90
+ if key.java_kind_of?(java.security.KeyPair)
91
+ pubKey = key.public
92
+ elsif PkernelJce::Certificate.is_cert_object?(key)
93
+ pubKey = PkernelJce::Certificate.public_key(key)
94
+ else
95
+ pubKey = key
96
+ end
97
+
98
+ case pubKey
99
+ when java.security.interfaces.RSAPublicKey
100
+ Pkernel::KeyPair::RSA_KEY_NAME
101
+ when Java::sun.security.provider.DSAPublicKey, Java::OrgBouncycastleJcajceProviderAsymmetricDsa::BCDSAPublicKey
102
+ Pkernel::KeyPair::DSA_KEY_NAME
103
+ when Java::OrgBouncycastleJcajceProviderAsymmetricEc::BCECPublicKey
104
+ Pkernel::KeyPair::EC_KEY_NAME
105
+ else
106
+ raise PkernelJce::Error, "Unknown pub key type '#{pubKey.class}'"
107
+ end
108
+ end
109
+
110
+ def KeyPair.ensure_java_keypair(kp)
111
+ raise PkernelJce::Error, "Keypair to check for Java keypair type is nil" if kp.nil?
112
+ end
113
+
114
+ def KeyPair.is_public_key?(key)
115
+ if key.nil?
116
+ false
117
+ else
118
+ case key
119
+ when java.security.interfaces.RSAPublicKey, Java::OrgBouncycastleJcajceProviderAsymmetricDsa::BCDSAPublicKey,Java::sun.security.provider.DSAPublicKey, Java::OrgBouncycastleJcajceProviderAsymmetricEc::BCECPublicKey
120
+ true
121
+ else
122
+ false
123
+ end
124
+ end
125
+ end
126
+
127
+ def KeyPair.is_private_key?(key)
128
+ if key.nil?
129
+ false
130
+ else
131
+ case key
132
+ when java.security.interfaces.RSAPrivateCrtKey, Java::sun.security.provider.DSAPrivateKey, org.bouncycastle.jcajce.provider.asymmetric.dsa.BCDSAPrivateKey, org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey
133
+ true
134
+ else
135
+ false
136
+ end
137
+ end
138
+ end
139
+
140
+ def KeyPair.is_keypair?(key)
141
+ if key.nil?
142
+ false
143
+ else
144
+ case key
145
+ when java.security.KeyPair
146
+ true
147
+ else
148
+ false
149
+ end
150
+ end
151
+ end
152
+
153
+ def KeyPair.public_key(priv)
154
+ if priv.nil?
155
+ raise PkernelJce::Error, "Cannot derive public key from nil key"
156
+ else
157
+ if priv.java_kind_of?(java.security.KeyPair)
158
+ priv.getPublic
159
+ elsif priv.java_kind_of?(java.security.PrivateKey)
160
+ type = key_type(priv)
161
+ case type
162
+ when Pkernel::KeyPair::RSA_KEY_NAME
163
+ java.security.KeyFactory.getInstance("RSA").generatePublic(java.security.spec.RSAPublicKeySpec.new(priv.modulus, priv.public_exponent))
164
+ when Pkernel::KeyPair::DSA_KEY_NAME
165
+ y = priv.params.g.to_java.modPow(priv.x, priv.params.p)
166
+ spec = java.security.spec.DSAPublicKeySpec.new(y, priv.params.p, priv.params.q, priv.params.g)
167
+ prov = PkernelJce::Provider.add_default
168
+ java.security.KeyFactory.getInstance("DSA",prov).generatePublic(spec)
169
+ when Pkernel::KeyPair::EC_KEY_NAME
170
+ d = priv.d;
171
+ q = priv.parameters.g.to_java.multiply(d);
172
+ pubSpec = org.bouncycastle.jce.spec.ECPublicKeySpec.new(q, priv.parameters);
173
+ prov = PkernelJce::Provider.add_default
174
+ java.security.KeyFactory.getInstance("EC",prov).generatePublic(pubSpec)
175
+ else
176
+ end
177
+ elsif priv.java_kind_of?(java.security.PublicKey)
178
+ priv
179
+ elsif priv.java_kind_of?(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo)
180
+ org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter.new.getPublicKey(priv)
181
+ elsif priv.java_kind_of?(org.bouncycastle.cert.X509CertificateHolder)
182
+ org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter.new.getPublicKey(priv.subject_public_key_info)
183
+ elsif priv.java_kind_of?(java.security.cert.Certificate)
184
+ priv.public_key
185
+ else
186
+ raise PkernelJce::Error, "Unsupported key type '#{priv.class}' to convert to public key"
187
+ end
188
+ end
189
+ end
190
+ # end public_key(priv)
191
+ #
192
+
193
+ # harmonize the private key acquiring
194
+ # There are BC and Java, keypair and private key
195
+ def KeyPair.private_key(kp)
196
+ if kp.nil?
197
+ raise PkernelJce::Error, "Cannot derive private key from nil private key"
198
+ else
199
+ case kp
200
+ when java.security.KeyPair
201
+ kp.private
202
+ when java.security.PrivateKey
203
+ kp
204
+ else
205
+ raise PkernelJce::Error, "Unsupported key type '#{kp}' to derive private key from."
206
+ end
207
+ end
208
+ end
209
+
210
+ def KeyPair.derive_signing_algo(kp, hashAlgo = "SHA256")
211
+ raise PkernelJce::Error, "Hashing algo should not be nil while deriving signing algo" if hashAlgo.nil?
212
+
213
+ PkernelJce::GConf.instance.glog.debug "Derive signing algo for key '#{kp.class}'"
214
+
215
+ if KeyPair.is_keypair?(kp)
216
+ type = PkernelJce::KeyPair.key_type(KeyPair.private_key(kp))
217
+ elsif KeyPair.is_public_key?(kp)
218
+ type = PkernelJce::KeyPair.pub_key_type(kp)
219
+ elsif Certificate.is_cert_object?(kp)
220
+ type = PkernelJce::KeyPair.pub_key_type(Certificate.public_key(kp))
221
+ elsif KeyPair.is_private_key?(kp)
222
+ type = PkernelJce::KeyPair.key_type(kp)
223
+ else
224
+ raise PkernelJce::Error, "Unknown key type to derive signing key algo from"
225
+ end
226
+
227
+ #type = PkernelJce::KeyPair.key_type(kp)
228
+ case type
229
+ when Pkernel::KeyPair::RSA_KEY_NAME
230
+ "#{hashAlgo}with#{type.upcase}"
231
+ when Pkernel::KeyPair::DSA_KEY_NAME
232
+ "#{hashAlgo}with#{type.upcase}"
233
+ when Pkernel::KeyPair::EC_KEY_NAME
234
+ "#{hashAlgo}with#{type.upcase}DSA"
235
+ else
236
+ raise PkernelJce::Error, "Unsupported type to derive signing algo '#{type}'"
237
+ end
238
+ end
239
+
240
+ def dump(keypair, options = {})
241
+ if keypair.nil?
242
+ raise PkernelJce::Error, "Keypair is nil during writing PEM"
243
+ end
244
+
245
+ # outputStream only make sense in Java world
246
+ #os = options[:outputStream]
247
+ file = options[:file]
248
+ pass = options[:password]
249
+
250
+ binOut = java.io.ByteArrayOutputStream.new
251
+
252
+ if file.nil?
253
+ PkernelJce::GConf.instance.glog.debug "Dump output to memory"
254
+ # return binary to caller
255
+ writer = org.bouncycastle.openssl.jcajce.JcaPEMWriter.new(java.io.OutputStreamWriter.new(binOut));
256
+ else
257
+ PkernelJce::GConf.instance.glog.debug "Dump output to file '#{file}'"
258
+ out = java.io.FileOutputStream.new(file)
259
+ writer = org.bouncycastle.openssl.jcajce.JcaPEMWriter.new(java.io.OutputStreamWriter.new(out));
260
+ end
261
+
262
+ begin
263
+ if pass.nil? or pass.empty?
264
+ writer.writeObject(keypair.getPrivate)
265
+ else
266
+ builder = org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder.new(org.bouncycastle.openssl.PKCS8Generator::AES_256_CBC).setProvider(PkernelJce::Provider::DefProvider).setPasssword(pass.to_java.toCharArray());
267
+
268
+ pkcs8 = org.bouncycastle.openssl.jcajce.JcaPKCS8Generator.new(keypair.getPrivate, builder.build);
269
+ writer.writeObject(pkcs8)
270
+ end
271
+ ensure
272
+ writer.flush
273
+ writer.close
274
+ end
275
+
276
+ if file.nil?
277
+ binOut.toByteArray
278
+ end
279
+ end
280
+ # end dump
281
+
282
+ def load(opts = {}, &block)
283
+ #is = opts[:inputStream]
284
+ #if is.nil?
285
+ # raise PkernelJce::Error, "InputStream not given"
286
+ #end
287
+ file = opts[:file]
288
+ bin = opts[:bin]
289
+
290
+ baos = java.io.ByteArrayOutputStream.new
291
+
292
+ if not file.nil? and not file.empty?
293
+ PkernelJce::GConf.instance.glog.debug "Load keypair from file '#{file}'"
294
+ f = java.io.File.new(file)
295
+ if f.exists?
296
+ b = Java::byte[f.length].new
297
+ dis = java.io.DataInputStream.new(java.io.FileInputStream.new(f))
298
+ dis.readFully(b)
299
+ dis.close
300
+
301
+ baos.write(b)
302
+ else
303
+ raise PkernelJce::Error, "Given file to load '#{f.absolute_path}' does not exist"
304
+ end
305
+ elsif not bin.nil?
306
+ PkernelJce::GConf.instance.glog.debug "Load keypair from memory"
307
+ baos.write(bin)
308
+ else
309
+ raise PkernelJce::Error, "No 'file' or 'bin' is defined to load keypair"
310
+ end
311
+
312
+ prov = opts[:provider] || PkernelJce::Provider::DefProvider
313
+ prov = PkernelJce::Provider.add_provider(prov)
314
+
315
+ reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.ByteArrayInputStream.new(baos.toByteArray)))
316
+ obj = reader.readObject
317
+ #p obj.inspect
318
+ #p obj.methods.sort
319
+ #p obj.java_kind_of?(org.bouncycastle.openssl.PEMEncryptedKeyPair)
320
+ if obj.is_a?(org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo)
321
+ pass = opts[:password]
322
+ if pass.nil?
323
+ if block
324
+ pass = block.call(:password)
325
+ else
326
+ raise PkernelJce::Error, "PEM key is encrypted. Please provide a password to load the key."
327
+ end
328
+ end
329
+ decProv = org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder.new.setProvider(PkernelJce::Provider::DefProvider).build(pass.to_java.toCharArray)
330
+ keyinfo = obj.decryptPrivateKeyInfo(decProv)
331
+
332
+ converter = org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter.new
333
+ converter.getPrivateKey(keyinfo)
334
+ else
335
+ keySpec = java.security.spec.PKCS8EncodedKeySpec.new(obj.getPrivateKeyInfo.encoded)
336
+ # Now it's in a PKCS#8 PrivateKeyInfo structure. Read its Algorithm
337
+ # OID and use that to construct a KeyFactory.
338
+ bIn = org.bouncycastle.asn1.ASN1InputStream.new(java.io.ByteArrayInputStream.new(keySpec.getEncoded()));
339
+ pki = org.bouncycastle.asn1.pkcs.PrivateKeyInfo.getInstance(bIn.readObject());
340
+ algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();
341
+ java.security.KeyFactory.getInstance(algOid,prov).generatePrivate(keySpec);
342
+
343
+ #privKey = java.security.KeyFactory.getInstance("RSA").generatePrivate(keySpec)
344
+ #privKey
345
+ end
346
+
347
+ end
348
+ # end load()
349
+ #
350
+
351
+ end
352
+
353
+
354
+ class KeyPairEngine
355
+ extend KeyPair
356
+ end
357
+
358
+ end
359
+