ccrypto-java 0.1.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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.java-version +1 -0
  3. data/.rspec +3 -0
  4. data/Gemfile +13 -0
  5. data/Gemfile.lock +94 -0
  6. data/README.md +150 -0
  7. data/Rakefile +10 -0
  8. data/bin/console +15 -0
  9. data/bin/setup +8 -0
  10. data/ccrypto-java.gemspec +44 -0
  11. data/jars/bcmail-jdk15on-165.jar +0 -0
  12. data/jars/bcpg-jdk15on-165.jar +0 -0
  13. data/jars/bcpkix-jdk15on-165.jar +0 -0
  14. data/jars/bcprov-ext-jdk15on-165.jar +0 -0
  15. data/jars/bcprov-jdk15on-165.jar +0 -0
  16. data/jars/bctls-jdk15on-165.jar +0 -0
  17. data/jars/shamir-0.6.1-p.jar +0 -0
  18. data/lib/ccrypto/java/data_conversion.rb +80 -0
  19. data/lib/ccrypto/java/engines/asn1_engine.rb +161 -0
  20. data/lib/ccrypto/java/engines/asn1_object.rb +12 -0
  21. data/lib/ccrypto/java/engines/cipher_engine.rb +255 -0
  22. data/lib/ccrypto/java/engines/compression_engine.rb +92 -0
  23. data/lib/ccrypto/java/engines/data_conversion_engine.rb +9 -0
  24. data/lib/ccrypto/java/engines/decompression_engine.rb +48 -0
  25. data/lib/ccrypto/java/engines/digest_engine.rb +208 -0
  26. data/lib/ccrypto/java/engines/ecc_engine.rb +263 -0
  27. data/lib/ccrypto/java/engines/hkdf_engine.rb +72 -0
  28. data/lib/ccrypto/java/engines/hmac_engine.rb +75 -0
  29. data/lib/ccrypto/java/engines/pbkdf2_engine.rb +87 -0
  30. data/lib/ccrypto/java/engines/pkcs7_engine.rb +558 -0
  31. data/lib/ccrypto/java/engines/rsa_engine.rb +572 -0
  32. data/lib/ccrypto/java/engines/scrypt_engine.rb +35 -0
  33. data/lib/ccrypto/java/engines/secret_key_engine.rb +44 -0
  34. data/lib/ccrypto/java/engines/secret_sharing_engine.rb +59 -0
  35. data/lib/ccrypto/java/engines/secure_random_engine.rb +76 -0
  36. data/lib/ccrypto/java/engines/x509_engine.rb +311 -0
  37. data/lib/ccrypto/java/ext/secret_key.rb +75 -0
  38. data/lib/ccrypto/java/ext/x509_cert.rb +48 -0
  39. data/lib/ccrypto/java/jce_provider.rb +52 -0
  40. data/lib/ccrypto/java/keybundle_store/pkcs12.rb +125 -0
  41. data/lib/ccrypto/java/utils/comparator.rb +20 -0
  42. data/lib/ccrypto/java/utils/memory_buffer.rb +77 -0
  43. data/lib/ccrypto/java/utils/native_helper.rb +19 -0
  44. data/lib/ccrypto/java/version.rb +7 -0
  45. data/lib/ccrypto/java.rb +30 -0
  46. data/lib/ccrypto/provider.rb +132 -0
  47. metadata +144 -0
