ccrypto-java 0.1.0

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