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,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