gcrypto_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 +12 -0
- data/.ruby-version +1 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +60 -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/gcrypto_jce.gemspec +47 -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/gcrypto_jce.rb +49 -0
- data/lib/gcrypto_jce/converter.rb +29 -0
- data/lib/gcrypto_jce/digest.rb +56 -0
- data/lib/gcrypto_jce/error.rb +6 -0
- data/lib/gcrypto_jce/global.rb +26 -0
- data/lib/gcrypto_jce/hkdf.rb +143 -0
- data/lib/gcrypto_jce/io_utils.rb +121 -0
- data/lib/gcrypto_jce/keypair_crypto.rb +278 -0
- data/lib/gcrypto_jce/pbkdf2.rb +95 -0
- data/lib/gcrypto_jce/provider.rb +66 -0
- data/lib/gcrypto_jce/secretkey.rb +159 -0
- data/lib/gcrypto_jce/secretkey_crypto.rb +412 -0
- data/lib/gcrypto_jce/secure_random.rb +43 -0
- data/lib/gcrypto_jce/version.rb +3 -0
- data/release.job +52 -0
- metadata +158 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
Dir.glob(File.join(File.dirname(__FILE__),'../../jars/*.jar')).each do |f|
|
4
|
+
require_relative File.expand_path(f)
|
5
|
+
end
|
6
|
+
|
7
|
+
require_relative 'global'
|
8
|
+
|
9
|
+
module GcryptoJce
|
10
|
+
module Provider
|
11
|
+
|
12
|
+
DefProvider = org.bouncycastle.jce.provider.BouncyCastleProvider.new
|
13
|
+
|
14
|
+
def Provider::add_default
|
15
|
+
add_provider(DefProvider)
|
16
|
+
DefProvider
|
17
|
+
end
|
18
|
+
#
|
19
|
+
# end add_default
|
20
|
+
#
|
21
|
+
|
22
|
+
def Provider::add_provider(prov)
|
23
|
+
if prov != nil
|
24
|
+
if prov.is_a?(String) and not prov.empty?
|
25
|
+
GcryptoJce::GConf.instance.glog.error "Unknown provider by string '#{prov}'. Please use provider object."
|
26
|
+
raise Exception, "Unknown provider by string '#{prov}'. Please use provider object."
|
27
|
+
elsif prov.is_a?(java.security.Provider)
|
28
|
+
if prov != nil
|
29
|
+
if not java.security.Security.get_providers.to_a.include?(prov)
|
30
|
+
GcryptoJce::GConf.instance.glog.debug "Adding security provider '#{prov.name}'"
|
31
|
+
java.security.Security.add_provider(prov)
|
32
|
+
end
|
33
|
+
prov
|
34
|
+
else
|
35
|
+
raise Exception, "Unknown provider object #{prov.inspect}"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
#
|
43
|
+
# end add_provider
|
44
|
+
#
|
45
|
+
|
46
|
+
def Provider::handle_options(opts = { }, def_if_nil = DefProvider)
|
47
|
+
if opts.nil? or opts.empty?
|
48
|
+
else
|
49
|
+
prov = opts[:provider]
|
50
|
+
if prov.nil?
|
51
|
+
if def_if_nil != nil
|
52
|
+
Provider::add_provider(def_if_nil)
|
53
|
+
end
|
54
|
+
else
|
55
|
+
Provider::add_provider(prov)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
#
|
60
|
+
# add handle_options
|
61
|
+
#
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
@@ -0,0 +1,159 @@
|
|
1
|
+
|
2
|
+
require 'pkernel'
|
3
|
+
require 'pkernel_jce'
|
4
|
+
|
5
|
+
require_relative 'error'
|
6
|
+
require_relative 'io_utils'
|
7
|
+
require_relative 'provider'
|
8
|
+
require_relative 'global'
|
9
|
+
|
10
|
+
module GcryptoJce
|
11
|
+
module SecretKey
|
12
|
+
|
13
|
+
def generate(opts = { })
|
14
|
+
|
15
|
+
skType = opts[:type]
|
16
|
+
if skType.nil?
|
17
|
+
raise GcryptoJce::Error, "Secret key type is not given for generation"
|
18
|
+
else
|
19
|
+
skType = to_algo_string(skType)
|
20
|
+
end
|
21
|
+
|
22
|
+
prov = GcryptoJce::Provider.handle_options(opts, nil)
|
23
|
+
|
24
|
+
if prov.nil?
|
25
|
+
GcryptoJce::GConf.instance.glog.debug "Provider is nil"
|
26
|
+
kg = javax.crypto.KeyGenerator.getInstance(skType)
|
27
|
+
else
|
28
|
+
GcryptoJce::GConf.instance.glog.debug "Provider is '#{prov.name}'"
|
29
|
+
kg = javax.crypto.KeyGenerator.getInstance(skType, prov)
|
30
|
+
end
|
31
|
+
|
32
|
+
keyLen = opts[:keyLen]
|
33
|
+
secRandom = opts[:secRandom]
|
34
|
+
if keyLen.nil? or keyLen.to_i == 0
|
35
|
+
raise GcryptoJce::Error, "Key length not given or invalid"
|
36
|
+
else
|
37
|
+
if secRandom.nil?
|
38
|
+
kg.init(keyLen.to_i)
|
39
|
+
else
|
40
|
+
kg.init(keyLen.to_i, secRandom)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
kg.generateKey
|
45
|
+
|
46
|
+
end
|
47
|
+
# end generate()
|
48
|
+
#
|
49
|
+
|
50
|
+
def SecretKey.is_secret_key?(obj)
|
51
|
+
if obj.nil?
|
52
|
+
false
|
53
|
+
else
|
54
|
+
obj.java_kind_of?(javax.crypto.spec.SecretKeySpec)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def dump(sk, opts = { })
|
59
|
+
file = opts[:file]
|
60
|
+
baos = java.io.ByteArrayOutputStream.new
|
61
|
+
|
62
|
+
if not (file.nil? or file.empty?)
|
63
|
+
os = java.io.ObjectOutputStream.new(java.io.FileOutputStream.new(file))
|
64
|
+
else
|
65
|
+
os = java.io.ObjectOutputStream.new(baos)
|
66
|
+
end
|
67
|
+
|
68
|
+
os.writeObject(sk)
|
69
|
+
os.flush
|
70
|
+
os.close
|
71
|
+
|
72
|
+
if not (file.nil? or file.empty?)
|
73
|
+
else
|
74
|
+
baos.toByteArray
|
75
|
+
end
|
76
|
+
end
|
77
|
+
# end dump()
|
78
|
+
|
79
|
+
def load(opts = { })
|
80
|
+
file = opts[:file]
|
81
|
+
bin = opts[:bin]
|
82
|
+
if not (file.nil? or file.empty?)
|
83
|
+
skBin = IoUtils.file_to_memory_byte_array(file)
|
84
|
+
elsif not bin.nil?
|
85
|
+
skBin = IoUtils.ensure_java_bytes(bin)
|
86
|
+
else
|
87
|
+
raise GcryptoJce::Error, "No file or buffer given to load secret key"
|
88
|
+
end
|
89
|
+
|
90
|
+
skOs = java.io.ObjectInputStream.new(java.io.ByteArrayInputStream.new(skBin))
|
91
|
+
sk = skOs.readObject
|
92
|
+
skOs.close
|
93
|
+
|
94
|
+
sk
|
95
|
+
end
|
96
|
+
# end load()
|
97
|
+
|
98
|
+
def load_from_bin(opts = { })
|
99
|
+
file = opts[:file]
|
100
|
+
bin = opts[:bin]
|
101
|
+
if not (file.nil? or file.empty?)
|
102
|
+
skBin = IoUtils.file_to_memory_byte_array(file)
|
103
|
+
elsif not bin.nil?
|
104
|
+
skBin = IoUtils.ensure_java_bytes(bin)
|
105
|
+
else
|
106
|
+
raise GcryptoJce::Error, "No file or buffer given to load secret key from binary"
|
107
|
+
end
|
108
|
+
|
109
|
+
skType = opts[:type]
|
110
|
+
if skType.nil? or skType.empty?
|
111
|
+
raise GcryptoJce::Error, "Secret Key type is not given to load from binary"
|
112
|
+
end
|
113
|
+
|
114
|
+
javax.crypto.spec.SecretKeySpec.new(skBin, skType)
|
115
|
+
end
|
116
|
+
|
117
|
+
def to_algo_string(key)
|
118
|
+
key = key.to_s.upcase
|
119
|
+
case key
|
120
|
+
when "AES"
|
121
|
+
"AES"
|
122
|
+
when "3DES", "TRIPLEDES", "TRIPLE-DES", "3-DES"
|
123
|
+
"3DES"
|
124
|
+
else
|
125
|
+
"AES"
|
126
|
+
#raise GcryptoJce::Error, "Unknown algo '#{key}'"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
#
|
130
|
+
# end to_algo_string
|
131
|
+
#
|
132
|
+
|
133
|
+
def SecretKey.key_type(secKeySpec)
|
134
|
+
algo = secKeySepc.algorithm
|
135
|
+
case algo
|
136
|
+
when "AES"
|
137
|
+
"AES"
|
138
|
+
when "3DES"
|
139
|
+
"3DES"
|
140
|
+
else
|
141
|
+
raise GcryptoJce::Error, "Unknown key type '#{algo}'"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
#
|
145
|
+
# end key_type
|
146
|
+
#
|
147
|
+
|
148
|
+
end
|
149
|
+
#
|
150
|
+
# end module SecretKey
|
151
|
+
#
|
152
|
+
|
153
|
+
class SecretKeyFactory
|
154
|
+
extend SecretKey
|
155
|
+
end
|
156
|
+
end
|
157
|
+
#
|
158
|
+
# end module Gcrypto
|
159
|
+
#
|
@@ -0,0 +1,412 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
require 'pkernel'
|
4
|
+
require 'pkernel_jce'
|
5
|
+
|
6
|
+
require 'gcrypto'
|
7
|
+
|
8
|
+
require_relative 'error'
|
9
|
+
require_relative 'io_utils'
|
10
|
+
require_relative 'provider'
|
11
|
+
require_relative 'global'
|
12
|
+
require_relative 'secretkey'
|
13
|
+
require_relative 'pbkdf2'
|
14
|
+
|
15
|
+
require 'securerandom'
|
16
|
+
|
17
|
+
require 'active_support'
|
18
|
+
class NumberHelper
|
19
|
+
extend ActiveSupport::NumberHelper
|
20
|
+
end
|
21
|
+
|
22
|
+
module Gcrypto #::SecretKeyCryptoContext
|
23
|
+
class AESCContext
|
24
|
+
attr_accessor :padding, :secure_random, :key_provider, :name
|
25
|
+
alias_method :ori_init, :initialize
|
26
|
+
def initialize
|
27
|
+
ori_init
|
28
|
+
#@keyType = :aes
|
29
|
+
#@keyLen = 256
|
30
|
+
#@mode = "GCM"
|
31
|
+
#@padding = "NoPadding"
|
32
|
+
@mode = "CBC"
|
33
|
+
#@padding = "PKCS5Padding"
|
34
|
+
@name = ::SecureRandom.hex(8) # KEK requires an ID, just generates it...
|
35
|
+
begin
|
36
|
+
# java 8 introduce getInstanceStrong()
|
37
|
+
@secure_random = java.security.SecureRandom.getInstanceStrong
|
38
|
+
rescue Exception
|
39
|
+
@secure_random = java.security.SecureRandom.getInstance('SHA1PRNG')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def padding
|
44
|
+
if @padding.nil? or @padding.empty?
|
45
|
+
case @mode
|
46
|
+
when "CBC"
|
47
|
+
@padding = "PKCS5Padding"
|
48
|
+
when "GCM"
|
49
|
+
@padding = "NoPadding"
|
50
|
+
else
|
51
|
+
@padding = "PKCS5Padding"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
@padding
|
56
|
+
end
|
57
|
+
|
58
|
+
def random_iv
|
59
|
+
if @iv.nil? or @iv.empty?
|
60
|
+
if mode == "GCM"
|
61
|
+
@iv = Java::byte[12].new # for GCM mode
|
62
|
+
else
|
63
|
+
@iv = Java::byte[16].new # for CBC mode
|
64
|
+
end
|
65
|
+
#@iv = Java::byte[12].new # for GCM mode
|
66
|
+
#@iv = Java::byte[16].new # for CBC mode
|
67
|
+
@secure_random.nextBytes(@iv)
|
68
|
+
end
|
69
|
+
|
70
|
+
@iv
|
71
|
+
end
|
72
|
+
# end random_iv
|
73
|
+
|
74
|
+
def random_key
|
75
|
+
if @key.nil?
|
76
|
+
conf = { type: @keyType, keyLen: @keyLen }
|
77
|
+
if @key_provider.nil?
|
78
|
+
else
|
79
|
+
conf.merge!({ provider: @key_provider })
|
80
|
+
end
|
81
|
+
|
82
|
+
if not @secure_random.nil?
|
83
|
+
conf.merge!({ secRandom: @secure_random })
|
84
|
+
end
|
85
|
+
|
86
|
+
@key = GcryptoJce::SecretKeyFactory.generate(conf)
|
87
|
+
end
|
88
|
+
|
89
|
+
@key
|
90
|
+
end
|
91
|
+
# end ramdom_key
|
92
|
+
|
93
|
+
def raw_key=(val)
|
94
|
+
@raw_key = val
|
95
|
+
|
96
|
+
if not @raw_key.nil?
|
97
|
+
@key = GcryptoJce::SecretKeyFactory.load_from_bin({ bin: @raw_key, type: "AES" })
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def raw_key
|
102
|
+
@raw_key
|
103
|
+
end
|
104
|
+
|
105
|
+
def derive_key(pass, opts = { })
|
106
|
+
|
107
|
+
eng = opts[:eng] || :pbkdf2
|
108
|
+
|
109
|
+
case eng
|
110
|
+
when :pbkdf2
|
111
|
+
opts.merge!( { reqKeyLen: @keyLen } )
|
112
|
+
res = GcryptoJce::KDF::PBKDF2Engine.derive(pass, opts)
|
113
|
+
@key = res[:key]
|
114
|
+
res.delete(:key)
|
115
|
+
|
116
|
+
res
|
117
|
+
else
|
118
|
+
raise GcryptoJce::Error, "Unknown derive key engine '#{eng}'"
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
def to_java_cipher_spec
|
124
|
+
"#{@keyType.to_s.upcase}/#{mode}/#{padding}"
|
125
|
+
end
|
126
|
+
# to_java_cipher_spec
|
127
|
+
|
128
|
+
def to_java_key_type
|
129
|
+
"AES"
|
130
|
+
end
|
131
|
+
|
132
|
+
def algo_params_spec
|
133
|
+
if @mode.upcase == "GCM"
|
134
|
+
if @iv.nil?
|
135
|
+
random_iv
|
136
|
+
end
|
137
|
+
|
138
|
+
# https://javainterviewpoint.com/java-aes-256-gcm-encryption-and-decryption/
|
139
|
+
javax.crypto.spec.GCMParameterSpec.new(16*8, @iv)
|
140
|
+
|
141
|
+
elsif mode == "CBC"
|
142
|
+
if @iv.nil?
|
143
|
+
random_iv
|
144
|
+
end
|
145
|
+
|
146
|
+
javax.crypto.spec.IvParameterSpec.new(@iv)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
# end algo_params_spec
|
150
|
+
|
151
|
+
def mode
|
152
|
+
if not @mode.nil?
|
153
|
+
@mode.to_s.upcase
|
154
|
+
end
|
155
|
+
|
156
|
+
@mode
|
157
|
+
end
|
158
|
+
# end mode
|
159
|
+
|
160
|
+
def finalize
|
161
|
+
IoUtils.attempt_zeroise(@key) if not @key.nil?
|
162
|
+
IoUtils.attempt_zeroise(@iv) if not @iv.nil?
|
163
|
+
end
|
164
|
+
# end finalize
|
165
|
+
|
166
|
+
end
|
167
|
+
# end class AES
|
168
|
+
end
|
169
|
+
# end SecretKeyCryptoContext::AES
|
170
|
+
|
171
|
+
module GcryptoJce
|
172
|
+
|
173
|
+
module SecretKeyCrypto
|
174
|
+
|
175
|
+
def encrypt(opts = { })
|
176
|
+
|
177
|
+
is = IoUtils.load_input(opts)
|
178
|
+
spec = opts[:crypto_context]
|
179
|
+
|
180
|
+
if spec.nil?
|
181
|
+
raise GcryptoJce::Error, "Crypto context is not given for secret key encryption"
|
182
|
+
end
|
183
|
+
|
184
|
+
os = IoUtils.prep_output(opts)
|
185
|
+
#outFile = opts[:outFile]
|
186
|
+
#if not (outFile.nil? or outFile.empty?)
|
187
|
+
# GcryptoJce::GConf.instance.glog.debug "File output for result"
|
188
|
+
# os = java.io.FileOutputStream.new(outFile)
|
189
|
+
#else
|
190
|
+
# GcryptoJce::GConf.instance.glog.debug "Buffer output for result"
|
191
|
+
# os = java.io.ByteArrayOutputStream.new
|
192
|
+
#end
|
193
|
+
|
194
|
+
if not spec.key_provider.nil?
|
195
|
+
prov = GcryptoJce::Provider.add_provider(spec.key_provider)
|
196
|
+
GcryptoJce::GConf.instance.glog.debug "Cipher spec : #{spec.to_java_cipher_spec}"
|
197
|
+
c = javax.crypto.Cipher.getInstance(spec.to_java_cipher_spec, prov)
|
198
|
+
else
|
199
|
+
GcryptoJce::GConf.instance.glog.debug "Cipher spec : #{spec.to_java_cipher_spec}"
|
200
|
+
c = javax.crypto.Cipher.getInstance(spec.to_java_cipher_spec)
|
201
|
+
end
|
202
|
+
|
203
|
+
algoParam = spec.algo_params_spec
|
204
|
+
if algoParam.nil?
|
205
|
+
GcryptoJce::GConf.instance.glog.debug "With nil algo params"
|
206
|
+
c.init(javax.crypto.Cipher::ENCRYPT_MODE, spec.key)
|
207
|
+
else
|
208
|
+
GcryptoJce::GConf.instance.glog.debug "With algo params : #{algoParam}"
|
209
|
+
c.init(javax.crypto.Cipher::ENCRYPT_MODE, spec.key, algoParam)
|
210
|
+
end
|
211
|
+
|
212
|
+
# special for GCM mode
|
213
|
+
if spec.mode == "GCM"
|
214
|
+
addAuthData = opts[:addAuthData]
|
215
|
+
if not addAuthData.nil?
|
216
|
+
case addAuthData
|
217
|
+
when Java::byte[]
|
218
|
+
c.updateAAD(addAuthData)
|
219
|
+
when String
|
220
|
+
c.updateAAD(addAuthData.to_java.getBytes)
|
221
|
+
when Java::char[]
|
222
|
+
cc.updateAAD(String.from_java_bytes(addAuthData).to_java.getBytes)
|
223
|
+
else
|
224
|
+
raise GcryptoJce::Error, "Addtional authenticated data given is not string, byte[] or char[]."
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
# end special data for GCM
|
229
|
+
|
230
|
+
begin
|
231
|
+
bufConf = opts[:int_buf] || { }
|
232
|
+
total = 0
|
233
|
+
IoUtils.read_chunk(is, bufConf) do |buf, from, len|
|
234
|
+
os.write(c.update(buf, from, len))
|
235
|
+
total += len
|
236
|
+
GcryptoJce::GConf.instance.glog.debug "Processed #{NumberHelper.number_to_human_size(total)}"
|
237
|
+
end
|
238
|
+
|
239
|
+
os.write(c.doFinal)
|
240
|
+
rescue Exception
|
241
|
+
ensure
|
242
|
+
begin
|
243
|
+
is.close
|
244
|
+
os.flush
|
245
|
+
os.close
|
246
|
+
rescue Exception
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
IoUtils.return_if_buffer(os)
|
251
|
+
#if outFile.nil? or outFile.empty?
|
252
|
+
# os.toByteArray
|
253
|
+
#end
|
254
|
+
|
255
|
+
end
|
256
|
+
#
|
257
|
+
# end encrypt
|
258
|
+
#
|
259
|
+
|
260
|
+
def decrypt(opts = { })
|
261
|
+
|
262
|
+
is = IoUtils.load_input(opts)
|
263
|
+
spec = opts[:crypto_context]
|
264
|
+
if spec.nil?
|
265
|
+
raise GcryptoJce::Error, "Crypto context is not given for secret key decryption"
|
266
|
+
end
|
267
|
+
|
268
|
+
#outFile = opts[:outFile]
|
269
|
+
#if not (outFile.nil? or outFile.empty?)
|
270
|
+
# os = java.io.FileOutputStream.new(outFile)
|
271
|
+
#else
|
272
|
+
# os = java.io.ByteArrayOutputStream.new
|
273
|
+
#end
|
274
|
+
os = IoUtils.prep_output(opts)
|
275
|
+
|
276
|
+
if not spec.key_provider.nil?
|
277
|
+
prov = GcryptoJce::Provider.add_provider(spec.key_provider)
|
278
|
+
GcryptoJce::GConf.instance.glog.debug "Cipher spec : #{spec.to_java_cipher_spec}"
|
279
|
+
c = javax.crypto.Cipher.getInstance(spec.to_java_cipher_spec, prov)
|
280
|
+
else
|
281
|
+
GcryptoJce::GConf.instance.glog.debug "Cipher spec : #{spec.to_java_cipher_spec}"
|
282
|
+
c = javax.crypto.Cipher.getInstance(spec.to_java_cipher_spec)
|
283
|
+
end
|
284
|
+
|
285
|
+
algoParam = spec.algo_params_spec
|
286
|
+
if algoParam.nil?
|
287
|
+
GcryptoJce::GConf.instance.glog.debug "With nil algo params"
|
288
|
+
c.init(javax.crypto.Cipher::DECRYPT_MODE, spec.key)
|
289
|
+
else
|
290
|
+
GcryptoJce::GConf.instance.glog.debug "With algo params : #{algoParam}"
|
291
|
+
c.init(javax.crypto.Cipher::DECRYPT_MODE, spec.key, algoParam)
|
292
|
+
end
|
293
|
+
|
294
|
+
begin
|
295
|
+
bufConf = opts[:int_buf] || { }
|
296
|
+
total = 0
|
297
|
+
IoUtils.read_chunk(is, bufConf) do |buf, from, len|
|
298
|
+
os.write(c.update(buf, from, len))
|
299
|
+
total += len
|
300
|
+
GcryptoJce::GConf.instance.glog.debug "Processed #{NumberHelper.number_to_human_size(total)}"
|
301
|
+
end
|
302
|
+
|
303
|
+
os.write(c.doFinal)
|
304
|
+
rescue Exception
|
305
|
+
ensure
|
306
|
+
begin
|
307
|
+
is.close
|
308
|
+
os.flush
|
309
|
+
os.close
|
310
|
+
rescue Exception
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
IoUtils.return_if_buffer(os)
|
315
|
+
#if outFile.nil? or outFile.empty?
|
316
|
+
# os.toByteArray
|
317
|
+
#end
|
318
|
+
|
319
|
+
end
|
320
|
+
# end decrypt()
|
321
|
+
|
322
|
+
# generate mac as signature using secret key
|
323
|
+
def sign(opts = { })
|
324
|
+
|
325
|
+
spec = opts[:crypto_context]
|
326
|
+
if spec.nil?
|
327
|
+
raise GcryptoJce::Error, "Crypto context is not given for secret key signing"
|
328
|
+
end
|
329
|
+
|
330
|
+
is = IoUtils.load_input(opts)
|
331
|
+
if not opts[:associatedData].nil?
|
332
|
+
dat = opts[:associatedData]
|
333
|
+
dat.merge!( { input_optional: true })
|
334
|
+
addIs = IoUtils.load_input(dat)
|
335
|
+
end
|
336
|
+
os = IoUtils.prep_output(opts)
|
337
|
+
|
338
|
+
hmacHash = opts[:hmacHash] || "SHA256"
|
339
|
+
hmacHashEng = "Hmac#{hmacHash}"
|
340
|
+
GcryptoJce::GConf.instance.glog.debug "Using '#{hmacHashEng}'"
|
341
|
+
|
342
|
+
if not spec.key_provider.nil?
|
343
|
+
prov = GcryptoJce::Provider.add_provider(spec.key_provider)
|
344
|
+
hmac = javax.crypto.Mac.getInstance(hmacHashEng, prov)
|
345
|
+
else
|
346
|
+
hmac = javax.crypto.Mac.getInstance(hmacHashEng)
|
347
|
+
end
|
348
|
+
|
349
|
+
hmac.init(spec.key)
|
350
|
+
|
351
|
+
begin
|
352
|
+
bufConf = opts[:int_buf] || { }
|
353
|
+
total = 0
|
354
|
+
IoUtils.read_chunk(is, bufConf) do |buf, from, len|
|
355
|
+
hmac.update(buf, from, len)
|
356
|
+
total += len
|
357
|
+
GcryptoJce::GConf.instance.glog.debug "Processed #{NumberHelper.number_to_human_size(total)}"
|
358
|
+
end
|
359
|
+
|
360
|
+
if not addIs.nil?
|
361
|
+
GcryptoJce::GConf.instance.glog.debug "Processing associated data"
|
362
|
+
IoUtils.read_chunk(addIs, bufConf) do |buf, from, len|
|
363
|
+
hmac.update(buf, from, len)
|
364
|
+
total += len
|
365
|
+
GcryptoJce::GConf.instance.glog.debug "Processed #{NumberHelper.number_to_human_size(total)}"
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
os.write(hmac.doFinal)
|
370
|
+
rescue Exception => ex
|
371
|
+
ensure
|
372
|
+
begin
|
373
|
+
is.close
|
374
|
+
os.flush
|
375
|
+
os.close
|
376
|
+
rescue Exception
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
IoUtils.return_if_buffer(os)
|
381
|
+
|
382
|
+
end
|
383
|
+
# end sign()
|
384
|
+
|
385
|
+
def verify(opts = { })
|
386
|
+
|
387
|
+
# mac value obtained by caller app
|
388
|
+
# must be in byte array value
|
389
|
+
mac = opts[:mac]
|
390
|
+
macBin = IoUtils.ensure_java_bytes(mac)
|
391
|
+
# calculate again based on input
|
392
|
+
refMac = sign(opts)
|
393
|
+
|
394
|
+
# compare both byte array
|
395
|
+
#
|
396
|
+
java.security.MessageDigest.isEqual(macBin, refMac)
|
397
|
+
end
|
398
|
+
# end verify()
|
399
|
+
|
400
|
+
end
|
401
|
+
#
|
402
|
+
# end SecretKeyCrypto
|
403
|
+
#
|
404
|
+
|
405
|
+
class SecretKeyCryptoEngine
|
406
|
+
extend SecretKeyCrypto
|
407
|
+
end
|
408
|
+
|
409
|
+
end
|
410
|
+
#
|
411
|
+
# end GcryptoJce
|
412
|
+
#
|