ccrypto-java 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,12 +1,11 @@
|
|
1
1
|
|
2
2
|
require_relative '../data_conversion'
|
3
|
-
require_relative '../keybundle_store/pkcs12'
|
4
|
-
#require_relative '../keybundle_store/pem_store'
|
5
3
|
|
6
4
|
module Ccrypto
|
7
5
|
module Java
|
8
6
|
|
9
7
|
class RSAPublicKey < Ccrypto::RSAPublicKey
|
8
|
+
include DataConversion
|
10
9
|
|
11
10
|
def to_bin
|
12
11
|
@native_pubKey.encoded
|
@@ -17,19 +16,87 @@ module Ccrypto
|
|
17
16
|
RSAPublicKey.new(pubKey)
|
18
17
|
end
|
19
18
|
|
19
|
+
def to_pem
|
20
|
+
cont = ["-----BEGIN RSA PUBLIC KEY-----\n"]
|
21
|
+
cont << to_b64(to_bin)
|
22
|
+
cont << "\n-----END RSA PUBLIC KEY-----"
|
23
|
+
cont.join
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.from_pem(str)
|
27
|
+
if str =~ /RSA PUBLIC/
|
28
|
+
cont = str.lines[1..-2].join.strip
|
29
|
+
to_key(from_b64(cont))
|
30
|
+
else
|
31
|
+
raise KeypairEngineException, "Not an RSA public key"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
20
35
|
def method_missing(mtd, *args, &block)
|
21
36
|
@native_pubKey.send(mtd, *args, &block)
|
22
37
|
end
|
23
38
|
|
24
39
|
end # RSAPublicKey
|
25
40
|
|
41
|
+
|
42
|
+
class RSAPrivateKey < Ccrypto::RSAPrivateKey
|
43
|
+
include DataConversion
|
44
|
+
|
45
|
+
def self.to_key(bin, &block)
|
46
|
+
if block
|
47
|
+
prov = block.call(:jce_provider)
|
48
|
+
else
|
49
|
+
prov = JCEProvider::BCProv
|
50
|
+
end
|
51
|
+
|
52
|
+
kf = java.security.KeyFactory.getInstance("RSA",prov)
|
53
|
+
priv = kf.generate_private(java.security.spec.PKCS8EncodedKeySpec.new(bin))
|
54
|
+
RSAPrivateKey.new(priv)
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_pem
|
59
|
+
cont = ["-----BEGIN RSA PRIVATE KEY-----\n"]
|
60
|
+
cont << to_b64(@native_privKey.encoded)
|
61
|
+
cont << "\n-----END RSA PRIVATE KEY-----"
|
62
|
+
cont.join
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.from_pem(str)
|
66
|
+
if str =~ /RSA PRIVATE/
|
67
|
+
cont = str.lines[1..-2].join.strip
|
68
|
+
to_key(from_b64(cont))
|
69
|
+
else
|
70
|
+
raise KeypairEngineException, "Not an RSA private key"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_bin
|
75
|
+
@native_privKey.encoded
|
76
|
+
end
|
77
|
+
|
78
|
+
def equals?(privKey)
|
79
|
+
if not @native_privKey.nil?
|
80
|
+
case privKey
|
81
|
+
when RSAPrivateKey
|
82
|
+
@native_privKey.encoded == privKey.to_bin
|
83
|
+
else
|
84
|
+
logger.warn "Unmatched private key : (native) #{@native_privKey} vs. (subject) #{privKey}"
|
85
|
+
false
|
86
|
+
end
|
87
|
+
else
|
88
|
+
logger.warn "RSAPrivateKey equals? returned false because native_privKey is nil"
|
89
|
+
false
|
90
|
+
end
|
91
|
+
end
|
92
|
+
alias_method :key_equals?, :equals?
|
93
|
+
|
94
|
+
end # class RSAPrivateKey
|
95
|
+
|
26
96
|
class RSAKeyBundle
|
27
97
|
include Ccrypto::RSAKeyBundle
|
28
98
|
include TR::CondUtils
|
29
99
|
|
30
|
-
include PKCS12
|
31
|
-
#include PEMStore
|
32
|
-
|
33
100
|
include TeLogger::TeLogHelper
|
34
101
|
|
35
102
|
teLogger_tag :j_rsa_keybundle
|
@@ -52,11 +119,11 @@ module Ccrypto
|
|
52
119
|
@privKey
|
53
120
|
end
|
54
121
|
|
55
|
-
def
|
56
|
-
|
57
|
-
case
|
58
|
-
when :
|
59
|
-
|
122
|
+
def write_keystore(type, &block)
|
123
|
+
ksType = Keystore.map_keystore_type(type)
|
124
|
+
case ksType
|
125
|
+
when :pkcs12
|
126
|
+
Keystore::PKCS12Keystore.to_p12 do |key, *val|
|
60
127
|
case key
|
61
128
|
when :keypair
|
62
129
|
@nativeKeypair
|
@@ -64,43 +131,26 @@ module Ccrypto
|
|
64
131
|
block.call(key) if block
|
65
132
|
end
|
66
133
|
end
|
67
|
-
|
68
134
|
when :jks
|
69
|
-
|
135
|
+
Keystore::JKSKeystore.to_jks do |key, *val|
|
70
136
|
case key
|
71
|
-
when :storeType
|
72
|
-
"JKS"
|
73
137
|
when :keypair
|
74
138
|
@nativeKeypair
|
75
139
|
else
|
76
140
|
block.call(key) if block
|
77
141
|
end
|
78
142
|
end
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|
82
143
|
|
83
|
-
def self.from_storage(bin, &block)
|
84
|
-
|
85
|
-
if is_pem?(bin)
|
86
144
|
else
|
87
|
-
|
88
|
-
end
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
def self.is_pem?(bin)
|
93
|
-
begin
|
94
|
-
(bin =~ /BEGIN/) != nil
|
95
|
-
rescue ArgumentError => ex
|
96
|
-
false
|
145
|
+
raise Ccrypto::Keystore::KeystoreException, "Unsupported keystore type '#{type}' for engine '#{self.class.name}'"
|
97
146
|
end
|
98
147
|
end
|
99
148
|
|
149
|
+
|
100
150
|
def equal?(kp)
|
101
151
|
case kp
|
102
152
|
when Ccrypto::RSAKeyBundle
|
103
|
-
|
153
|
+
private_key.encoded == kp.private_key.encoded
|
104
154
|
else
|
105
155
|
false
|
106
156
|
end
|
@@ -126,6 +176,10 @@ module Ccrypto
|
|
126
176
|
|
127
177
|
teLogger_tag :j_rsa
|
128
178
|
|
179
|
+
def self.supported_params
|
180
|
+
[1024,2048,4096,8192]
|
181
|
+
end
|
182
|
+
|
129
183
|
def initialize(*args, &block)
|
130
184
|
@config = args.first
|
131
185
|
raise KeypairEngineException, "1st parameter must be a #{Ccrypto::KeypairConfig.class} object" if not @config.is_a?(Ccrypto::KeypairConfig)
|
@@ -8,18 +8,22 @@ module Ccrypto
|
|
8
8
|
include TR::CondUtils
|
9
9
|
|
10
10
|
def initialize(conf, &block)
|
11
|
+
|
11
12
|
raise KDFEngineException, "KDF config is expected" if not conf.is_a?(Ccrypto::KDFConfig)
|
12
13
|
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
14
|
@config = conf
|
14
15
|
|
15
16
|
if is_empty?(@config.salt)
|
16
|
-
@config.salt = Java::byte[16].new
|
17
|
-
java.security.SecureRandom.getInstance("NativePRNG").
|
17
|
+
@config.salt = ::Java::byte[16].new
|
18
|
+
java.security.SecureRandom.getInstance("NativePRNG").next_bytes(@config.salt)
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
21
22
|
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.
|
23
|
+
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)
|
24
|
+
|
25
|
+
#logger.debug "scrypt output : #{res.inspect}"
|
26
|
+
|
23
27
|
case output
|
24
28
|
when :hex
|
25
29
|
to_hex(res)
|
@@ -30,6 +34,11 @@ module Ccrypto
|
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
37
|
+
private
|
38
|
+
def logger
|
39
|
+
Ccrypto::Java.logger(:scrypt_eng)
|
40
|
+
end
|
41
|
+
|
33
42
|
end
|
34
43
|
end
|
35
44
|
end
|
@@ -2,41 +2,106 @@
|
|
2
2
|
|
3
3
|
module Ccrypto
|
4
4
|
module Java
|
5
|
+
|
6
|
+
class SecretKeyEngineException < StandardError; end
|
7
|
+
|
5
8
|
class SecretKeyEngine
|
9
|
+
include TR::CondUtils
|
10
|
+
include DataConversion
|
11
|
+
|
12
|
+
def self.supported_secret_key_configs
|
13
|
+
if @supKeyConf.nil?
|
14
|
+
@supKeyConf = []
|
15
|
+
supported_secret_key_config_table.each do |algo, keysize|
|
16
|
+
keysize.each do |k,v|
|
17
|
+
@supKeyConf << v
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
@supKeyConf
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.find_supported_secret_key_config(algo, keysize = nil)
|
25
|
+
res = supported_secret_key_config_table[algo] || {}
|
26
|
+
res[keysize] || nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.is_secret_key_config_supported?(algo, keysize = nil)
|
30
|
+
not find_supported_secret_key_config(algo. keysize).nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def self.supported_secret_key_config_table
|
35
|
+
if @seckey_configs.nil?
|
36
|
+
@seckey_configs = {}
|
6
37
|
|
7
|
-
|
8
|
-
|
9
|
-
|
38
|
+
CipherEngine.supported_ciphers.each do |cf|
|
39
|
+
kf = cf.key_config
|
40
|
+
algo = kf.algo.to_sym
|
41
|
+
keysize = kf.keysize
|
42
|
+
|
43
|
+
if @seckey_configs[algo].nil?
|
44
|
+
@seckey_configs[algo] = { }
|
45
|
+
@seckey_configs[algo][keysize] = kf
|
46
|
+
else
|
47
|
+
if is_empty?(@seckey_configs[algo][keysize])
|
48
|
+
@seckey_configs[algo][keysize] = kf
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
@seckey_configs
|
55
|
+
end
|
56
|
+
|
57
|
+
public
|
10
58
|
def self.generate(*args, &block)
|
11
59
|
config = args.first
|
12
60
|
|
13
|
-
raise SecretKeyEngineException, "KeyConfig is expected" if not config.is_a?(Ccrypto::KeyConfig)
|
61
|
+
raise SecretKeyEngineException, "KeyConfig is expected but got '#{config.class.name}'" if not config.is_a?(Ccrypto::KeyConfig)
|
62
|
+
raise SecretKeyEngineException, "Provider initialized KeyConfig is expected" if is_empty?(config.provider_config)
|
14
63
|
|
15
64
|
if block
|
16
65
|
kgProv = block.call(:keygen_jceProvider)
|
17
66
|
ranProv = block.call(:random_jceProvider)
|
67
|
+
else
|
68
|
+
kgProv = config.provider_config[:key_jce_provider] || JCEProvider::DEFProv
|
18
69
|
end
|
19
70
|
|
20
71
|
if kgProv.nil?
|
21
|
-
|
22
|
-
keyGen = javax.crypto.KeyGenerator.getInstance(config.
|
72
|
+
logger.debug "KeyGen using algo #{config.algo.to_s} with null provider"
|
73
|
+
keyGen = javax.crypto.KeyGenerator.getInstance(config.provider_config[:keygen_algo])
|
23
74
|
else
|
24
|
-
|
25
|
-
keyGen = javax.crypto.KeyGenerator.getInstance(config.
|
75
|
+
logger.debug "KeyGen using algo #{config.algo.to_s} with provider #{kgProv.is_a?(String) ? kgProv : kgProv.name}"
|
76
|
+
keyGen = javax.crypto.KeyGenerator.getInstance(config.provider_config[:keygen_algo], kgProv)
|
26
77
|
end
|
27
78
|
|
28
79
|
if ranProv.nil?
|
29
|
-
|
80
|
+
logger.debug "Init KeyGen with keysize #{config.keysize.to_i}"
|
30
81
|
keyGen.init(config.keysize.to_i)
|
31
82
|
else
|
32
|
-
|
83
|
+
logger.debug "Init KeyGen with keysize #{config.keysize.to_i} with provider #{ranProv.is_a?(String) ? ranProv : ranProv.name}"
|
33
84
|
keyGen.init(config.keysize.to_i, ranProv)
|
34
85
|
end
|
35
86
|
|
36
87
|
key = keyGen.generateKey
|
37
|
-
|
38
|
-
Ccrypto::SecretKey.new(config.algo, key)
|
88
|
+
logger.debug "Secret key #{config} generated"
|
89
|
+
sk = Ccrypto::SecretKey.new(config.algo, config.keysize, key)
|
90
|
+
sk.provider_config = config.provider_config
|
91
|
+
sk
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.secret_key_from_bin(bin, algo, keysize)
|
96
|
+
raise SecretKeyEngineException, "No data given to convert to secret key" if is_empty?(bin)
|
97
|
+
raise SecretKeyEngineException, "Algo cannot be empty" if is_empty?(algo)
|
98
|
+
|
99
|
+
Ccrypto::SecretKey.new(algo, keysize, javax.crypto.spec.SecretKeySpec.new(to_java_bytes(bin), algo.to_s))
|
100
|
+
end
|
39
101
|
|
102
|
+
private
|
103
|
+
def self.logger
|
104
|
+
Ccrypto::Java.logger(:seckey_eng)
|
40
105
|
end
|
41
106
|
|
42
107
|
end
|
@@ -3,14 +3,22 @@ require_relative '../data_conversion'
|
|
3
3
|
|
4
4
|
module Ccrypto
|
5
5
|
module Java
|
6
|
+
|
7
|
+
class SecretSharingException < Ccrypto::SecretSharingException; end
|
8
|
+
|
6
9
|
class SecretSharingEngine
|
7
10
|
include DataConversion
|
8
11
|
|
12
|
+
|
9
13
|
def initialize(*args, &block)
|
10
14
|
@config = args.first
|
15
|
+
|
11
16
|
raise SecretSharingException, "SecretSharingConfig is required" if not @config.is_a?(Ccrypto::SecretSharingConfig)
|
12
|
-
|
13
|
-
|
17
|
+
sit = @config.split_into.to_i
|
18
|
+
rp = @config.required_parts.to_i
|
19
|
+
raise SecretSharingException, "split_into value must be more than 1" if not sit > 1
|
20
|
+
raise SecretSharingException, "required_parts value must be more than 0" if not rp > 0
|
21
|
+
raise SecretSharingException, "required_parts value (#{@config.required_parts}) must be less than or equal split_into value (#{@config.split_into})." if not rp <= sit.to_i
|
14
22
|
end
|
15
23
|
|
16
24
|
def split(secVal)
|
@@ -36,6 +44,7 @@ module Ccrypto
|
|
36
44
|
# as the automated conversion of JRuby will turn the key into
|
37
45
|
# java.lang.Long instead of java.lang.Integer
|
38
46
|
# Using Map with parameterize auto conversion will failed inside the Java
|
47
|
+
partLength = -1
|
39
48
|
parts.each do |k,v|
|
40
49
|
if not v.is_a?(::Java::byte[])
|
41
50
|
vv = to_java_bytes(v)
|
@@ -43,6 +52,12 @@ module Ccrypto
|
|
43
52
|
vv = v
|
44
53
|
end
|
45
54
|
|
55
|
+
if partLength == -1
|
56
|
+
partLength = vv.length
|
57
|
+
else
|
58
|
+
raise SecretSharingException, "Invalid parts are given. Inconsistant part length (#{partLength} vs. #{vv.length})" if partLength != vv.length
|
59
|
+
end
|
60
|
+
|
46
61
|
jhash.put(java.lang.Integer.new(k),vv)
|
47
62
|
end
|
48
63
|
when java.util.Map
|
@@ -0,0 +1,249 @@
|
|
1
|
+
|
2
|
+
require_relative '../data_conversion'
|
3
|
+
|
4
|
+
module Ccrypto
|
5
|
+
module Java
|
6
|
+
|
7
|
+
class X25519PublicKey < Ccrypto::X25519PublicKey
|
8
|
+
include DataConversion
|
9
|
+
|
10
|
+
def to_bin
|
11
|
+
res = @native_pubKey.encoded
|
12
|
+
#puts "to_bion : #{to_hex(res)}"
|
13
|
+
res
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.to_key(bin)
|
17
|
+
pubKey = java.security.KeyFactory.getInstance("X25519", "BC").generatePublic(java.security.spec.X509EncodedKeySpec.new(bin))
|
18
|
+
X25519PublicKey.new(pubKey)
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_pem
|
22
|
+
cont = ["-----BEGIN X25519 PUBLIC KEY-----\n"]
|
23
|
+
cont << to_b64(to_bin)
|
24
|
+
cont << "\n-----END X25519 PUBLIC KEY-----"
|
25
|
+
cont.join
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.from_pem(str)
|
29
|
+
if str =~ /X25519 PUBLIC/
|
30
|
+
cont = str.lines[1..-2].join.strip
|
31
|
+
to_key(from_b64(cont))
|
32
|
+
else
|
33
|
+
raise KeypairEngineException, "Not an X25519 public key"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end # X25519PublicKey
|
38
|
+
|
39
|
+
class X25519PrivateKey < Ccrypto::X25519PrivateKey
|
40
|
+
include DataConversion
|
41
|
+
|
42
|
+
def to_bin
|
43
|
+
@native_privKey.encoded
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.to_key(bin, &block)
|
47
|
+
if block
|
48
|
+
prov = block.call(:jce_provider)
|
49
|
+
else
|
50
|
+
prov = JCEProvider::BCProv
|
51
|
+
end
|
52
|
+
|
53
|
+
kf = java.security.KeyFactory.getInstance("X25519",prov)
|
54
|
+
priv = kf.generate_private(java.security.spec.PKCS8EncodedKeySpec.new(bin))
|
55
|
+
X25519PrivateKey.new(priv)
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_pem
|
60
|
+
cont = ["-----BEGIN X25519 PRIVATE KEY-----\n"]
|
61
|
+
cont << to_b64(@native_privKey.encoded)
|
62
|
+
cont << "\n-----END X25519 PRIVATE KEY-----"
|
63
|
+
cont.join
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.from_pem(str)
|
67
|
+
if str =~ /X25519 PRIVATE/
|
68
|
+
cont = str.lines[1..-2].join.strip
|
69
|
+
to_key(from_b64(cont))
|
70
|
+
else
|
71
|
+
raise KeypairEngineException, "Not an X25519 private key"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def equals?(privKey)
|
76
|
+
if not @native_privKey.nil?
|
77
|
+
case privKey
|
78
|
+
when X25519PrivateKey
|
79
|
+
@native_privKey.encoded == privKey.to_bin
|
80
|
+
else
|
81
|
+
logger.warn "Unmatched private key : (native) #{@native_privKey} vs. (subject) #{privKey}"
|
82
|
+
false
|
83
|
+
end
|
84
|
+
else
|
85
|
+
logger.warn "X25519PrivateKey equals? returned false because native_privKey is nil"
|
86
|
+
false
|
87
|
+
end
|
88
|
+
end
|
89
|
+
alias_method :key_equals?, :equals?
|
90
|
+
|
91
|
+
end # X25519PrivateKey
|
92
|
+
|
93
|
+
class X25519KeyBundle
|
94
|
+
include Ccrypto::X25519KeyBundle
|
95
|
+
include Ccrypto::X25519KeyBundle
|
96
|
+
|
97
|
+
include TR::CondUtils
|
98
|
+
include DataConversion
|
99
|
+
|
100
|
+
include TeLogger::TeLogHelper
|
101
|
+
teLogger_tag :x25519_kb_j
|
102
|
+
|
103
|
+
def initialize(kp)
|
104
|
+
@nativeKeypair = kp
|
105
|
+
end
|
106
|
+
|
107
|
+
def public_key
|
108
|
+
if @pubKey.nil?
|
109
|
+
@pubKey = X25519PublicKey.new(@nativeKeypair.getPublic)
|
110
|
+
end
|
111
|
+
@pubKey
|
112
|
+
end
|
113
|
+
|
114
|
+
def private_key
|
115
|
+
X25519PrivateKey.new(@nativeKeypair.getPrivate)
|
116
|
+
end
|
117
|
+
|
118
|
+
def derive_dh_shared_secret(pubKey, &block)
|
119
|
+
|
120
|
+
JCEProvider.instance.add_bc_provider
|
121
|
+
|
122
|
+
ka = javax.crypto.KeyAgreement.getInstance("X25519",JCEProvider::BCProv.name)
|
123
|
+
ka.init(@nativeKeypair.getPrivate)
|
124
|
+
|
125
|
+
case pubKey
|
126
|
+
when X25519PublicKey
|
127
|
+
uPubKey = pubKey.native_pubKey
|
128
|
+
else
|
129
|
+
raise KeypairEngineException, "Unsupported public key type '#{pubKey.class}'"
|
130
|
+
end
|
131
|
+
|
132
|
+
ka.doPhase(uPubKey, true)
|
133
|
+
ka.generateSecret()
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
## should be under keybundle_store but not sure how to do this
|
138
|
+
def to_storage(eng = :ccrypto, &block)
|
139
|
+
case eng
|
140
|
+
when :ccrypto
|
141
|
+
res = { }
|
142
|
+
|
143
|
+
rawPrivate = false
|
144
|
+
rawPublic = false
|
145
|
+
if block
|
146
|
+
rawPrivate = block.call(:export_raw_private_key)
|
147
|
+
rawPublic = block.call(:export_raw_public_key)
|
148
|
+
end
|
149
|
+
|
150
|
+
res[:private] = private_key.to_bin
|
151
|
+
if rawPrivate == true
|
152
|
+
# 5th Sept 2022 - untested code
|
153
|
+
res[:private] = org.bouncycastle.crypto.params.X25519PrivateKeyParameters.new(res[:private],0).encoded
|
154
|
+
res[:raw_private] = true
|
155
|
+
end
|
156
|
+
|
157
|
+
res[:public] = public_key.to_bin
|
158
|
+
if rawPublic == true
|
159
|
+
# 5th Sept 2022 - untested code
|
160
|
+
res[:public] = org.bouncycastle.crypto.params.X25519PublicKeyParameters.new(res[:public],0).encoded
|
161
|
+
res[:raw_public] = true
|
162
|
+
end
|
163
|
+
|
164
|
+
res
|
165
|
+
else
|
166
|
+
raise KeypairEngineException, "Unsupported storage type '#{eng}'"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def self.from_storage(bin)
|
171
|
+
case bin
|
172
|
+
when Hash
|
173
|
+
res = { }
|
174
|
+
JCEProvider.instance.add_bc_provider
|
175
|
+
|
176
|
+
kf = java.security.KeyFactory.getInstance("X25519", JCEProvider::BCProv.name)
|
177
|
+
|
178
|
+
if not_empty?(bin[:private])
|
179
|
+
# raw_private = true means the given private key is in its raw data form
|
180
|
+
# 5th Sept 22 - Not tested not sure how to generate raw key
|
181
|
+
if bin[:raw_private] == true
|
182
|
+
# 5th Sept 2022 - untested code
|
183
|
+
info = org.bouncycastle.asn1.pkcs.PrivateKeyInfo.new(org.bouncycastle.asn1.x509.AlgorithmIdentifier.new(org.bouncycastle.asn1.edec.EdECObjectIdentifiers::id_X25519), org.bouncycastle.asn1.DEROctetString.new(bin[:private]))
|
184
|
+
|
185
|
+
spec = java.security.spec.PKCS8EncodedKeySpec.new(info.encoded)
|
186
|
+
else
|
187
|
+
spec = java.security.spec.PKCS8EncodedKeySpec.new(bin[:private])
|
188
|
+
end
|
189
|
+
|
190
|
+
res[:private] = X25519PrivateKey.new(kf.generatePrivate(spec))
|
191
|
+
|
192
|
+
#res[:private] = X25519PrivateKey.new(org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters.new(bin[:private],0))
|
193
|
+
end
|
194
|
+
|
195
|
+
if not_empty?(bin[:public])
|
196
|
+
if bin[:raw_public] == true
|
197
|
+
# 5th Sept 2022 - untested code
|
198
|
+
#pubRaw = org.bouncycastle.crypto.params.Ed25519PublicKeyParameters.new(bin[:public],0).encoded
|
199
|
+
pubRaw = bin[:public]
|
200
|
+
info = org.bouncycastle.asn1.x509.SubjectPublicKeyInfo.new(org.bouncycastle.asn1.x509.AlgorithmIdentifier.new(org.bouncycastle.asn1.edec.EdECObjectIdentifiers::id_X25519), bin[:public])
|
201
|
+
|
202
|
+
spec = java.security.spec.X509EncodedKeySpec.new(info.encoded)
|
203
|
+
else
|
204
|
+
spec = java.security.spec.X509EncodedKeySpec.new(bin[:public])
|
205
|
+
end
|
206
|
+
|
207
|
+
res[:public] = X25519PublicKey.new(kf.generatePublic(spec))
|
208
|
+
end
|
209
|
+
|
210
|
+
res[:keypair] = X25519KeyBundle.new(java.security.KeyPair.new(res[:public].native_pubKey, res[:private].native_privKey)) if not_empty?(res[:public]) and not_empty?(res[:private])
|
211
|
+
|
212
|
+
res
|
213
|
+
|
214
|
+
else
|
215
|
+
raise KeypairEngineException, "No sure how to handle storage input '#{bin.class}'"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
end # X25519KeyBundle
|
220
|
+
|
221
|
+
class X25519Engine
|
222
|
+
include TR::CondUtils
|
223
|
+
include DataConversion
|
224
|
+
|
225
|
+
include TeLogger::TeLogHelper
|
226
|
+
teLogger_tag :x25519_eng_j
|
227
|
+
|
228
|
+
def self.supported_params
|
229
|
+
[]
|
230
|
+
end
|
231
|
+
|
232
|
+
def initialize(*args, &block)
|
233
|
+
@config = args.first
|
234
|
+
end
|
235
|
+
|
236
|
+
def generate_keypair(&block)
|
237
|
+
|
238
|
+
JCEProvider.instance.add_bc_provider
|
239
|
+
kg = java.security.KeyPairGenerator.getInstance("X25519", JCEProvider::BCProv.name)
|
240
|
+
kg.java_send(:initialize, [java.security.spec.AlgorithmParameterSpec], org.bouncycastle.jcajce.spec.XDHParameterSpec.new(org.bouncycastle.jcajce.spec.XDHParameterSpec::X25519))
|
241
|
+
X25519KeyBundle.new(kg.generateKeyPair)
|
242
|
+
|
243
|
+
end
|
244
|
+
|
245
|
+
|
246
|
+
end
|
247
|
+
|
248
|
+
end
|
249
|
+
end
|