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,263 @@
1
+
2
+ require_relative '../data_conversion'
3
+
4
+ require_relative '../keybundle_store/pkcs12'
5
+
6
+ module Ccrypto
7
+ module Java
8
+
9
+ class ECCPublicKey < Ccrypto::ECCPublicKey
10
+ include DataConversion
11
+
12
+ def to_bin
13
+ @native_pubKey.encoded
14
+ end
15
+
16
+ def encoded
17
+ to_bin
18
+ end
19
+
20
+ def self.to_key(bin)
21
+ bin = to_java_bytes(bin) if not bin.is_a?(::Java::byte[])
22
+ pubKey = java.security.KeyFactory.getInstance("ECDSA", "BC").generatePublic(java.security.spec.X509EncodedKeySpec.new(bin))
23
+ ECCPublicKey.new(pubKey)
24
+ end
25
+
26
+ end
27
+
28
+ class ECCKeyBundle
29
+ include Ccrypto::ECCKeyBundle
30
+ include TR::CondUtils
31
+ include DataConversion
32
+
33
+ include PKCS12
34
+
35
+ include TeLogger::TeLogHelper
36
+
37
+ teLogger_tag :j_ecc_keybundle
38
+
39
+ def initialize(kp)
40
+ @keypair = kp
41
+ end
42
+
43
+ def native_keypair
44
+ @keypair
45
+ end
46
+
47
+ def public_key
48
+ if @pubKey.nil?
49
+ @pubKey = ECCPublicKey.new(@keypair.public)
50
+ end
51
+ @pubKey
52
+ end
53
+
54
+ def private_key
55
+ ECCPrivateKey.new(@keypair.private)
56
+ end
57
+
58
+ def derive_dh_shared_secret(pubKey, &block)
59
+
60
+ JCEProvider.instance.add_bc_provider
61
+
62
+ ka = javax.crypto.KeyAgreement.getInstance("ECDH", JCEProvider::DEFProv)
63
+ ka.init(@keypair.private)
64
+
65
+ case pubKey
66
+ when ECCPublicKey
67
+ pub = pubKey.native_pubKey
68
+ when java.security.PublicKey
69
+ pub = pubKey
70
+ else
71
+ raise KeypairEngineException, "Unsupported public key type #{pubKey.class}"
72
+ end
73
+ ka.doPhase(pub, true)
74
+ #ka.doPhase(pubKey.native_pubKey, true)
75
+ if block
76
+ keyType = block.call(:keytype)
77
+ else
78
+ keyType = "AES"
79
+ end
80
+ keyType = "AES" if is_empty?(keyType)
81
+ teLogger.debug "Generate secret key type #{keyType}"
82
+ ka.generateSecret(keyType).encoded
83
+ end
84
+
85
+ def is_public_key_equal?(pubKey)
86
+ @keypair.public.encoded == pubKey.encoded
87
+ end
88
+
89
+ def to_storage(type, &block)
90
+
91
+ case type
92
+ when :p12, :pkcs12
93
+ to_pkcs12 do |key|
94
+ case key
95
+ when :keypair
96
+ @keypair
97
+ else
98
+ block.call(key) if block
99
+ end
100
+ end
101
+
102
+ when :jks
103
+ to_pkcs12 do |key|
104
+ case key
105
+ when :storeType
106
+ "JKS"
107
+ when :keypair
108
+ @keypair
109
+ else
110
+ block.call(key) if key
111
+ end
112
+ end
113
+
114
+ when :pem
115
+
116
+ header = "-----BEGIN EC PRIVATE KEY-----\n"
117
+ footer = "\n-----END EC PRIVATE KEY-----"
118
+
119
+ out = StringIO.new
120
+ out.write header
121
+ out.write to_b64_mime(@keypair.private.encoded)
122
+ out.write footer
123
+
124
+ out.string
125
+
126
+ else
127
+ raise KeypairEngineException, "Unknown storage type #{type}"
128
+ end
129
+
130
+ end
131
+
132
+ def self.from_storage(bin, &block)
133
+
134
+ if is_pem?(bin)
135
+ else
136
+ from_pkcs12(bin, &block)
137
+ end
138
+
139
+ end
140
+
141
+ def self.is_pem?(bin)
142
+ begin
143
+ (bin =~ /BEGIN/) != nil
144
+ rescue ArgumentError => ex
145
+ false
146
+ end
147
+ end
148
+
149
+ def equal?(kp)
150
+ case kp
151
+ when Ccrypto::ECCKeyBundle
152
+ @keypair.encoded == kp.private.encoded
153
+ else
154
+ false
155
+ end
156
+ end
157
+
158
+ def method_missing(mtd, *args, &block)
159
+ teLogger.debug "Sending to native #{mtd}"
160
+ @keypair.send(mtd, *args, &block)
161
+ end
162
+
163
+ def respond_to_missing?(mtd, incPriv = false)
164
+ teLogger.debug "Respond to missing #{mtd}"
165
+ @keypair.respond_to?(mtd)
166
+ end
167
+
168
+ end
169
+
170
+ class ECCEngine
171
+ include TR::CondUtils
172
+ include DataConversion
173
+
174
+ include TeLogger::TeLogHelper
175
+ teLogger_tag :j_ecc
176
+
177
+ def self.supported_curves
178
+ if @curves.nil?
179
+ @curves = org.bouncycastle.asn1.x9.ECNamedCurveTable.getNames.sort.to_a.map { |c| Ccrypto::ECCConfig.new(c) }
180
+ end
181
+ @curves
182
+ end
183
+
184
+ def initialize(*args,&block)
185
+ @config = args.first
186
+ raise KeypairEngineException, "1st parameter must be a #{Ccrypto::KeypairConfig.class} object" if not @config.is_a?(Ccrypto::KeypairConfig)
187
+ end
188
+
189
+ def generate_keypair(&block)
190
+
191
+ algoName = "ECDSA"
192
+ prov = Ccrypto::Java::JCEProvider::BCProv
193
+ randomEngine = java.security.SecureRandom.new
194
+ if block
195
+ # it is the responsibility of caller program to add the
196
+ # provider into the provider list.
197
+ # Here provider string shall be used
198
+ uprov = block.call(:jce_provider)
199
+ prov = uprov if not is_empty?(uprov)
200
+
201
+ uAlgo = block.call(:jce_algo_name)
202
+ algoName = uAlgo if not is_empty?(uAlgo)
203
+
204
+ uRandEng = block.call(:random_engine)
205
+ randomEngine = uRandEng if not uRandEng.nil?
206
+ end
207
+
208
+ kpg = java.security.KeyPairGenerator.getInstance(algoName, prov)
209
+ #kpg.java_send :initialize, [java.security.spec.AlgorithmParameterSpec, java.security.SecureRandom], java.security.spec.ECGenParameterSpec.new(curve), java.security.SecureRandom.new
210
+ kpg.java_send :initialize, [java.security.spec.AlgorithmParameterSpec, randomEngine.class], java.security.spec.ECGenParameterSpec.new(@config.curve), randomEngine
211
+ kp = kpg.generate_key_pair
212
+
213
+ kb = ECCKeyBundle.new(kp)
214
+ kb
215
+
216
+ end
217
+
218
+ def regenerate_keypair(pubKey, privKey, &block)
219
+ kp = java.security.KeyPair.new(pubKey, privKey)
220
+ ECCKeyBundle.new(kp)
221
+ end
222
+
223
+ def sign(val, &block)
224
+ raise KeypairEngineException, "Keypair is required" if @config.keypair.nil?
225
+ raise KeypairEngineException, "ECC keypair is required. Given #{@config.keypair}" if not @config.keypair.is_a?(ECCKeyBundle)
226
+ kp = @config.keypair
227
+
228
+ sign = java.security.Signature.getInstance("SHA256WithECDSA")
229
+ sign.initSign(kp.private_key)
230
+ teLogger.debug "Signing data : #{val}"
231
+ case val
232
+ when java.io.InputStream
233
+ buf = Java::byte[102400].new
234
+ while((read = val.read(buf, 0, buf.length)) != nil)
235
+ sign.update(buf,0,read)
236
+ end
237
+ else
238
+ sign.update(to_java_bytes(val))
239
+ end
240
+
241
+ sign.sign
242
+ end
243
+
244
+ def self.verify(pubKey, val, sign)
245
+ ver = java.security.Signature.getInstance("SHA256WithECDSA")
246
+ ver.initVerify(pubKey)
247
+ teLogger.debug "Verifing data : #{val}"
248
+ case val
249
+ when java.io.InputStream
250
+ buf = Java::byte[102400].new
251
+ while((read = val.read(buf, 0 ,buf.length)) != nil)
252
+ ver.update(buf,0, read)
253
+ end
254
+ else
255
+ ver.update(to_java_bytes(val))
256
+ end
257
+
258
+ ver.verify(to_java_bytes(sign))
259
+ end
260
+
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,72 @@
1
+
2
+ require_relative '../data_conversion'
3
+
4
+ module Ccrypto
5
+ module Java
6
+ class HKDFEngine
7
+ include DataConversion
8
+ include TR::CondUtils
9
+
10
+ def initialize(*args, &block)
11
+ @config = args.first
12
+
13
+ raise KDFEngineException, "KDF config is expected. Given #{@config}" if not @config.is_a?(Ccrypto::KDFConfig)
14
+ raise KDFEngineException, "Output bit length (outBitLength) value is not given or not a positive value (#{@config.outBitLength})" if is_empty?(@config.outBitLength) or @config.outBitLength <= 0
15
+
16
+
17
+ @config.salt = SecureRandom.random_bytes(16) if is_empty?(@config.salt)
18
+ end
19
+
20
+ def derive(input, output = :binary)
21
+ begin
22
+
23
+ case @config.digest
24
+ when :sha1
25
+ dig = org.bouncycastle.crypto.digests.SHA1Digest.new
26
+ when :sha224
27
+ dig = org.bouncycastle.crypto.digests.SHA224Digest.new
28
+ when :sha256
29
+ dig = org.bouncycastle.crypto.digests.SHA256Digest.new
30
+ when :sha384
31
+ dig = org.bouncycastle.crypto.digests.SHA384Digest.new
32
+ when :sha512
33
+ dig = org.bouncycastle.crypto.digests.SHA512Digest.new
34
+ when :sha3_224
35
+ dig = org.bouncycastle.crypto.digests.SHA3Digest.new(224)
36
+ when :sha3_256
37
+ dig = org.bouncycastle.crypto.digests.SHA3Digest.new(256)
38
+ when :sha3_384
39
+ dig = org.bouncycastle.crypto.digests.SHA3Digest.new(384)
40
+ when :sha3_512
41
+ dig = org.bouncycastle.crypto.digests.SHA3Digest.new(512)
42
+ else
43
+ raise KDFEngineException, "Digest #{@config.digest} not supported"
44
+ end
45
+
46
+ @config.info = "" if @config.info.nil?
47
+
48
+ hkdf = org.bouncycastle.crypto.generators.HKDFBytesGenerator.new(dig)
49
+ hkdfParam = org.bouncycastle.crypto.params.HKDFParameters.new(to_java_bytes(input), to_java_bytes(@config.salt) ,to_java_bytes(@config.info))
50
+ hkdf.init(hkdfParam)
51
+
52
+ out = ::Java::byte[@config.outBitLength/8].new
53
+ hkdf.generateBytes(out, 0, out.length)
54
+
55
+ case output
56
+ when :b64
57
+ to_b64(out)
58
+ when :hex
59
+ to_hex(out)
60
+ else
61
+ out
62
+ end
63
+
64
+ rescue Exception => ex
65
+ raise KDFEngineException, ex
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,75 @@
1
+
2
+ require_relative '../data_conversion'
3
+
4
+ module Ccrypto
5
+ module Java
6
+ class HMACEngine
7
+ include TR::CondUtils
8
+ include DataConversion
9
+
10
+ include TeLogger::TeLogHelper
11
+ teLogger_tag :j_hmac
12
+
13
+ def initialize(*args, &block)
14
+ @config = args.first
15
+
16
+ raise HMACEngineException, "HMAC config is expected" if not @config.is_a?(Ccrypto::HMACConfig)
17
+
18
+ raise HMACEngineException, "Signing key is required" if is_empty?(@config.key)
19
+ raise HMACEngineException, "Secret key as signing key is required. Given #{@config.key.class}" if not @config.key.is_a?(Ccrypto::SecretKey)
20
+
21
+ teLogger.debug "Config : #{@config.inspect}"
22
+ begin
23
+ macAlgo = to_jce_spec(@config)
24
+ teLogger.debug "Mac algo : #{macAlgo}"
25
+ @hmac = javax.crypto.Mac.getInstance(to_jce_spec(@config))
26
+ @hmac.init(@config.key.to_jce_secret_key)
27
+ rescue Exception => ex
28
+ raise HMACEngineException, ex
29
+ end
30
+
31
+ end
32
+
33
+ def hmac_update(val)
34
+ @hmac.update(to_java_bytes(val)) if not_empty?(val)
35
+ end
36
+
37
+ def hmac_final
38
+ @hmac.doFinal
39
+ end
40
+
41
+ def hmac_digest(val, output = :binary)
42
+ hmac_update(val)
43
+ res = hmac_final
44
+
45
+ case output
46
+ when :hex
47
+ to_hex(res)
48
+ when :b64
49
+ to_b64(res)
50
+ else
51
+ res
52
+ end
53
+ end
54
+
55
+
56
+ private
57
+ def to_jce_spec(config)
58
+ res = []
59
+ res << "HMAC"
60
+
61
+ salgo = config.digest.to_s
62
+ if salgo =~ /_/
63
+ res << salgo.gsub("_","-").upcase
64
+ else
65
+ res << salgo.upcase
66
+ end
67
+
68
+ res.join
69
+
70
+ end
71
+
72
+
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,87 @@
1
+
2
+ require_relative '../data_conversion'
3
+
4
+ module Ccrypto
5
+ module Java
6
+
7
+ class PBKDF2Engine
8
+ include TR::CondUtils
9
+ include DataConversion
10
+
11
+ def initialize(*args, &block)
12
+ @config = args.first
13
+
14
+ raise KDFEngineException, "KDF config is expected. Given #{@config}" if not @config.is_a?(Ccrypto::PBKDF2Config)
15
+ raise KDFEngineException, "Output bit length (outBitLength) value is not given or not a positive value (#{@config.outBitLength})" if is_empty?(@config.outBitLength) or @config.outBitLength <= 0
16
+
17
+ raise KDFEngineException, "Digest algo is not supported. Given #{@config.digest}, supported: #{supported_digest.join(", ")}" if not @config.digest.nil? and not is_digest_supported?(@config.digest)
18
+
19
+ @config.digest = default_digest if is_empty?(@config.digest)
20
+
21
+ @config.salt = SecureRandom.random_bytes(16) if is_empty?(@config.salt)
22
+ end
23
+
24
+ def derive(input, output = :binary)
25
+
26
+ begin
27
+
28
+ case input
29
+ when String
30
+ if input.ascii_only?
31
+ pass = input.to_java.toCharArray
32
+ else
33
+ pass = to_hex(to_java_bytes(input)).to_java.toCharArray
34
+ end
35
+ when ::Java::byte[]
36
+ pass = to_hex(to_java_bytes(input)).to_java.toCharArray
37
+ else
38
+ raise KDFEngineException, "Input type '#{input.class}' cannot convert to char array"
39
+ end
40
+
41
+ skf = javax.crypto.SecretKeyFactory.getInstance("PBKDF2WithHMAC#{@config.digest.upcase}",JCEProvider::DEFProv)
42
+ keySpec = javax.crypto.spec.PBEKeySpec.new(pass.to_java, to_java_bytes(@config.salt), @config.iter, @config.outBitLength)
43
+
44
+ sk = skf.generateSecret(keySpec)
45
+ out = sk.encoded
46
+
47
+ case output
48
+ when :b64
49
+ to_b64(out)
50
+ when :hex
51
+ to_hex(out)
52
+ else
53
+ out
54
+ end
55
+
56
+ rescue Exception => ex
57
+ raise KDFEngineException, ex
58
+ end
59
+
60
+ end
61
+
62
+ def default_digest
63
+ :sha256
64
+ end
65
+
66
+ private
67
+ def logger
68
+ if @logger.nil?
69
+ @logger = TeLogger::Tlogger.new
70
+ @logger.tag = :j_pbkdf2
71
+ end
72
+ @logger
73
+ end
74
+
75
+ def is_digest_supported?(dig)
76
+ supported_digest.include?(dig)
77
+ end
78
+
79
+ def supported_digest
80
+ [:sha1, :sha256, :sha224, :sha384, :sha512]
81
+ end
82
+
83
+
84
+ end
85
+
86
+ end
87
+ end