gcrypto_jce 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,121 @@
1
+
2
+ require_relative 'global'
3
+ require 'active_support'
4
+ class NumberHelper
5
+ extend ActiveSupport::NumberHelper
6
+ end
7
+
8
+
9
+ module GcryptoJce
10
+ module IoUtils
11
+
12
+ def IoUtils.load_input(opts = { })
13
+ if opts.nil? or opts.empty?
14
+ raise GcryptoJce::Error, "No input given to load"
15
+ else
16
+ file = opts[:file]
17
+ bin = opts[:bin]
18
+
19
+ if not (file.nil? or file.empty?)
20
+ fis = java.io.FileInputStream.new(file)
21
+ fis
22
+ elsif not bin.nil?
23
+ begin
24
+ bais = java.io.ByteArrayInputStream.new(bin.to_java_bytes)
25
+ rescue NoMethodError
26
+ bais = java.io.ByteArrayInputStream.new(bin)
27
+ end
28
+ bais
29
+ else
30
+ if not (opts[:input_optional].nil? and opts[:input_optional])
31
+ raise GcryptoJce::Error, "Neither file nor bin given to load input"
32
+ end
33
+ end
34
+ end
35
+ end
36
+ #
37
+ # end load_input()
38
+ #
39
+
40
+ def IoUtils.prep_output(opts = { })
41
+
42
+ if opts.nil? or opts.empty?
43
+ raise GcryptoJce::Error, "No opts given to prep output"
44
+ else
45
+ file = opts[:outFile]
46
+
47
+ if not (file.nil? or file.empty?)
48
+ fos = java.io.FileOutputStream.new(file)
49
+ fos
50
+ else
51
+ baos = java.io.ByteArrayOutputStream.new
52
+ baos
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ def IoUtils.return_if_buffer(os)
59
+ if os.java_kind_of?(java.io.ByteArrayOutputStream)
60
+ os.toByteArray
61
+ end
62
+ end
63
+
64
+ def IoUtils.read_chunk(is, opts = { },&block)
65
+
66
+ raise GcryptoJce::Error, "Cannot read chunk from nil input stream" if is.nil?
67
+ raise GcryptoJce::Error, "Block required for read_chunk" if not block
68
+
69
+ if not is.java_kind_of?(java.io.InputStream)
70
+ raise GcryptoJce::Error, "Cannot read from '#{is.class}' object"
71
+ end
72
+
73
+ bufLen = opts[:buffer_size] || 1024*1024
74
+ GcryptoJce::GConf.instance.glog.debug "read_chunk buffer size is #{NumberHelper.number_to_human_size(bufLen)}. Modifiable by caller app via key :in_buf -> :buffer_size"
75
+
76
+ b = Java::byte[bufLen].new
77
+ while((read = is.read(b,0,b.length)) != -1)
78
+ block.call(b,0,read)
79
+ end
80
+ end
81
+ #
82
+ # end read_chunk
83
+ #
84
+
85
+ def IoUtils.file_to_memory_byte_array(path)
86
+ if path.nil? or path.empty?
87
+ raise PkernelJce::Error, "Given path '#{path}' to load to memory is nil or empty"
88
+ else
89
+ f = java.io.File.new(path)
90
+ b = Java::byte[f.length].new
91
+ dis = java.io.DataInputStream.new(java.io.FileInputStream.new(f))
92
+ dis.readFully(b)
93
+ dis.close
94
+
95
+ b
96
+ end
97
+ end
98
+ # end file_to_memory_byte_array
99
+ #
100
+
101
+ def IoUtils.ensure_java_bytes(bin)
102
+ if not bin.java_kind_of?(Java::byte[])
103
+ bin.to_java_bytes
104
+ else
105
+ bin
106
+ end
107
+ end
108
+ # end ensure_java_bytes
109
+ #
110
+
111
+ def IoUtils.attempt_zeroise(var)
112
+ java.util.Arrays.fill(var, 0)
113
+ end
114
+ end
115
+ # end IoUtils
116
+ #
117
+
118
+ end
119
+ # end GcryptoJce
120
+ #
121
+
@@ -0,0 +1,278 @@
1
+
2
+
3
+ require 'pkernel'
4
+ require 'pkernel_jce'
5
+
6
+ require_relative 'error'
7
+ require_relative 'io_utils'
8
+ require_relative 'provider'
9
+ require_relative 'global'
10
+
11
+ module GcryptoJce
12
+
13
+ module KeyPairCrypto
14
+
15
+ def sign(opts = { })
16
+ raise GcryptoJce::Error, "Insufficient parameters for signature generation" if opts.nil? or opts.empty?
17
+
18
+ id = opts[:identity]
19
+ if id.nil?
20
+ raise GcryptoJce::Error, "Identity to sign the data is not available"
21
+ end
22
+
23
+ prov = GcryptoJce::Provider.handle_options(opts, nil)
24
+
25
+ is = IoUtils.load_input(opts)
26
+
27
+ if prov.nil?
28
+ GcryptoJce::GConf.instance.glog.debug "Provider is nil"
29
+ sign = java.security.Signature.getInstance(KeyPairCrypto.derive_signing_algo(id.privKey))
30
+ else
31
+ GcryptoJce::GConf.instance.glog.debug "Provider is '#{prov.name}'"
32
+ sign = java.security.Signature.getInstance(KeyPairCrypto.derive_signing_algo(id.privKey), prov)
33
+ end
34
+
35
+
36
+ GcryptoJce::GConf.instance.glog.debug "Private key is #{id.privKey.class}"
37
+ sign.initSign(id.privKey)
38
+
39
+ begin
40
+ IoUtils.read_chunk(is) do |buf, from, len|
41
+ sign.update(buf, from, len)
42
+ end
43
+ rescue Exception => ex
44
+ GcryptoJce::GConf.instance.glog.error ex.message
45
+ GcryptoJce::GConf.instance.glog.error ex.backtrace.join("\n")
46
+ ensure
47
+ begin
48
+ is.close
49
+ rescue Exception
50
+ end
51
+ end
52
+
53
+ sign.sign
54
+
55
+ end
56
+ #
57
+ # end method sign()
58
+ #
59
+
60
+ def KeyPairCrypto.derive_signing_algo(kp, hash = "SHA256")
61
+ PkernelJce::KeyPair.derive_signing_algo(kp,hash)
62
+ end
63
+
64
+ def verify(opts = { })
65
+
66
+ if opts.nil? or opts.empty?
67
+ raise GcryptoJce::Error, "Insufficient parameters for signature verification"
68
+ end
69
+
70
+ file = opts[:sign_file]
71
+ bin = opts[:sign_bin]
72
+ if not (file.nil? or file.empty?)
73
+ signBin = IoUtils.file_to_memory_byte_array(file)
74
+ elsif not bin.nil?
75
+ signBin = IoUtils.ensure_java_bytes(bin)
76
+ else
77
+ raise GcryptoJce::Error, "Neither signature in file or memory buffer given for signatur verification"
78
+ end
79
+
80
+ is = IoUtils.load_input(opts)
81
+ prov = GcryptoJce::Provider.handle_options(opts, nil)
82
+
83
+ cert = opts[:certificate]
84
+ pubKey = opts[:pubKey]
85
+ if not cert.nil?
86
+
87
+ if prov.nil?
88
+ GcryptoJce::GConf.instance.glog.debug "Provider is nil"
89
+ sign = java.security.Signature.getInstance(KeyPairCrypto.derive_signing_algo(cert))
90
+ else
91
+ GcryptoJce::GConf.instance.glog.debug "Provider is '#{prov.name}'"
92
+ sign = java.security.Signature.getInstance(KeyPairCrypto.derive_signing_algo(cert), prov)
93
+ end
94
+
95
+ sign.initVerify(cert)
96
+
97
+ elsif not pubKey.nil?
98
+
99
+ if prov.nil?
100
+ GcryptoJce::GConf.instance.glog.debug "Provider is nil"
101
+ sign = java.security.Signature.getInstance(KeyPairCrypto.derive_signing_algo(pubKey))
102
+ else
103
+ GcryptoJce::GConf.instance.glog.debug "Provider is '#{prov.name}'"
104
+ sign = java.security.Signature.getInstance(KeyPairCrypto.derive_signing_algo(pubKey), prov)
105
+ end
106
+
107
+ sign.initVerify(pubKey)
108
+
109
+ else
110
+ raise GcryptoJce::Error, "No public key or certificate during signature verification"
111
+ end
112
+
113
+ begin
114
+ IoUtils.read_chunk(is) do |buf, from, len|
115
+ sign.update(buf, from, len)
116
+ end
117
+ rescue Exception => ex
118
+ GcryptoJce::GConf.instance.glog.error ex.message
119
+ GcryptoJce::GConf.instance.glog.error ex.backtrace.join("\n")
120
+ ensure
121
+ begin
122
+ is.close
123
+ rescue Exception
124
+ end
125
+ end
126
+
127
+ sign.verify(signBin)
128
+
129
+ end
130
+ #
131
+ # end method verify()
132
+ #
133
+
134
+
135
+ def encrypt(opts = { })
136
+
137
+ file = opts[:file]
138
+ bin = opts[:bin]
139
+
140
+ # assumption:
141
+ # Data size is small (~kb)
142
+ # Because for RSA the max data = public key size
143
+ if not (file.nil? or file.empty?)
144
+ data = IoUtils.file_to_memory_byte_array(file)
145
+ elsif not bin.nil?
146
+ data = IoUtils.ensure_java_bytes(bin)
147
+ else
148
+ raise GcryptoJce::Error, "No input given for keypair encryption"
149
+ end
150
+
151
+ recp = opts[:recipient]
152
+ if recp.nil?
153
+ raise GcryptoJce::Error, "No recipient given for keypair encryption"
154
+ end
155
+
156
+ if Pkernel::Certificate.is_cert_object?(recp)
157
+ pubKey = Pkernel::Certificate.public_key(recp)
158
+ elsif Pkernel::KeyPair.is_public_key?(recp)
159
+ pubKey = recp
160
+ else
161
+ raise GcryptoJce::Error, "Given recipient is neither certificate nor public key."
162
+ end
163
+
164
+ prov = GcryptoJce::Provider.handle_options(opts, nil)
165
+
166
+ cipherSpec = opts[:cipher_spec] || "RSA/ECB/OAEPWithSHA-256AndMGF1Padding"
167
+ type = Pkernel::KeyPair.pub_key_type(pubKey)
168
+ case type
169
+ when Pkernel::KeyPair::RSA_KEY_NAME
170
+ if prov.nil?
171
+ GcryptoJce::GConf.instance.glog.debug "Provider is nil"
172
+ if cipherSpec =~ /PKCS5Padding/
173
+ GcryptoJce::GConf.instance.glog.warn "PKCS#1 1.5 may be vulnerable to Bleichenbacher's CCA attack"
174
+ end
175
+ GcryptoJce::GConf.instance.glog.debug "Using cipher spec '#{cipherSpec}'"
176
+ cipher = javax.crypto.Cipher.getInstance(cipherSpec)
177
+ else
178
+ GcryptoJce::GConf.instance.glog.debug "Provider is '#{prov.name}'"
179
+ cipher = javax.crypto.Cipher.getInstance(cipherSpec, prov)
180
+ end
181
+ else
182
+ raise GcryptoJce::Error, "Unsupported key type '#{pubKey}' for keypair data encryption operation"
183
+ end
184
+
185
+ cipher.init(javax.crypto.Cipher::ENCRYPT_MODE, pubKey)
186
+
187
+ outStream = opts[:outStream]
188
+ if not outStream.nil?
189
+ outStream.write(cipher.update(data))
190
+ outStream.write(cipher.doFinal)
191
+ outStream.flush
192
+ else
193
+ baos = java.io.ByteArrayOutputStream.new
194
+ baos.write(cipher.update(data))
195
+ baos.write(cipher.doFinal)
196
+ baos.toByteArray
197
+ end
198
+
199
+ end
200
+ #
201
+ # end encrypt()
202
+ #
203
+
204
+ def decrypt(opts = { })
205
+
206
+ file = opts[:enc_file]
207
+ bin = opts[:enc_bin]
208
+
209
+ # assumption:
210
+ # Data size is small (~kb)
211
+ # Because for RSA the max data = public key size
212
+ if not (file.nil? or file.empty?)
213
+ data = IoUtils.file_to_memory_byte_array(file)
214
+ elsif not bin.nil?
215
+ data = IoUtils.ensure_java_bytes(bin)
216
+ else
217
+ raise GcryptoJce::Error, "No input given for decrypt"
218
+ end
219
+
220
+ id = opts[:identity]
221
+ if id.nil?
222
+ raise GcryptoJce::Error, "No identity given for decrypt"
223
+ end
224
+
225
+ if id.privKey.nil?
226
+ raise GcryptoJce::Error, "Private key is nil for data decryption"
227
+ end
228
+
229
+ prov = GcryptoJce::Provider.handle_options(opts, nil)
230
+
231
+ cipherSpec = opts[:cipher_spec] || "RSA/ECB/OAEPWithSHA-256AndMGF1Padding"
232
+ type = Pkernel::KeyPair.key_type(id.privKey)
233
+ case type
234
+ when Pkernel::KeyPair::RSA_KEY_NAME
235
+ if prov.nil?
236
+ GcryptoJce::GConf.instance.glog.debug "Provider is nil"
237
+ if cipherSpec =~ /PKCS5Padding/
238
+ GcryptoJce::GConf.instance.glog.warn "PKCS#1 1.5 may be vulnerable to Bleichenbacher's CCA attack"
239
+ end
240
+ GcryptoJce::GConf.instance.glog.debug "Using cipher spec '#{cipherSpec}'"
241
+ cipher = javax.crypto.Cipher.getInstance(cipherSpec)
242
+ else
243
+ GcryptoJce::GConf.instance.glog.debug "Provider is '#{prov.name}'"
244
+ cipher = javax.crypto.Cipher.getInstance(cipherSpec, prov)
245
+ end
246
+ else
247
+ raise GcryptoJce::Error, "Unsupported key type '#{id.privKey}' for data decryption operation"
248
+ end
249
+
250
+ cipher.init(javax.crypto.Cipher::DECRYPT_MODE, id.privKey)
251
+
252
+ outStream = opts[:outStream]
253
+ if not outStream.nil?
254
+ outStream.write(cipher.update(data))
255
+ outStream.write(cipher.doFinal)
256
+ outStream.flush
257
+ else
258
+ baos = java.io.ByteArrayOutputStream.new
259
+ baos.write(cipher.update(data))
260
+ baos.write(cipher.doFinal)
261
+ baos.toByteArray
262
+ end
263
+
264
+ end
265
+ #
266
+ # end decrypt()
267
+ #
268
+
269
+ end
270
+ # end KeyPairCrypto
271
+ #
272
+
273
+ class KeyPairCryptoEngine
274
+ extend KeyPairCrypto
275
+ end
276
+
277
+ end
278
+ # end gcrypto
@@ -0,0 +1,95 @@
1
+
2
+ require 'gcrypto'
3
+ require_relative 'secretkey'
4
+ require_relative 'error'
5
+ require_relative 'io_utils'
6
+ require_relative 'provider'
7
+ require_relative 'global'
8
+ require_relative 'converter'
9
+
10
+ module GcryptoJce
11
+ module KDF
12
+ module PBKDF2
13
+
14
+ def derive(pass, opts = { })
15
+
16
+ if pass.nil? or pass.empty?
17
+ raise GcryptoJce::Error, "Password to derive is empty"
18
+ else
19
+ if pass.is_a?(String)
20
+ pa = pass.to_java.toCharArray
21
+ elsif pass.java_kind_of?(Java::byte[])
22
+ pa = String.from_java_bytes(pass).to_java.toCharArray
23
+ elsif pass.java_kind_of?(Java::char[])
24
+ pa = pass
25
+ else
26
+ raise GcryptoJce::Error, "Unknown password type '#{pass.class}'"
27
+ end
28
+ end
29
+
30
+ iter = opts[:iteration]
31
+ if iter.nil? or iter.to_i == 0
32
+ iter = rand(10000...20000)
33
+ end
34
+
35
+ keyLen = opts[:outKeyLen]
36
+ case keyLen
37
+ when 128
38
+ outKeyLen = 128
39
+ engSpec = "PBKDF2WithHMACSHA1"
40
+ when 256, 192
41
+ outKeyLen = 256
42
+ engSpec = "PBKDF2WithHMACSHA256"
43
+ when 512
44
+ outKeyLen = 512
45
+ engSpec = "PBKDF2WithHMACSHA512"
46
+ else
47
+ outKeyLen = 256
48
+ engSpec = "PBKDF2WithHMACSHA256"
49
+ end
50
+
51
+ prov = GcryptoJce::Provider.handle_options(opts, nil)
52
+
53
+ salt = opts[:salt]
54
+ if salt.nil?
55
+ salt = Java::byte[outKeyLen/8].new
56
+ java.security.SecureRandom.new.nextBytes(salt)
57
+ end
58
+
59
+ GcryptoJce::GConf.instance.glog.debug "PBKDF2 using config salt : #{Gcrypto::Converter.to_hex(salt)} / iteration : #{iter} / output hash length : #{outKeyLen} / Eng : #{engSpec}"
60
+ spec = javax.crypto.spec.PBEKeySpec.new(pa, salt, iter, outKeyLen)
61
+ if prov.nil?
62
+ fact = javax.crypto.SecretKeyFactory.getInstance(engSpec)
63
+ else
64
+ fact = javax.crypto.SecretKeyFactory.getInstance(engSpec, prov)
65
+ end
66
+
67
+ secKey = fact.generateSecret(spec)
68
+ key = javax.crypto.spec.SecretKeySpec.new(secKey.encoded,"AES")
69
+
70
+ res = { }
71
+ res[:key] = key
72
+ res[:hash] = secKey.getEncoded
73
+ res[:salt] = salt
74
+ res[:iteration] = iter
75
+ res[:hashLen] = outKeyLen
76
+ res[:eng] = :pbkdf2
77
+
78
+ res
79
+
80
+ end
81
+ end
82
+ # end PBKDF2
83
+ #
84
+
85
+ class PBKDF2Engine
86
+ extend PBKDF2
87
+ end
88
+
89
+ end
90
+ # end KDF
91
+ #
92
+
93
+ end
94
+ # end GcryptoJce
95
+ #