@@ -0,0 +1,572 @@
1
+
2
+ require_relative '../data_conversion'
3
+ require_relative '../keybundle_store/pkcs12'
4
+ #require_relative '../keybundle_store/pem_store'
5
+
6
+ module Ccrypto
7
+ module Java
8
+
9
+ class RSAPublicKey < Ccrypto::RSAPublicKey
10
+
11
+ def to_bin
12
+ @native_pubKey.encoded
13
+ end
14
+
15
+ def self.to_key(bin)
16
+ pubKey = java.security.KeyFactory.getInstance("RSA", "BC").generatePublic(java.security.spec.X509EncodedKeySpec.new(bin))
17
+ RSAPublicKey.new(pubKey)
18
+ end
19
+
20
+ def method_missing(mtd, *args, &block)
21
+ @native_pubKey.send(mtd, *args, &block)
22
+ end
23
+
24
+ end # RSAPublicKey
25
+
26
+ class RSAKeyBundle
27
+ include Ccrypto::RSAKeyBundle
28
+ include TR::CondUtils
29
+
30
+ include PKCS12
31
+ #include PEMStore
32
+
33
+ include TeLogger::TeLogHelper
34
+
35
+ teLogger_tag :j_rsa_keybundle
36
+
37
+ def initialize(kp)
38
+ @nativeKeypair = kp
39
+ end
40
+
41
+ def public_key
42
+ if @pubKey.nil?
43
+ @pubKey = RSAPublicKey.new(@nativeKeypair.public)
44
+ end
45
+ @pubKey
46
+ end
47
+
48
+ def private_key
49
+ if @privKey.nil?
50
+ @privKey = RSAPrivateKey.new(@nativeKeypair.private)
51
+ end
52
+ @privKey
53
+ end
54
+
55
+ def to_storage(type, &block)
56
+
57
+ case type
58
+ when :p12, :pkcs12
59
+ to_pkcs12 do |key|
60
+ case key
61
+ when :keypair
62
+ @nativeKeypair
63
+ else
64
+ block.call(key) if block
65
+ end
66
+ end
67
+
68
+ when :jks
69
+ to_pkcs12 do |key|
70
+ case key
71
+ when :storeType
72
+ "JKS"
73
+ when :keypair
74
+ @nativeKeypair
75
+ else
76
+ block.call(key) if block
77
+ end
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ def self.from_storage(bin, &block)
84
+
85
+ if is_pem?(bin)
86
+ else
87
+ from_pkcs12(bin, &block)
88
+ end
89
+
90
+ end
91
+
92
+ def self.is_pem?(bin)
93
+ begin
94
+ (bin =~ /BEGIN/) != nil
95
+ rescue ArgumentError => ex
96
+ false
97
+ end
98
+ end
99
+
100
+ def equal?(kp)
101
+ case kp
102
+ when Ccrypto::RSAKeyBundle
103
+ @nativeKeypair.encoded == kp.private.encoded
104
+ else
105
+ false
106
+ end
107
+ end
108
+
109
+ def method_missing(mtd, *args, &block)
110
+ teLogger.debug "Sending to native #{mtd}"
111
+ @nativeKeypair.send(mtd, *args, &block)
112
+ end
113
+
114
+ def respond_to_missing?(mtd, incPriv = false)
115
+ teLogger.debug "Respond to missing #{mtd}"
116
+ @nativeKeypair.respond_to?(mtd)
117
+ end
118
+
119
+ end # RSAKeyBundle
120
+
121
+ class RSAEngine
122
+ include TR::CondUtils
123
+ include DataConversion
124
+
125
+ include TeLogger::TeLogHelper
126
+
127
+ teLogger_tag :j_rsa
128
+
129
+ def initialize(*args, &block)
130
+ @config = args.first
131
+ raise KeypairEngineException, "1st parameter must be a #{Ccrypto::KeypairConfig.class} object" if not @config.is_a?(Ccrypto::KeypairConfig)
132
+
133
+ end
134
+
135
+ def generate_keypair(&block)
136
+ prov = Ccrypto::Java::JCEProvider::DEFProv
137
+ if block
138
+ prov = block.call(:jce_provider)
139
+ end
140
+ prov = Ccrypto::Java::JCEProvider::DEFProv if is_empty?(prov)
141
+
142
+ kpg = java.security.KeyPairGenerator.getInstance("RSA", prov)
143
+ kpg.java_send :initialize, [::Java::int], @config.keysize
144
+ kp = kpg.generate_key_pair
145
+
146
+ RSAKeyBundle.new(kp)
147
+ end
148
+
149
+ def sign(val, &block)
150
+ if block
151
+ pss = block.call(:pss_mode)
152
+ pss = false if is_empty?(pss) or not is_bool?(pss)
153
+
154
+ if pss
155
+ sign_pss(val, &block)
156
+ else
157
+ sign_typical(val, &block)
158
+ end
159
+ else
160
+ sign_typical(val,&block)
161
+ end
162
+ end
163
+
164
+ def self.verify(pubKey, val, ssign, &block)
165
+ if block
166
+ pss = block.call(:pss_mode)
167
+ pss = false if is_empty?(pss) or not is_bool?(pss)
168
+
169
+ if pss
170
+ verify_pss(pubKey, val, ssign, &block)
171
+ else
172
+ verify_typical()
173
+ end
174
+
175
+ else
176
+ verify_typical(pubKey, val, ssign, &block)
177
+ end
178
+ end
179
+
180
+ def self.encrypt(pubKey, val, &block)
181
+
182
+ raise KeypairEngineException, "Public key is required" if is_empty?(pubKey)
183
+
184
+ prov = nil
185
+ if block
186
+ prov = block.call(:jce_provider)
187
+ padding = block.call(:padding)
188
+ digAlgo = block.call(:oaep_digest)
189
+ mode = block.call(:mode)
190
+ end
191
+ padding = :oaep if is_empty?(padding)
192
+ digAlgo = :sha256 if is_empty?(digAlgo)
193
+ mode = :none if is_empty?(mode)
194
+
195
+ case padding
196
+ when :pkcs1
197
+ teLogger.owarn "RSA with PKCS1Padding mode is vulnerable. :oeap mode recommended"
198
+ transform = "RSA/#{mode.to_s.upcase}/PKCS1Padding"
199
+
200
+ when :oaep
201
+ transform = "RSA/None/OAEPWith#{digAlgo.to_s.upcase}AndMGF1Padding"
202
+
203
+ # standardize BC vs Oracle defaults
204
+ # https://stackoverflow.com/a/50299291/3625825
205
+ case digAlgo
206
+ when :sha1
207
+ oaepSpec = javax.crypto.spec.OAEPParameterSpec.new(digAlgo.to_s.upcase, "MGF1", java.security.spec.MGF1ParameterSpec::SHA1, javax.crypto.spec.PSource::PSpecified::DEFAULT)
208
+ when :sha224
209
+ oaepSpec = javax.crypto.spec.OAEPParameterSpec.new(digAlgo.to_s.upcase, "MGF1", java.security.spec.MGF1ParameterSpec::SHA224, javax.crypto.spec.PSource::PSpecified::DEFAULT)
210
+ when :sha256
211
+ oaepSpec = javax.crypto.spec.OAEPParameterSpec.new(digAlgo.to_s.upcase, "MGF1", java.security.spec.MGF1ParameterSpec::SHA256, javax.crypto.spec.PSource::PSpecified::DEFAULT)
212
+ when :sha384
213
+ oaepSpec = javax.crypto.spec.OAEPParameterSpec.new(digAlgo.to_s.upcase, "MGF1", java.security.spec.MGF1ParameterSpec::SHA384, javax.crypto.spec.PSource::PSpecified::DEFAULT)
214
+ when :sha512
215
+ oaepSpec = javax.crypto.spec.OAEPParameterSpec.new(digAlgo.to_s.upcase, "MGF1", java.security.spec.MGF1ParameterSpec::SHA512, javax.crypto.spec.PSource::PSpecified::DEFAULT)
216
+ else
217
+ raise KeypairEngineException, "Unknown #{digAlgo} digest for OAEP mode"
218
+ end
219
+
220
+ when :no_padding
221
+ teLogger.owarn "RSA with NoPadding mode is vulnerable. :oeap mode recommended"
222
+ transform = "RSA/#{mode.to_s.upcase}/NoPadding"
223
+
224
+ else
225
+ raise KeypairEngineException, "Padding requires either :pkcs1, :no_padding or :oaep. Default is :oaep"
226
+ end
227
+
228
+ begin
229
+
230
+ if prov.nil?
231
+ teLogger.debug "Encrypt transformation #{transform} with nil provider"
232
+ cipher = javax.crypto.Cipher.getInstance(transform)
233
+ else
234
+ teLogger.debug "Encrypt transformation #{transform} with provider #{prov.is_a?(String) ? prov : prov.name}"
235
+ cipher = javax.crypto.Cipher.getInstance(transform, prov)
236
+ end
237
+
238
+
239
+ if oaepSpec.nil?
240
+ teLogger.debug "Init cipher with default parameter spec"
241
+ cipher.init(javax.crypto.Cipher::ENCRYPT_MODE, pubKey.native_pubKey)
242
+ else
243
+ teLogger.debug "Init cipher with parameter spec #{oaepSpec}"
244
+ cipher.init(javax.crypto.Cipher::ENCRYPT_MODE, pubKey.native_pubKey, oaepSpec)
245
+ end
246
+
247
+ if block
248
+ # this is share with caller to ensure input data should not be longer then this size
249
+ block.call(:max_data_size, cipher.getBlockSize)
250
+ end
251
+
252
+ out = java.io.ByteArrayOutputStream.new
253
+ case val
254
+ when java.io.InputStream
255
+ buf = ::Java::byte[102400].new
256
+ while((read = val.read(buf, 0, buf.length)) != nil)
257
+ out.write(cipher.update(buf, 0, read))
258
+ end
259
+ else
260
+ inDat = to_java_bytes(val)
261
+ teLogger.debug "Encrypting #{inDat.length} bytes"
262
+ ed = cipher.update(inDat)
263
+ out.write(ed) if not_empty?(ed)
264
+ end
265
+
266
+ last = cipher.doFinal
267
+ out.write(last) if not_empty?(last)
268
+ #out.write(cipher.doFinal)
269
+
270
+ out.toByteArray
271
+
272
+ rescue Exception => ex
273
+ raise KeypairEngineException, ex
274
+ end
275
+
276
+ end
277
+
278
+ def decrypt(enc, &block)
279
+
280
+ raise KeypairEngineException, "Private key is required" if not @config.has_private_key?
281
+ raise KeypairEngineException, "RSA private key is required. Given #{@config.private_key}" if not @config.private_key.is_a?(RSAPrivateKey)
282
+
283
+ prov = nil
284
+ if block
285
+ prov = block.call(:jce_provider)
286
+ padding = block.call(:padding)
287
+ digAlgo = block.call(:oaep_digest)
288
+ mode = block.call(:mode)
289
+ end
290
+ padding = :oaep if is_empty?(padding)
291
+ digAlgo = :sha256 if is_empty?(digAlgo)
292
+ mode = :none if is_empty?(mode)
293
+
294
+ case padding
295
+ when :pkcs1
296
+ transform = "RSA/#{mode.to_s.upcase}/PKCS1Padding"
297
+ when :oaep
298
+ transform = "RSA/None/OAEPWith#{digAlgo.to_s.upcase}AndMGF1Padding"
299
+ when :no_padding
300
+ transform = "RSA/#{mode.to_s.upcase}/NoPadding"
301
+ else
302
+ raise KeypairEngineException, "Padding requires either :pkcs1, :no_padding or :oaep. Default is :oaep"
303
+ end
304
+
305
+ begin
306
+
307
+ if prov.nil?
308
+ cipher = javax.crypto.Cipher.getInstance(transform)
309
+ else
310
+ cipher = javax.crypto.Cipher.getInstance(transform, prov)
311
+ end
312
+
313
+ cipher.init(javax.crypto.Cipher::DECRYPT_MODE, @config.private_key.native_privKey)
314
+
315
+ out = java.io.ByteArrayOutputStream.new
316
+ case enc
317
+ when java.io.InputStream
318
+ buf = ::Java::byte[102400].new
319
+ while((read = enc.read(buf, 0, buf.length)) != nil)
320
+ out.write(cipher.update(buf,0, read))
321
+ end
322
+ else
323
+ inDat = to_java_bytes(enc)
324
+ teLogger.debug "Decrypting #{inDat.length} bytes"
325
+ pd = cipher.update(inDat)
326
+ out.write(pd) if not_empty?(pd)
327
+ end
328
+
329
+ last = cipher.doFinal
330
+ out.write(last) if not_empty?(last)
331
+
332
+ out.toByteArray
333
+
334
+ rescue Exception => ex
335
+ raise KeypairEngineException, ex
336
+ end
337
+
338
+ end
339
+
340
+
341
+ ##############################################
342
+ ## Private section
343
+ ###
344
+ private
345
+ def sign_typical(val, &block)
346
+
347
+ prov = block.call(:jce_provider) if block
348
+
349
+ signHash = block.call(:sign_hash) if block
350
+ signHash = :sha256 if is_empty?(signHash)
351
+
352
+ signAlgo = "#{signHash.to_s.upcase}WithRSA"
353
+
354
+ begin
355
+
356
+ if is_empty?(prov)
357
+ teLogger.debug "Provider is nil"
358
+ sign = java.security.Signature.getInstance(signAlgo)
359
+ else
360
+ teLogger.debug "Provider is '#{prov.name}'"
361
+ sign = java.security.Signature.getInstance(signAlgo, prov)
362
+ end
363
+
364
+ teLogger.debug "Private key is #{@config.private_key.native_privKey}"
365
+ sign.initSign(@config.private_key.native_privKey)
366
+
367
+ algoSpec = block.call(:signAlgoSpec) if block
368
+
369
+ if not_empty?(algoSpec) and algoSpec.is_a?(java.security.spec.AlgorithmParameterSpec)
370
+ sign.setParameter(algoSpec)
371
+ teLogger.debug "Sign Algo Parameter : '#{algoSpec}'"
372
+ end
373
+
374
+ case val
375
+ when java.io.InputStream
376
+ buf = ::Java::byte[102400].new
377
+ while((read = val.read(buf, 0, buf.length)) != nil)
378
+ sign.update(buf, 0, read)
379
+ end
380
+ else
381
+ sign.update(to_java_bytes(val))
382
+ end
383
+
384
+ sign.sign
385
+
386
+ rescue Exception => ex
387
+ raise KeypairEngineException, ex
388
+ end
389
+
390
+ end
391
+
392
+ def sign_pss(val, &block)
393
+
394
+ raise KeypairEngineException, "Private key is required" if not @config.has_private_key?
395
+ raise KeypairEngineException, "RSA private key is required." if not @config.private_key.is_a?(RSAPrivateKey)
396
+
397
+ privKey = @config.private_key
398
+
399
+ if block
400
+ signHash = block.call(:sign_hash)
401
+ mgf1Hash = block.call(:mgf1_hash)
402
+ saltLen = block.call(:salt_length)
403
+ prov = block.call(:jce_provider)
404
+ trailer = block.call(:trailer_field)
405
+ end
406
+
407
+ mgf1Hash = :sha256 if is_empty?(mgf1Hash)
408
+ # Comment under post https://stackoverflow.com/a/48854106/3625825
409
+ # indicated 20 is the value when use with OpenSSL
410
+ #saltLen = 20 if is_empty?(saltLen)
411
+ saltLen = 32 if is_empty?(saltLen)
412
+ signHash = "sha256" if is_empty?(signHash)
413
+ # there is post on StackOverflow indicated to verify with OpenSSL
414
+ # trailer = 0xBC
415
+ #trailer = 0xBC if is_empty?(trailer)
416
+ trailer = 1 if is_empty?(trailer)
417
+
418
+ case mgf1Hash.to_sym
419
+ when :sha1
420
+ mgf1Spec = java.security.spec.MGF1ParameterSpec::SHA1
421
+ when :sha224
422
+ mgf1Spec = java.security.spec.MGF1ParameterSpec::SHA224
423
+ when :sha256
424
+ mgf1Spec = java.security.spec.MGF1ParameterSpec::SHA256
425
+ when :sha384
426
+ mgf1Spec = java.security.spec.MGF1ParameterSpec::SHA384
427
+ when :sha512
428
+ mgf1Spec = java.security.spec.MGF1ParameterSpec::SHA512
429
+ when :sha512_224
430
+ mgf1Spec = java.security.spec.MGF1ParameterSpec::SHA512_224
431
+ when :sha512_256
432
+ mgf1Spec = java.security.spec.MGF1ParameterSpec::SHA512_256
433
+ else
434
+ raise KeypairEngineException, "Not supported mgf1Hash value #{mgf1Hash}. Supported value including: :sha1, :sha224, :sha256, :sha384, :sha512, :sha512_224 and :sha512_256"
435
+ end
436
+
437
+ if prov.nil?
438
+ sign = java.security.Signature.getInstance("#{signHash.to_s.strip.upcase}WithRSA/PSS")
439
+ else
440
+ sign = java.security.Signature.getInstance("#{signHash.to_s.strip.upcase}WithRSA/PSS", prov)
441
+ end
442
+
443
+ sign.setParameter(java.security.spec.PSSParameterSpec.new(signHash.to_s.strip.upcase,"MGF1", mgf1Spec, saltLen, trailer))
444
+
445
+ sign.initSign(privKey.native_privKey)
446
+
447
+ case val
448
+ when java.io.InputStream
449
+ buf = ::Java::byte[102400].new
450
+ while((read = val.read(buf, 0, buf.length)) != nil)
451
+ sign.update(buf, 0, read)
452
+ end
453
+ else
454
+ sign.update(to_java_bytes(val))
455
+ end
456
+
457
+ sign.sign
458
+
459
+ end
460
+
461
+ def self.verify_typical(pubKey, val, ssign, &block)
462
+
463
+ #raise KeypairEngineException, "block is required" if not block
464
+
465
+ prov = block.call(:jce_provider) if block
466
+
467
+ signAlgo = block.call(:signAlgo) if block
468
+ signAlgo = "SHA256WithRSA" if is_empty?(signAlgo)
469
+
470
+ case pubKey.native_pubKey
471
+ when java.security.cert.Certificate, java.security.PublicKey
472
+
473
+ if is_empty?(prov)
474
+ teLogger.debug "Provider is nil"
475
+ sign = java.security.Signature.getInstance(signAlgo)
476
+ else
477
+ teLogger.debug "Provider is '#{prov.name}'"
478
+ sign = java.security.Signature.getInstance(signAlgo, prov)
479
+ end
480
+
481
+ sign.initVerify(pubKey.native_pubKey)
482
+
483
+ else
484
+ raise KeypairEngineException, "Unknown pubKey type #{pubKey}"
485
+ end
486
+
487
+ case val
488
+ when java.io.InputStream
489
+ buf = ::Java::byte[102400].new
490
+ while((read = val.read(buf, 0, buf.length)) != nil)
491
+ sign.update(buf, 0, read)
492
+ end
493
+ else
494
+ sign.update(to_java_bytes(val))
495
+ end
496
+
497
+ sign.verify(to_java_bytes(ssign))
498
+
499
+ end
500
+
501
+ def self.verify_pss(pubKey, val, ssign, &block)
502
+
503
+ raise KeypairEngineException, "Public key is required" if pubKey.nil?
504
+ raise KeypairEngineException, "RSA public key is required. Given #{pubKey}" if not pubKey.is_a?(RSAPublicKey)
505
+
506
+ if block
507
+ signHash = block.call(:sign_hash)
508
+ mgf1Hash = block.call(:mgf1_hash)
509
+ saltLen = block.call(:salt_length)
510
+ prov = block.call(:jce_provider)
511
+ trailer = block.call(:trailer_field)
512
+ end
513
+
514
+ mgf1Hash = :sha256 if is_empty?(mgf1Hash)
515
+ # Comment under post https://stackoverflow.com/a/48854106/3625825
516
+ # indicated 20 is the value when use with OpenSSL
517
+ #saltLen = 20 if is_empty?(saltLen)
518
+ saltLen = 32 if is_empty?(saltLen)
519
+ signHash = "sha256" if is_empty?(signHash)
520
+ # there is post on StackOverflow indicated to verify with OpenSSL
521
+ # trailer = 0xBC
522
+ #trailer = 0xBC if is_empty?(trailer)
523
+ trailer = 1 if is_empty?(trailer)
524
+
525
+ case mgf1Hash.to_sym
526
+ when :sha1
527
+ mgf1Spec = java.security.spec.MGF1ParameterSpec::SHA1
528
+ when :sha224
529
+ mgf1Spec = java.security.spec.MGF1ParameterSpec::SHA224
530
+ when :sha256
531
+ mgf1Spec = java.security.spec.MGF1ParameterSpec::SHA256
532
+ when :sha384
533
+ mgf1Spec = java.security.spec.MGF1ParameterSpec::SHA384
534
+ when :sha512
535
+ mgf1Spec = java.security.spec.MGF1ParameterSpec::SHA512
536
+ when :sha512_224
537
+ mgf1Spec = java.security.spec.MGF1ParameterSpec::SHA512_224
538
+ when :sha512_256
539
+ mgf1Spec = java.security.spec.MGF1ParameterSpec::SHA512_256
540
+ else
541
+ raise KeypairEngineException, "Not supported mgf1Hash value #{mgf1Hash}. Supported value including: :sha1, :sha224, :sha256, :sha384, :sha512, :sha512_224 and :sha512_256"
542
+ end
543
+
544
+ if prov.nil?
545
+ sign = java.security.Signature.getInstance("#{signHash.to_s.strip.upcase}WithRSA/PSS")
546
+ else
547
+ sign = java.security.Signature.getInstance("#{signHash.to_s.strip.upcase}WithRSA/PSS", prov)
548
+ end
549
+
550
+ sign.setParameter(java.security.spec.PSSParameterSpec.new(signHash.to_s.strip.upcase,"MGF1", mgf1Spec, saltLen, trailer))
551
+
552
+ sign.initVerify(pubKey.native_pubKey)
553
+
554
+ case val
555
+ when java.io.InputStream
556
+ buf = ::Java::byte[102400].new
557
+ while((read = val.read(buf, 0, buf.length)) != nil)
558
+ sign.update(buf, 0, read)
559
+ end
560
+ else
561
+ sign.update(to_java_bytes(val))
562
+ end
563
+
564
+ sign.verify(ssign)
565
+
566
+ end
567
+
568
+
569
+ end
570
+
571
+ end
572
+ end
@@ -0,0 +1,35 @@
1
+
2
+ require_relative '../data_conversion'
3
+
4
+ module Ccrypto
5
+ module Java
6
+ class ScryptEngine
7
+ include DataConversion
8
+ include TR::CondUtils
9
+
10
+ def initialize(conf, &block)
11
+ raise KDFEngineException, "KDF config is expected" if not conf.is_a?(Ccrypto::KDFConfig)
12
+ raise KDFEngineException, "Output bit length (outBitLength) value is not given or not a positive value (#{conf.outBitLength})" if is_empty?(conf.outBitLength) or conf.outBitLength <= 0
13
+ @config = conf
14
+
15
+ if is_empty?(@config.salt)
16
+ @config.salt = Java::byte[16].new
17
+ java.security.SecureRandom.getInstance("NativePRNG").random_bytes(@config.salt)
18
+ end
19
+ end
20
+
21
+ def derive(input, output = :binary)
22
+ res = org.bouncycastle.crypto.generators.SCrypt.generate(to_java_bytes(input), to_java_bytes(@config.salt),@config.cost, @config.blockSize, @config.parallel, @config.outBitLength/8)
23
+ case output
24
+ when :hex
25
+ to_hex(res)
26
+ when :b64
27
+ to_b64(res)
28
+ else
29
+ res
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,44 @@
1
+
2
+
3
+ module Ccrypto
4
+ module Java
5
+ class SecretKeyEngine
6
+
7
+ include TeLogger::TeLogHelper
8
+ teLogger_tag :j_secretkey
9
+
10
+ def self.generate(*args, &block)
11
+ config = args.first
12
+
13
+ raise SecretKeyEngineException, "KeyConfig is expected" if not config.is_a?(Ccrypto::KeyConfig)
14
+
15
+ if block
16
+ kgProv = block.call(:keygen_jceProvider)
17
+ ranProv = block.call(:random_jceProvider)
18
+ end
19
+
20
+ if kgProv.nil?
21
+ teLogger.debug "KeyGen using algo #{config.algo.to_s} with null provider"
22
+ keyGen = javax.crypto.KeyGenerator.getInstance(config.algo.to_s)
23
+ else
24
+ teLogger.debug "KeyGen using algo #{config.algo.to_s} with provider #{kgProv.is_a?(String) ? kgProv : kgProv.name}"
25
+ keyGen = javax.crypto.KeyGenerator.getInstance(config.algo.to_s, kgProv)
26
+ end
27
+
28
+ if ranProv.nil?
29
+ teLogger.debug "Init KeyGen with keysize #{config.keysize.to_i}"
30
+ keyGen.init(config.keysize.to_i)
31
+ else
32
+ teLogger.debug "Init KeyGen with keysize #{config.keysize.to_i} with provider #{ranProv.is_a?(String) ? ranProv : ranProv.name}"
33
+ keyGen.init(config.keysize.to_i, ranProv)
34
+ end
35
+
36
+ key = keyGen.generateKey
37
+ teLogger.debug "Secret key #{config} generated"
38
+ Ccrypto::SecretKey.new(config.algo, key)
39
+
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,59 @@
1
+
2
+ require_relative '../data_conversion'
3
+
4
+ module Ccrypto
5
+ module Java
6
+ class SecretSharingEngine
7
+ include DataConversion
8
+
9
+ def initialize(*args, &block)
10
+ @config = args.first
11
+ raise SecretSharingException, "SecretSharingConfig is required" if not @config.is_a?(Ccrypto::SecretSharingConfig)
12
+ raise SecretSharingException, "split_into value must be more than 1" if not @config.split_into.to_i > 1
13
+ raise SecretSharingException, "required_parts value (#{@config.required_parts}) must be less than or equal split_into value (#{@config.split_into})." if not @config.required_parts.to_i < @config.split_into.to_i
14
+ end
15
+
16
+ def split(secVal)
17
+ eng = com.codahale.shamir.Scheme.new(java.security.SecureRandom.new, @config.split_into.to_i, @config.required_parts.to_i)
18
+ case secVal
19
+ when Ccrypto::SecretKey
20
+ val = secVal.to_bin
21
+ when ::Java::byte[]
22
+ val = secVal
23
+ when String
24
+ val = to_java_bytes(secVal)
25
+ else
26
+ raise SecretSharingException, "Unknown secret value to split (#{secVal.class})"
27
+ end
28
+ eng.split(val)
29
+ end
30
+
31
+ def self.combine(req, parts)
32
+ jhash = java.util.HashMap.new
33
+ case parts
34
+ when Hash
35
+ # need to lock the key to java.lang.Integer
36
+ # as the automated conversion of JRuby will turn the key into
37
+ # java.lang.Long instead of java.lang.Integer
38
+ # Using Map with parameterize auto conversion will failed inside the Java
39
+ parts.each do |k,v|
40
+ if not v.is_a?(::Java::byte[])
41
+ vv = to_java_bytes(v)
42
+ else
43
+ vv = v
44
+ end
45
+
46
+ jhash.put(java.lang.Integer.new(k),vv)
47
+ end
48
+ when java.util.Map
49
+ jhash = parts
50
+ else
51
+ raise SecretSharingException, "Unsupported parts of #{parts.class}"
52
+ end
53
+
54
+ com.codahale.shamir.Scheme.join(jhash)
55
+ end
56
+
57
+ end
58
+ end
59
+ end