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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.java-version +1 -1
  3. data/.release_history.yml +4 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +1 -1
  6. data/Gemfile.lock +68 -53
  7. data/Rakefile +2 -1
  8. data/bin/console +14 -0
  9. data/jars/bcjmail-jdk18on-172.jar +0 -0
  10. data/jars/bcmail-jdk18on-172.jar +0 -0
  11. data/jars/bcpg-jdk18on-172.1.jar +0 -0
  12. data/jars/bcpkix-jdk18on-172.jar +0 -0
  13. data/jars/bcprov-ext-jdk18on-172.jar +0 -0
  14. data/jars/bcprov-jdk18on-172.jar +0 -0
  15. data/jars/bctls-jdk18on-172.jar +0 -0
  16. data/jars/bcutil-jdk18on-172.jar +0 -0
  17. data/lib/ccrypto/java/bc_const_mapping.rb +42 -0
  18. data/lib/ccrypto/java/data_conversion.rb +23 -2
  19. data/lib/ccrypto/java/engines/argon2_engine.rb +95 -0
  20. data/lib/ccrypto/java/engines/asn1_engine.rb +2 -1
  21. data/lib/ccrypto/java/engines/bcrypt_engine.rb +56 -0
  22. data/lib/ccrypto/java/engines/cipher_engine.rb +462 -130
  23. data/lib/ccrypto/java/engines/compression_engine.rb +7 -28
  24. data/lib/ccrypto/java/engines/crystal_dilithium_engine.rb +226 -0
  25. data/lib/ccrypto/java/engines/crystal_kyber_engine.rb +260 -0
  26. data/lib/ccrypto/java/engines/decompression_engine.rb +5 -4
  27. data/lib/ccrypto/java/engines/digest_engine.rb +221 -139
  28. data/lib/ccrypto/java/engines/ecc_engine.rb +249 -96
  29. data/lib/ccrypto/java/engines/ed25519_engine.rb +211 -0
  30. data/lib/ccrypto/java/engines/hkdf_engine.rb +82 -23
  31. data/lib/ccrypto/java/engines/hmac_engine.rb +98 -23
  32. data/lib/ccrypto/java/engines/pbkdf2_engine.rb +82 -33
  33. data/lib/ccrypto/java/engines/pkcs7_engine.rb +44 -33
  34. data/lib/ccrypto/java/engines/rsa_engine.rb +85 -31
  35. data/lib/ccrypto/java/engines/scrypt_engine.rb +12 -3
  36. data/lib/ccrypto/java/engines/secret_key_engine.rb +77 -12
  37. data/lib/ccrypto/java/engines/secret_sharing_engine.rb +17 -2
  38. data/lib/ccrypto/java/engines/x25519_engine.rb +249 -0
  39. data/lib/ccrypto/java/engines/x509_csr_engine.rb +141 -0
  40. data/lib/ccrypto/java/engines/x509_engine.rb +365 -71
  41. data/lib/ccrypto/java/ext/secret_key.rb +37 -25
  42. data/lib/ccrypto/java/ext/x509_cert.rb +429 -5
  43. data/lib/ccrypto/java/ext/x509_csr.rb +151 -0
  44. data/lib/ccrypto/java/jce_provider.rb +0 -11
  45. data/lib/ccrypto/java/keystore/jce_keystore.rb +205 -0
  46. data/lib/ccrypto/java/keystore/jks_keystore.rb +52 -0
  47. data/lib/ccrypto/java/keystore/keystore.rb +97 -0
  48. data/lib/ccrypto/java/keystore/pem_keystore.rb +147 -0
  49. data/lib/ccrypto/java/keystore/pkcs12_keystore.rb +56 -0
  50. data/lib/ccrypto/java/utils/comparator.rb +25 -2
  51. data/lib/ccrypto/java/version.rb +1 -1
  52. data/lib/ccrypto/java.rb +46 -0
  53. data/lib/ccrypto/provider.rb +139 -3
  54. metadata +40 -24
  55. data/ccrypto-java.gemspec +0 -44
  56. data/jars/bcmail-jdk15on-165.jar +0 -0
  57. data/jars/bcpg-jdk15on-165.jar +0 -0
  58. data/jars/bcpkix-jdk15on-165.jar +0 -0
  59. data/jars/bcprov-ext-jdk15on-165.jar +0 -0
  60. data/jars/bcprov-jdk15on-165.jar +0 -0
  61. data/jars/bctls-jdk15on-165.jar +0 -0
  62. 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 to_storage(type, &block)
56
-
57
- case type
58
- when :p12, :pkcs12
59
- to_pkcs12 do |key|
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
- to_pkcs12 do |key|
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
- 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
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
- @nativeKeypair.encoded == kp.private.encoded
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").random_bytes(@config.salt)
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.blockSize, @config.parallel, @config.outBitLength/8)
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
- include TeLogger::TeLogHelper
8
- teLogger_tag :j_secretkey
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
- teLogger.debug "KeyGen using algo #{config.algo.to_s} with null provider"
22
- keyGen = javax.crypto.KeyGenerator.getInstance(config.algo.to_s)
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
- 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)
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
- teLogger.debug "Init KeyGen with keysize #{config.keysize.to_i}"
80
+ logger.debug "Init KeyGen with keysize #{config.keysize.to_i}"
30
81
  keyGen.init(config.keysize.to_i)
31
82
  else
32
- teLogger.debug "Init KeyGen with keysize #{config.keysize.to_i} with provider #{ranProv.is_a?(String) ? ranProv : ranProv.name}"
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
- teLogger.debug "Secret key #{config} generated"
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
- 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
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