ccrypto-java 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/.java-version +1 -1
- data/.release_history.yml +4 -0
- data/.ruby-version +1 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +68 -53
- data/Rakefile +2 -1
- data/bin/console +14 -0
- data/jars/bcjmail-jdk18on-172.jar +0 -0
- data/jars/bcmail-jdk18on-172.jar +0 -0
- data/jars/bcpg-jdk18on-172.1.jar +0 -0
- data/jars/bcpkix-jdk18on-172.jar +0 -0
- data/jars/bcprov-ext-jdk18on-172.jar +0 -0
- data/jars/bcprov-jdk18on-172.jar +0 -0
- data/jars/bctls-jdk18on-172.jar +0 -0
- data/jars/bcutil-jdk18on-172.jar +0 -0
- data/lib/ccrypto/java/bc_const_mapping.rb +42 -0
- data/lib/ccrypto/java/data_conversion.rb +23 -2
- data/lib/ccrypto/java/engines/argon2_engine.rb +95 -0
- data/lib/ccrypto/java/engines/asn1_engine.rb +2 -1
- data/lib/ccrypto/java/engines/bcrypt_engine.rb +56 -0
- data/lib/ccrypto/java/engines/cipher_engine.rb +462 -130
- data/lib/ccrypto/java/engines/compression_engine.rb +7 -28
- data/lib/ccrypto/java/engines/crystal_dilithium_engine.rb +226 -0
- data/lib/ccrypto/java/engines/crystal_kyber_engine.rb +260 -0
- data/lib/ccrypto/java/engines/decompression_engine.rb +5 -4
- data/lib/ccrypto/java/engines/digest_engine.rb +221 -139
- data/lib/ccrypto/java/engines/ecc_engine.rb +249 -96
- data/lib/ccrypto/java/engines/ed25519_engine.rb +211 -0
- data/lib/ccrypto/java/engines/hkdf_engine.rb +82 -23
- data/lib/ccrypto/java/engines/hmac_engine.rb +98 -23
- data/lib/ccrypto/java/engines/pbkdf2_engine.rb +82 -33
- data/lib/ccrypto/java/engines/pkcs7_engine.rb +44 -33
- data/lib/ccrypto/java/engines/rsa_engine.rb +85 -31
- data/lib/ccrypto/java/engines/scrypt_engine.rb +12 -3
- data/lib/ccrypto/java/engines/secret_key_engine.rb +77 -12
- data/lib/ccrypto/java/engines/secret_sharing_engine.rb +17 -2
- data/lib/ccrypto/java/engines/x25519_engine.rb +249 -0
- data/lib/ccrypto/java/engines/x509_csr_engine.rb +141 -0
- data/lib/ccrypto/java/engines/x509_engine.rb +365 -71
- data/lib/ccrypto/java/ext/secret_key.rb +37 -25
- data/lib/ccrypto/java/ext/x509_cert.rb +429 -5
- data/lib/ccrypto/java/ext/x509_csr.rb +151 -0
- data/lib/ccrypto/java/jce_provider.rb +0 -11
- data/lib/ccrypto/java/keystore/jce_keystore.rb +205 -0
- data/lib/ccrypto/java/keystore/jks_keystore.rb +52 -0
- data/lib/ccrypto/java/keystore/keystore.rb +97 -0
- data/lib/ccrypto/java/keystore/pem_keystore.rb +147 -0
- data/lib/ccrypto/java/keystore/pkcs12_keystore.rb +56 -0
- data/lib/ccrypto/java/utils/comparator.rb +25 -2
- data/lib/ccrypto/java/version.rb +1 -1
- data/lib/ccrypto/java.rb +46 -0
- data/lib/ccrypto/provider.rb +139 -3
- metadata +40 -24
- data/ccrypto-java.gemspec +0 -44
- data/jars/bcmail-jdk15on-165.jar +0 -0
- data/jars/bcpg-jdk15on-165.jar +0 -0
- data/jars/bcpkix-jdk15on-165.jar +0 -0
- data/jars/bcprov-ext-jdk15on-165.jar +0 -0
- data/jars/bcprov-jdk15on-165.jar +0 -0
- data/jars/bctls-jdk15on-165.jar +0 -0
- data/lib/ccrypto/java/keybundle_store/pkcs12.rb +0 -125
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
require_relative '../data_conversion'
|
3
3
|
|
4
|
-
require_relative '../
|
4
|
+
require_relative '../keystore/keystore'
|
5
5
|
|
6
6
|
module Ccrypto
|
7
7
|
module Java
|
@@ -9,181 +9,309 @@ module Ccrypto
|
|
9
9
|
class ECCPublicKey < Ccrypto::ECCPublicKey
|
10
10
|
include DataConversion
|
11
11
|
|
12
|
-
def
|
13
|
-
|
12
|
+
def initialize(kp, curve)
|
13
|
+
super(kp)
|
14
|
+
@curve = curve
|
15
|
+
end
|
16
|
+
|
17
|
+
def curve
|
18
|
+
@curve
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_bin(enc = :bin)
|
22
|
+
res = @native_pubKey.encoded
|
23
|
+
case enc
|
24
|
+
when :b64, :base64
|
25
|
+
to_b64(res)
|
26
|
+
when :hex
|
27
|
+
to_hex(res)
|
28
|
+
else
|
29
|
+
res
|
30
|
+
end
|
14
31
|
end
|
15
32
|
|
16
33
|
def encoded
|
17
34
|
to_bin
|
18
35
|
end
|
19
36
|
|
37
|
+
def to_pem
|
38
|
+
cont = ["-----BEGIN ECC PUBLIC KEY-----\n"]
|
39
|
+
cont << to_b64(to_bin)
|
40
|
+
cont << "\n-----END ECC PUBLIC KEY-----"
|
41
|
+
cont.join
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.from_pem(str)
|
45
|
+
if str =~ /ECC PUBLIC/
|
46
|
+
cont = str.lines[1..-2].join.strip
|
47
|
+
to_key(from_b64(cont))
|
48
|
+
else
|
49
|
+
raise KeypairEngineException, "Not an ECC public key"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# from binary to public key object
|
20
54
|
def self.to_key(bin)
|
21
55
|
bin = to_java_bytes(bin) if not bin.is_a?(::Java::byte[])
|
22
56
|
pubKey = java.security.KeyFactory.getInstance("ECDSA", "BC").generatePublic(java.security.spec.X509EncodedKeySpec.new(bin))
|
23
|
-
|
57
|
+
#p pubKey
|
58
|
+
curve = pubKey.params.name
|
59
|
+
ECCPublicKey.new(pubKey, curve)
|
24
60
|
end
|
25
61
|
|
26
|
-
|
62
|
+
def equals?(pubKey)
|
63
|
+
if not @native_pubKey.nil?
|
64
|
+
case pubKey
|
65
|
+
when ECCPublicKey
|
66
|
+
@native_pubKey.encoded == pubKey.to_bin
|
67
|
+
else
|
68
|
+
logger.warn "Unmatched public key : (native) #{@native_pubKey} vs. (subject) #{pubKey}"
|
69
|
+
false
|
70
|
+
end
|
71
|
+
else
|
72
|
+
logger.warn "ECCPublicKey equals? returned false because native_pubKey is nil"
|
73
|
+
false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
alias_method :key_equals?, :equals?
|
77
|
+
|
78
|
+
private
|
79
|
+
def logger
|
80
|
+
Ccrypto::Java.logger(:ecc_pubKey)
|
81
|
+
end
|
82
|
+
|
83
|
+
end # class ECCPublicKey
|
84
|
+
|
85
|
+
class ECCPrivateKey < Ccrypto::ECCPrivateKey
|
86
|
+
include DataConversion
|
87
|
+
|
88
|
+
def self.to_key(bin, &block)
|
89
|
+
if block
|
90
|
+
prov = block.call(:jce_provider)
|
91
|
+
else
|
92
|
+
prov = JCEProvider::BCProv
|
93
|
+
end
|
94
|
+
|
95
|
+
kf = java.security.KeyFactory.getInstance("ECDSA",prov)
|
96
|
+
priv = kf.generate_private(java.security.spec.PKCS8EncodedKeySpec.new(bin))
|
97
|
+
curve = priv.params.name
|
98
|
+
ECCPrivateKey.new(priv, curve)
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
attr_reader :curve
|
103
|
+
def initialize(privKey, curve = nil)
|
104
|
+
super(privKey)
|
105
|
+
@curve = curve
|
106
|
+
end
|
107
|
+
|
108
|
+
def to_pem
|
109
|
+
cont = ["-----BEGIN ECC PRIVATE KEY-----\n"]
|
110
|
+
cont << to_b64(@native_privKey.encoded)
|
111
|
+
cont << "\n-----END ECC PRIVATE KEY-----"
|
112
|
+
cont.join
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.from_pem(str)
|
116
|
+
if str =~ /ECC PRIVATE/
|
117
|
+
cont = str.lines[1..-2].join.strip
|
118
|
+
to_key(from_b64(cont))
|
119
|
+
else
|
120
|
+
raise KeypairEngineException, "Not an ECC private key"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def to_bin
|
125
|
+
@native_privKey.encoded
|
126
|
+
end
|
127
|
+
|
128
|
+
def equals?(privKey)
|
129
|
+
if not @native_privKey.nil?
|
130
|
+
case privKey
|
131
|
+
when ECCPrivateKey
|
132
|
+
@native_privKey.encoded == privKey.to_bin
|
133
|
+
else
|
134
|
+
logger.warn "Unmatched private key : (native) #{@native_privKey} vs. (subject) #{privKey}"
|
135
|
+
false
|
136
|
+
end
|
137
|
+
else
|
138
|
+
logger.warn "ECCPrivateKey equals? returned false because native_privKey is nil"
|
139
|
+
false
|
140
|
+
end
|
141
|
+
end
|
142
|
+
alias_method :key_equals?, :equals?
|
143
|
+
|
144
|
+
end # class ECCPrivateKey
|
27
145
|
|
28
146
|
class ECCKeyBundle
|
29
147
|
include Ccrypto::ECCKeyBundle
|
30
148
|
include TR::CondUtils
|
31
149
|
include DataConversion
|
32
150
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
teLogger_tag :j_ecc_keybundle
|
151
|
+
def initialize(kp, conf)
|
152
|
+
@nativeKeypair = kp
|
153
|
+
@config = conf
|
154
|
+
end
|
38
155
|
|
39
|
-
def
|
40
|
-
@
|
156
|
+
def curve
|
157
|
+
@config.provider_config[:curve]
|
41
158
|
end
|
42
159
|
|
43
|
-
|
44
|
-
|
160
|
+
# standardize external API
|
161
|
+
def key_param
|
162
|
+
@config
|
45
163
|
end
|
46
164
|
|
165
|
+
# standardize external API
|
47
166
|
def public_key
|
48
167
|
if @pubKey.nil?
|
49
|
-
@pubKey = ECCPublicKey.new(@
|
168
|
+
@pubKey = ECCPublicKey.new(@nativeKeypair.public, @config.curve)
|
50
169
|
end
|
51
170
|
@pubKey
|
52
171
|
end
|
53
172
|
|
173
|
+
# standardize external API
|
54
174
|
def private_key
|
55
|
-
ECCPrivateKey.new(@
|
175
|
+
ECCPrivateKey.new(@nativeKeypair.private)
|
56
176
|
end
|
57
177
|
|
58
|
-
|
178
|
+
# standardize external API
|
179
|
+
def derive_enc_shared_secret(*args, &block)
|
180
|
+
derive_dh_shared_secret(*args, &block)
|
181
|
+
end
|
59
182
|
|
60
|
-
|
183
|
+
# standardize external API
|
184
|
+
def derive_dec_shared_secret(*args, &block)
|
185
|
+
derive_dh_shared_secret(*args, &block)
|
186
|
+
end
|
61
187
|
|
62
|
-
|
63
|
-
|
188
|
+
def is_public_key_equal?(pubKey)
|
189
|
+
public_key.equals?(pubKey)
|
190
|
+
end
|
64
191
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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)
|
192
|
+
def equal?(kp)
|
193
|
+
case kp
|
194
|
+
when Ccrypto::ECCKeyBundle
|
195
|
+
private_key.encoded == kp.private_key.encoded
|
77
196
|
else
|
78
|
-
|
197
|
+
false
|
79
198
|
end
|
80
|
-
keyType = "AES" if is_empty?(keyType)
|
81
|
-
teLogger.debug "Generate secret key type #{keyType}"
|
82
|
-
ka.generateSecret(keyType).encoded
|
83
199
|
end
|
84
200
|
|
85
|
-
def
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
case type
|
92
|
-
when :p12, :pkcs12
|
93
|
-
to_pkcs12 do |key|
|
201
|
+
def write_keystore(type, &block)
|
202
|
+
ksType = Keystore.map_keystore_type(type)
|
203
|
+
case ksType
|
204
|
+
when :pkcs12
|
205
|
+
Keystore::PKCS12Keystore.to_p12 do |key, *val|
|
94
206
|
case key
|
95
207
|
when :keypair
|
96
|
-
@
|
208
|
+
@nativeKeypair
|
97
209
|
else
|
98
210
|
block.call(key) if block
|
99
211
|
end
|
100
212
|
end
|
101
|
-
|
102
213
|
when :jks
|
103
|
-
|
214
|
+
Keystore::JKSKeystore.to_jks do |key, *val|
|
104
215
|
case key
|
105
|
-
when :storeType
|
106
|
-
"JKS"
|
107
216
|
when :keypair
|
108
|
-
@
|
217
|
+
@nativeKeypair
|
109
218
|
else
|
110
|
-
block.call(key) if
|
219
|
+
block.call(key) if block
|
111
220
|
end
|
112
221
|
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
222
|
|
126
223
|
else
|
127
|
-
raise
|
224
|
+
raise Ccrypto::Keystore::KeystoreException, "Unsupported keystore type '#{type}' for engine '#{self.class.name}'"
|
128
225
|
end
|
129
|
-
|
130
226
|
end
|
131
227
|
|
132
|
-
|
133
|
-
|
134
|
-
if is_pem?(bin)
|
135
|
-
else
|
136
|
-
from_pkcs12(bin, &block)
|
137
|
-
end
|
228
|
+
private
|
229
|
+
def derive_dh_shared_secret(pubKey, &block)
|
138
230
|
|
139
|
-
|
231
|
+
JCEProvider.instance.add_bc_provider
|
140
232
|
|
141
|
-
|
142
|
-
|
143
|
-
(bin =~ /BEGIN/) != nil
|
144
|
-
rescue ArgumentError => ex
|
145
|
-
false
|
146
|
-
end
|
147
|
-
end
|
233
|
+
ka = javax.crypto.KeyAgreement.getInstance("ECDH", JCEProvider::DEFProv)
|
234
|
+
ka.init(@nativeKeypair.private)
|
148
235
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
236
|
+
case pubKey
|
237
|
+
when ECCPublicKey
|
238
|
+
#teLogger.debug "pubKey instanceof ECCPublicKey"
|
239
|
+
pub = pubKey.native_pubKey
|
240
|
+
when java.security.PublicKey
|
241
|
+
#teLogger.debug "pubKey instanceof java.security.PublicKey"
|
242
|
+
pub = pubKey
|
153
243
|
else
|
154
|
-
|
244
|
+
raise KeypairEngineException, "Unsupported public key type #{pubKey.class}"
|
155
245
|
end
|
246
|
+
ka.doPhase(pub, true)
|
247
|
+
|
248
|
+
ka.generateSecret
|
249
|
+
|
250
|
+
#if block
|
251
|
+
# keyType = block.call(:keytype)
|
252
|
+
#else
|
253
|
+
# keyType = "AES"
|
254
|
+
#end
|
255
|
+
#keyType = "AES" if is_empty?(keyType)
|
256
|
+
#teLogger.debug "Generate secret key type #{keyType}"
|
257
|
+
#ka.generateSecret(keyType).encoded
|
258
|
+
|
156
259
|
end
|
157
260
|
|
158
261
|
def method_missing(mtd, *args, &block)
|
159
262
|
teLogger.debug "Sending to native #{mtd}"
|
160
|
-
@
|
263
|
+
@nativeKeypair.send(mtd, *args, &block)
|
161
264
|
end
|
162
265
|
|
163
266
|
def respond_to_missing?(mtd, incPriv = false)
|
164
267
|
teLogger.debug "Respond to missing #{mtd}"
|
165
|
-
@
|
268
|
+
@nativeKeypair.respond_to?(mtd)
|
166
269
|
end
|
167
270
|
|
168
|
-
|
271
|
+
def teLogger
|
272
|
+
Ccrypto::Java.logger(:ecc_keybundle)
|
273
|
+
end
|
274
|
+
|
275
|
+
end # class ECCKeyBundle
|
169
276
|
|
170
277
|
class ECCEngine
|
171
278
|
include TR::CondUtils
|
172
279
|
include DataConversion
|
173
280
|
|
174
|
-
include TeLogger::TeLogHelper
|
175
|
-
teLogger_tag :j_ecc
|
176
|
-
|
177
281
|
def self.supported_curves
|
178
282
|
if @curves.nil?
|
179
|
-
@curves = org.bouncycastle.asn1.x9.ECNamedCurveTable.getNames.sort.to_a.map { |c|
|
283
|
+
@curves = org.bouncycastle.asn1.x9.ECNamedCurveTable.getNames.sort.to_a.map { |c|
|
284
|
+
conf = Ccrypto::ECCConfig.new(c.downcase.to_sym)
|
285
|
+
conf.provider_config = { curve: c }
|
286
|
+
conf
|
287
|
+
}
|
180
288
|
end
|
181
289
|
@curves
|
182
290
|
end
|
183
291
|
|
292
|
+
def self.find_curve(name)
|
293
|
+
case name
|
294
|
+
when String, Symbol
|
295
|
+
supported_curves.select { |c| c.provider_config[:curve] == name or c.curve == name.downcase.to_sym }.first
|
296
|
+
when Ccrypto::ECCKeyBundle
|
297
|
+
fname = name.key_param
|
298
|
+
supported_curves.select { |c| c.provider_config[:curve] == fname.provider_config[:curve] or c.curve == fname.algo }.first
|
299
|
+
when Ccrypto::ECCPublicKey
|
300
|
+
fname = name.curve
|
301
|
+
supported_curves.select { |c| c.provider_config[:curve] == fname or c.curve == fname.to_sym }.first
|
302
|
+
else
|
303
|
+
raise KeypairEngineException, "Not supported curve finder with '#{name.class}'"
|
304
|
+
end
|
305
|
+
end
|
306
|
+
class <<self
|
307
|
+
alias_method :supported_params, :supported_curves
|
308
|
+
alias_method :find_by_param, :find_curve
|
309
|
+
end
|
310
|
+
|
184
311
|
def initialize(*args,&block)
|
185
312
|
@config = args.first
|
186
313
|
raise KeypairEngineException, "1st parameter must be a #{Ccrypto::KeypairConfig.class} object" if not @config.is_a?(Ccrypto::KeypairConfig)
|
314
|
+
raise KeypairEngineException, "Keypair config must be an initialized config. Please get the initialized config from the list of supported_curves()" if is_empty?(@config.provider_config)
|
187
315
|
end
|
188
316
|
|
189
317
|
def generate_keypair(&block)
|
@@ -207,10 +335,10 @@ module Ccrypto
|
|
207
335
|
|
208
336
|
kpg = java.security.KeyPairGenerator.getInstance(algoName, prov)
|
209
337
|
#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
|
338
|
+
kpg.java_send :initialize, [java.security.spec.AlgorithmParameterSpec, randomEngine.class], java.security.spec.ECGenParameterSpec.new(@config.provider_config[:curve]), randomEngine
|
211
339
|
kp = kpg.generate_key_pair
|
212
340
|
|
213
|
-
kb = ECCKeyBundle.new(kp)
|
341
|
+
kb = ECCKeyBundle.new(kp, @config)
|
214
342
|
kb
|
215
343
|
|
216
344
|
end
|
@@ -227,7 +355,7 @@ module Ccrypto
|
|
227
355
|
|
228
356
|
sign = java.security.Signature.getInstance("SHA256WithECDSA")
|
229
357
|
sign.initSign(kp.private_key)
|
230
|
-
teLogger.debug "Signing data : #{val}"
|
358
|
+
#teLogger.debug "Signing data : #{val}"
|
231
359
|
case val
|
232
360
|
when java.io.InputStream
|
233
361
|
buf = Java::byte[102400].new
|
@@ -244,7 +372,7 @@ module Ccrypto
|
|
244
372
|
def self.verify(pubKey, val, sign)
|
245
373
|
ver = java.security.Signature.getInstance("SHA256WithECDSA")
|
246
374
|
ver.initVerify(pubKey)
|
247
|
-
teLogger.debug "Verifing data : #{val}"
|
375
|
+
#teLogger.debug "Verifing data : #{val}"
|
248
376
|
case val
|
249
377
|
when java.io.InputStream
|
250
378
|
buf = Java::byte[102400].new
|
@@ -258,6 +386,31 @@ module Ccrypto
|
|
258
386
|
ver.verify(to_java_bytes(sign))
|
259
387
|
end
|
260
388
|
|
389
|
+
#
|
390
|
+
# KeyFactory keyFactory = KeyFactory.getInstance(EC.getAlgorithmName(), BouncyCastleProviderHolder.getInstance());
|
391
|
+
# BCECPrivateKey ecPrivateKey = (BCECPrivateKey) privateKey;
|
392
|
+
# ECParameterSpec ecParameterSpec = ecPrivateKey.getParameters();
|
393
|
+
# ECPoint ecPoint = new FixedPointCombMultiplier().multiply(ecParameterSpec.getG(), ecPrivateKey.getD());
|
394
|
+
# ECPublicKeySpec keySpec = new ECPublicKeySpec(ecPoint, ecParameterSpec);
|
395
|
+
# return keyFactory.generatePublic(keySpec);
|
396
|
+
#
|
397
|
+
def self.ecc_public_key_from_private_key(privKey)
|
398
|
+
kf = java.security.KeyFactory.getInstance("ECDSA", JCEProvider::BCProv)
|
399
|
+
param = privKey.parameters
|
400
|
+
ecPoint = org.bouncycastle.math.ec.FixedPointCombMultiplier.new.multiply(param.g, privKey.d)
|
401
|
+
keySpec = org.bouncycastle.jce.spec.ECPublicKeySpec.new(ecPoint, param)
|
402
|
+
kf.generatePublic(keySpec)
|
403
|
+
end
|
404
|
+
|
405
|
+
private
|
406
|
+
def self.teLogger
|
407
|
+
Ccrypto::Java.logger(:ecc_eng)
|
408
|
+
end
|
409
|
+
def teLogger
|
410
|
+
self.class.teLogger
|
411
|
+
end
|
412
|
+
|
413
|
+
|
261
414
|
end
|
262
415
|
end
|
263
416
|
end
|
@@ -0,0 +1,211 @@
|
|
1
|
+
|
2
|
+
require_relative '../data_conversion'
|
3
|
+
|
4
|
+
module Ccrypto
|
5
|
+
module Java
|
6
|
+
|
7
|
+
class ED25519PublicKey < Ccrypto::ED25519PublicKey
|
8
|
+
include DataConversion
|
9
|
+
|
10
|
+
def to_bin
|
11
|
+
@native_pubKey.encoded
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.to_key(bin)
|
15
|
+
pubKey = java.security.KeyFactory.getInstance("ED25519", "BC").generatePublic(java.security.spec.X509EncodedKeySpec.new(bin))
|
16
|
+
ED25519PublicKey.new(pubKey)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_pem
|
20
|
+
cont = ["-----BEGIN ED25519 PUBLIC KEY-----\n"]
|
21
|
+
cont << to_b64(to_bin)
|
22
|
+
cont << "\n-----END ED25519 PUBLIC KEY-----"
|
23
|
+
cont.join
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.from_pem(str)
|
27
|
+
if str =~ /ED25519 PUBLIC/
|
28
|
+
cont = str.lines[1..-2].join.strip
|
29
|
+
to_key(from_b64(cont))
|
30
|
+
else
|
31
|
+
raise KeypairEngineException, "Not an ED25519 public key"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end # ED25519PublicKey
|
36
|
+
|
37
|
+
class ED25519PrivateKey < Ccrypto::ED25519PrivateKey
|
38
|
+
include DataConversion
|
39
|
+
|
40
|
+
def self.to_key(bin, &block)
|
41
|
+
if block
|
42
|
+
prov = block.call(:jce_provider)
|
43
|
+
else
|
44
|
+
prov = JCEProvider::BCProv
|
45
|
+
end
|
46
|
+
|
47
|
+
kf = java.security.KeyFactory.getInstance("ED25519",prov)
|
48
|
+
priv = kf.generate_private(java.security.spec.PKCS8EncodedKeySpec.new(bin))
|
49
|
+
ED25519PrivateKey.new(priv)
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_pem
|
54
|
+
cont = ["-----BEGIN ED25519 PRIVATE KEY-----\n"]
|
55
|
+
cont << to_b64(@native_privKey.encoded)
|
56
|
+
cont << "\n-----END ED25519 PRIVATE KEY-----"
|
57
|
+
cont.join
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.from_pem(str)
|
61
|
+
if str =~ /ED25519 PRIVATE/
|
62
|
+
cont = str.lines[1..-2].join.strip
|
63
|
+
to_key(from_b64(cont))
|
64
|
+
else
|
65
|
+
raise KeypairEngineException, "Not an ED25519 private key"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_bin
|
70
|
+
@native_privKey.encoded
|
71
|
+
end
|
72
|
+
|
73
|
+
def equals?(privKey)
|
74
|
+
if not @native_privKey.nil?
|
75
|
+
case privKey
|
76
|
+
when ED25519PrivateKey
|
77
|
+
@native_privKey.encoded == privKey.to_bin
|
78
|
+
else
|
79
|
+
logger.warn "Unmatched private key : (native) #{@native_privKey} vs. (subject) #{privKey}"
|
80
|
+
false
|
81
|
+
end
|
82
|
+
else
|
83
|
+
logger.warn "ED25519PrivateKey equals? returned false because native_privKey is nil"
|
84
|
+
false
|
85
|
+
end
|
86
|
+
end
|
87
|
+
alias_method :key_equals?, :equals?
|
88
|
+
|
89
|
+
|
90
|
+
end # ED25519PrivateKey
|
91
|
+
|
92
|
+
class ED25519KeyBundle
|
93
|
+
include Ccrypto::ED25519KeyBundle
|
94
|
+
include Ccrypto::X25519KeyBundle
|
95
|
+
|
96
|
+
include TR::CondUtils
|
97
|
+
include DataConversion
|
98
|
+
|
99
|
+
include TeLogger::TeLogHelper
|
100
|
+
teLogger_tag :ed25519_kb_j
|
101
|
+
|
102
|
+
def initialize(kp)
|
103
|
+
@nativeKeypair = kp
|
104
|
+
end
|
105
|
+
|
106
|
+
def public_key
|
107
|
+
if @pubKey.nil?
|
108
|
+
@pubKey = ED25519PublicKey.new(@nativeKeypair.getPublic)
|
109
|
+
end
|
110
|
+
@pubKey
|
111
|
+
end
|
112
|
+
|
113
|
+
def private_key
|
114
|
+
ED25519PrivateKey.new(@nativeKeypair.getPrivate)
|
115
|
+
end
|
116
|
+
|
117
|
+
def derive_dh_shared_secret(pubKey, &block)
|
118
|
+
|
119
|
+
JCEProvider.instance.add_bc_provider
|
120
|
+
|
121
|
+
ka = javax.crypto.KeyAgreement.getInstance("X25519",JCEProvider::BCProv.name)
|
122
|
+
ka.init(@nativeKeypair.getPrivate)
|
123
|
+
ka.doPhase(pubKey, true)
|
124
|
+
ka.generateSecret()
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end # ED25519KeyBundle
|
129
|
+
|
130
|
+
class ED25519Engine
|
131
|
+
include TR::CondUtils
|
132
|
+
include DataConversion
|
133
|
+
|
134
|
+
include TeLogger::TeLogHelper
|
135
|
+
teLogger_tag :ed25519_eng_j
|
136
|
+
|
137
|
+
def self.supported_params
|
138
|
+
[]
|
139
|
+
end
|
140
|
+
|
141
|
+
def initialize(*args, &block)
|
142
|
+
@config = args.first
|
143
|
+
end
|
144
|
+
|
145
|
+
def generate_keypair(&block)
|
146
|
+
|
147
|
+
JCEProvider.instance.add_bc_provider
|
148
|
+
kg = java.security.KeyPairGenerator.getInstance("ED25519", JCEProvider::BCProv.name)
|
149
|
+
ED25519KeyBundle.new(kg.generateKeyPair)
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
def sign(val, &block)
|
154
|
+
|
155
|
+
sign = java.security.Signature.getInstance("EdDSA", JCEProvider::BCProv.name)
|
156
|
+
|
157
|
+
case @config.keypair
|
158
|
+
when ED25519KeyBundle
|
159
|
+
privKey = @config.keypair.nativeKeypair.getPrivate
|
160
|
+
else
|
161
|
+
raise KeypairEngineException,"Unsupported keypair type '#{@config.keypair.class}'"
|
162
|
+
end
|
163
|
+
|
164
|
+
sign.initSign(privKey)
|
165
|
+
|
166
|
+
case val
|
167
|
+
when java.io.InputStream
|
168
|
+
buf = Java::byte[102400].new
|
169
|
+
while((read = val.read(buf, 0, buf.length)) != nil)
|
170
|
+
sign.update(buf,0,read)
|
171
|
+
end
|
172
|
+
else
|
173
|
+
sign.update(to_java_bytes(val))
|
174
|
+
end
|
175
|
+
|
176
|
+
sign.sign
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
def self.verify(pubKey, val, sign)
|
181
|
+
|
182
|
+
ver = java.security.Signature.getInstance("EdDSA", JCEProvider::BCProv.name)
|
183
|
+
|
184
|
+
case pubKey
|
185
|
+
when ED25519PublicKey
|
186
|
+
uPubKey = pubKey.native_pubKey
|
187
|
+
else
|
188
|
+
raise KeypairEngineException, "Unsupported public key type '#{pubKey.class}'"
|
189
|
+
end
|
190
|
+
|
191
|
+
ver.initVerify(uPubKey)
|
192
|
+
|
193
|
+
case val
|
194
|
+
when java.io.InputStream
|
195
|
+
buf = Java::byte[102400].new
|
196
|
+
while((read = val.read(buf, 0 ,buf.length)) != nil)
|
197
|
+
ver.update(buf,0, read)
|
198
|
+
end
|
199
|
+
else
|
200
|
+
ver.update(to_java_bytes(val))
|
201
|
+
end
|
202
|
+
|
203
|
+
ver.verify(to_java_bytes(sign))
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
end
|