pkernel_jce 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+