ccrypto-ruby 0.1.0 → 0.1.2

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.
@@ -11,73 +11,194 @@ module Ccrypto
11
11
 
12
12
  teLogger_tag :r_cipher_eng
13
13
 
14
+ NotAbleToFigureOutOnOpenSSLv2 = [
15
+ "aes-128-cbc-hmac-sha1",
16
+ "aes-256-cbc-hmac-sha1",
17
+ "aes-128-cbc-hmac-sha256",
18
+ "aes-256-cbc-hmac-sha256",
19
+ "aes-128-ccm",
20
+ "aes-192-ccm",
21
+ "aes-256-ccm",
22
+ "aria-128-ccm",
23
+ "aria-192-ccm",
24
+ "aria-256-ccm",
25
+ "rc4-hmac-md5"
26
+ ]
27
+
28
+ #CherryPick = [
29
+ # "aes-128-cbc", "aes-192-cbc", "aes-256-cbc",
30
+ # "aes-128-gcm", "aes-192-gcm", "aes-256-gcm",
31
+ # "aria-128-cbc","aria-192-cbc", "aria-256-cbc",
32
+ # "aria-128-gcm","aria-192-gcm", "aria-256-gcm",
33
+ # "camellia-128-cbc","camellia-192-cbc", "camellia-256-cbc",
34
+ # "camellia-128-ctr","camellia-192-ctr", "camellia-256-ctr",
35
+ # "chacha20-poly1305"
36
+ #]
37
+
14
38
  def self.supported_ciphers
15
39
  if @sCipher.nil?
16
- @sCipher = OpenSSL::Cipher.ciphers
40
+ @sCipherStr = []
41
+ @sCipher = []
42
+
43
+ OpenSSL::Cipher.ciphers.each do |c|
44
+
45
+ teLogger.debug "found cipher : #{c}"
46
+ next if c =~ /^id-\w*/
47
+ teLogger.debug "loading cipher : #{c}"
48
+
49
+ if OpenSSL::VERSION < "3.0.0" and NotAbleToFigureOutOnOpenSSLv2.include?(c)
50
+ teLogger.debug "Running on OpenSSL < v3. Skipping cipher #{c}"
51
+ next
52
+ end
53
+
54
+ begin
55
+ co = OpenSSL::Cipher.new(c)
56
+ #teLogger.debug "Algo #{c} : authenticated? #{co.authenticated?}"
57
+ #p co.methods.sort
58
+ cc = c.split("-")
59
+ @sCipherStr << c
60
+
61
+ algo = cc.first
62
+ exclusion = ["chacha20","sm4"]
63
+ # to find string like aes128, aes256 from openssl
64
+ if not exclusion.include?(algo) and (algo =~ /[0-9]/) != nil
65
+ # match the one before the numbers
66
+ algo = $`
67
+ end
68
+
69
+ native = { algo_str: c }
70
+ keysize = co.key_len*8
71
+ opts = { keysize: keysize, ivLength: co.iv_len, authMode: co.authenticated? }
72
+
73
+ if c.downcase =~ /\w*(gcm|ecb|cbc|cfb|cfb1|cfb8|ofb|ctr|ccm|xts|wrap|poly1305)/
74
+ teLogger.debug "Mode extraction : #{$&} / #{$'}"
75
+ # after the match
76
+ if not_empty?($')
77
+ opts[:mode] = "#{$&}#{$'}"
78
+ else
79
+ # the match
80
+ opts[:mode] = $&.downcase
81
+ end
82
+ else
83
+ # no mode defined. Seems defaulted to cbc according to document
84
+ if co.authenticated?
85
+ opts[:mode] = "gcm"
86
+ else
87
+ opts[:mode] = "cbc"
88
+ end
89
+ end
90
+
91
+ teLogger.debug "Mode : #{opts[:mode]}"
92
+ if opts[:mode] == :xts.to_s
93
+ opts[:min_input_length] = 16
94
+ elsif opts[:mode] == "cbc-hmac-sha1"
95
+ opts[:min_input_length] = 16
96
+ opts[:mandatory_block_size] = 16
97
+ elsif opts[:mode] == "cbc-hmac-sha256"
98
+ opts[:min_input_length] = 32
99
+ opts[:mandatory_block_size] = 32
100
+ elsif opts[:mode] == "wrap"
101
+ case algo
102
+ when "aes"
103
+ case keysize
104
+ when 128
105
+ opts[:min_input_length] = 16
106
+ opts[:mandatory_block_size] = 8
107
+ when 192
108
+ opts[:min_input_length] = 24
109
+ opts[:mandatory_block_size] = 8
110
+ when 256
111
+ opts[:min_input_length] = 32
112
+ opts[:mandatory_block_size] = 8
113
+ end
114
+ when "des3", "des"
115
+ opts[:min_input_length] = 8
116
+ opts[:mandatory_block_size] = 8
117
+ end
118
+ end
119
+
120
+ conf = Ccrypto::CipherConfig.new(algo, opts)
121
+ conf.native_config = native
122
+
123
+ Ccrypto::SupportedCipherList.instance.register(conf)
124
+
125
+ @sCipher << conf
126
+ rescue OpenSSL::Cipher::CipherError => ex
127
+ teLogger.debug "Algo '#{c}' hit error : #{ex.message}"
128
+ end
129
+ end
17
130
  end
18
131
 
19
132
  @sCipher
20
133
 
21
134
  end
22
135
 
136
+ def self.get_cipher(algo, keysize = nil, mode = nil)
137
+ supported_ciphers if Ccrypto::SupportedCipherList.instance.algo_count == 0
138
+
139
+ if is_empty?(algo)
140
+ []
141
+ elsif is_empty?(keysize) and is_empty?(mode)
142
+ teLogger.debug "get_cipher algo #{algo} only"
143
+ Ccrypto::SupportedCipherList.instance.find_algo(algo)
144
+ elsif is_empty?(mode) and not_empty?(keysize)
145
+ teLogger.debug "get_cipher algo #{algo} keysize #{keysize}"
146
+ Ccrypto::SupportedCipherList.instance.find_algo_keysize(algo, keysize)
147
+ elsif not_empty?(mode) and is_empty?(keysize)
148
+ teLogger.debug "get_cipher algo #{algo} mode #{mode}"
149
+ Ccrypto::SupportedCipherList.instance.find_algo_mode(algo, mode)
150
+ elsif not_empty?(keysize) and not_empty?(mode)
151
+ teLogger.debug "get_cipher #{algo}/#{keysize}/#{mode}"
152
+ Ccrypto::SupportedCipherList.instance.find_algo_keysize_mode(algo, keysize, mode)
153
+ end
154
+ end
155
+ class << self
156
+ alias_method :get_cipher_config, :get_cipher
157
+ end
158
+
159
+ def self.supported_cipher_list
160
+ supported_ciphers if Ccrypto::SupportedCipherList.instance.algo_count == 0
161
+ Ccrypto::SupportedCipherList.instance
162
+ end
163
+
23
164
  def self.is_supported_cipher?(c)
24
165
  case c
25
166
  when String
26
- supported_ciphers.include?(c)
27
- when Hash
28
- spec = to_openssl_spec(c)
29
- begin
30
- OpenSSL::Cipher.new(spec)
31
- true
32
- rescue Exception => ex
167
+ supported_ciphers if @sCipherStr.nil?
168
+
169
+ if not @sCipherStr.nil?
170
+ @sCipherStr.include?(C)
171
+ else
33
172
  false
34
173
  end
174
+ when Ccrypto::CipherConfig
175
+ @sCipher.include?(c)
35
176
  else
36
177
  raise Ccrypto::CipherEngineException, "Unsupported input #{c} to check supported cipher"
37
178
  end
38
179
  end
39
180
 
40
181
  def self.to_openssl_spec(spec)
41
- res = []
42
182
 
43
- teLogger.debug "to_openssl_spec #{spec}"
44
- case spec.algo
45
- when :blowfish
46
- res << "bf"
183
+ case spec
184
+ when Ccrypto::CipherConfig
185
+ spec.native_config[:algo_str]
186
+ #@sCipher[spec]
47
187
  else
48
- res << spec.algo
188
+ raise Ccrypto::Error, "Unknown spec #{spec.inspect}"
49
189
  end
50
190
 
51
- res << spec.keysize if not_empty?(spec.keysize) and spec.keysize.to_i > 0 and not spec.is_algo?(:chacha20) and not spec.is_algo?(:seed) and not spec.is_algo?(:sm4) and not spec.is_algo?(:blowfish)
52
-
53
- res << spec.mode
54
-
55
- teLogger.debug "to_openssl_spec #{res}"
56
-
57
- res.join("-")
58
-
59
- end
191
+ end # self.to_openssl_spec(spec)
60
192
 
61
193
  def initialize(*args, &block)
194
+
62
195
  @spec = args.first
63
196
 
64
- #teLogger = TteLogger.new
65
- teLogger.debug "Cipher spec : #{@spec}"
197
+ raise Ccrypto::CipherEngineException, "Not supported cipher spec #{@spec.class}" if not @spec.is_a?(Ccrypto::CipherConfig)
66
198
 
67
- begin
68
- case @spec
69
- #when String
70
- # @cipher = OpenSSL::Cipher.new(@spec)
71
- when Ccrypto::CipherEngineConfig
72
- @cipher = OpenSSL::Cipher.new(@spec.provider_config)
73
- when Ccrypto::DirectCipherConfig
74
- @cipher = OpenSSL::Cipher.new(self.class.to_openssl_spec(@spec))
75
- else
76
- raise Ccrypto::CipherEngineException, "Not supported cipher init type #{@spec.class}"
77
- end
78
- rescue OpenSSL::Cipher::CipherError, RuntimeError => ex
79
- raise Ccrypto::CipherEngineException, ex
80
- end
199
+ teLogger.debug "Cipher spec : #{@spec} (Native algo : #{@spec.native_config[:algo_str]})"
200
+
201
+ @cipher = OpenSSL::Cipher.new(@spec.native_config[:algo_str])
81
202
 
82
203
  case @spec.cipherOps
83
204
  when :encrypt, :enc
@@ -94,11 +215,11 @@ module Ccrypto
94
215
  if @spec.has_iv?
95
216
  teLogger.debug "IV from spec"
96
217
  @cipher.iv = @spec.iv
97
- teLogger.debug "IV : #{to_hex(@spec.iv)}"
218
+ teLogger.debug "IV : #{to_hex(@spec.iv)} / #{@spec.iv.length}"
98
219
  else
99
220
  teLogger.debug "Generate random IV"
100
221
  @spec.iv = @cipher.random_iv
101
- teLogger.debug "IV : #{to_hex(@spec.iv)}"
222
+ teLogger.debug "IV : #{to_hex(@spec.iv)} / #{@spec.iv.length}"
102
223
  end
103
224
 
104
225
 
@@ -118,25 +239,50 @@ module Ccrypto
118
239
  end
119
240
 
120
241
 
121
- if @spec.is_mode?(:gcm)
122
-
123
- if not_empty?(@spec.auth_data)
124
- teLogger.debug "Setting auth data"
242
+ if @spec.is_mode?(:ccm)
243
+ #if not_empty?(@spec.auth_data)
244
+ if @spec.is_encrypt_cipher_mode?
245
+ teLogger.debug "Setting ccm plaintext data length (ccm mode) [#{@spec.plaintext_length}]"
246
+ @cipher.ccm_data_len = @spec.plaintext_length
247
+ teLogger.debug "Setting auth data (ccm mode)"
248
+ @cipher.auth_data = @spec.auth_data.nil? ? "" : @spec.auth_data
249
+ teLogger.debug "Setting auth tag len (ccm mode)"
250
+ @cipher.auth_tag_len = 12
251
+ elsif @spec.is_decrypt_cipher_mode?
252
+ teLogger.debug "Setting ccm cipher data length (ccm mode) #{@spec.ciphertext_length}"
253
+ @cipher.ccm_data_len = @spec.ciphertext_length
254
+ teLogger.debug "Setting auth data (ccm mode)"
255
+ @cipher.auth_data = @spec.auth_data.nil? ? "" : @spec.auth_data
256
+ teLogger.debug "Setting auth tag (ccm mode)"
257
+ @cipher.auth_tag = @spec.auth_tag
258
+ end
259
+ #end
260
+
261
+
262
+ elsif @spec.is_auth_mode_cipher?
263
+
264
+ if not_empty?(@spec.auth_data) and not ((@spec.is_mode?("cbc-hmac-sha1") or @spec.is_mode?("cbc-hmac-sha256")))
265
+ teLogger.debug "Setting auth data (generic mode)"
125
266
  @cipher.auth_data = @spec.auth_data
126
- end
127
267
 
128
- if not_empty?(@spec.auth_tag)
129
- raise CipherEngineException, "Tag length of 16 bytes is expected" if @spec.auth_tag.bytesize != 16
130
- teLogger.debug "Setting auth tag"
131
- @cipher.auth_tag = @spec.auth_tag
268
+ if @spec.is_decrypt_cipher_mode?
269
+ teLogger.debug "Setting auth tag (generic mode)"
270
+ raise CipherEngineException, "Tag length of 16 bytes is expected" if @spec.auth_tag.bytesize != 16 and @spec.is_mode?(:gcm)
271
+ @cipher.auth_tag = @spec.auth_tag
272
+ end
132
273
  end
133
274
 
134
275
  end
135
276
 
136
- end
277
+
278
+ end # initialize
137
279
 
138
280
  def update(val)
139
- @cipher.update(val)
281
+ if not_empty?(val)
282
+ res = @cipher.update(val)
283
+ teLogger.debug "(update) Written #{val.length} bytes"
284
+ res
285
+ end
140
286
  end
141
287
 
142
288
  def final(val = nil)
@@ -145,17 +291,22 @@ module Ccrypto
145
291
  begin
146
292
 
147
293
  if not_empty?(val)
148
- res << @cipher.update(val)
294
+ teLogger.debug "(final) Written #{val.length} bytes"
295
+ res << @cipher.update(val)
149
296
  end
150
297
 
151
298
  res << @cipher.final
299
+ teLogger.debug "(final) cipher finalized"
152
300
 
153
301
  rescue Exception => ex
302
+ teLogger.error self
303
+ teLogger.error ex.backtrace.join("\n")
154
304
  raise CipherEngineException, ex
155
305
  end
156
306
 
157
- if @spec.is_mode?(:gcm) and @spec.is_encrypt_cipher_mode?
158
- @spec.auth_tag = @cipher.auth_tag
307
+ #if @spec.is_mode?(:gcm)
308
+ if @spec.is_auth_mode_cipher? and @spec.is_encrypt_cipher_mode?
309
+ @spec.auth_tag = @cipher.auth_tag
159
310
  end
160
311
 
161
312
  res.join
@@ -165,6 +316,14 @@ module Ccrypto
165
316
  @cipher.reset
166
317
  end
167
318
 
319
+ def method_missing(mtd, *args, &block)
320
+ if not @cipher.nil?
321
+ @cipher.send(mtd, *args, &block)
322
+ else
323
+ super
324
+ end
325
+ end
326
+
168
327
  end
169
328
  end
170
329
  end
@@ -27,9 +27,10 @@ module Ccrypto
27
27
  Ccrypto::SHAKE256.provider_info("shake256"),
28
28
  Ccrypto::BLAKE2b512.provider_info("BLAKE2b512"),
29
29
  Ccrypto::BLAKE2s256.provider_info("BLAKE2s256"),
30
- Ccrypto::SM3.provider_info("SM3"),
31
- Ccrypto::RIPEMD160.provider_info("RIPEMD160"),
32
- Ccrypto::WHIRLPOOL.provider_info("whirlpool")
30
+ Ccrypto::SM3.provider_info("SM3")
31
+ # deprecated starting OpenSSL v3.0
32
+ #Ccrypto::RIPEMD160.provider_info("RIPEMD160"),
33
+ #Ccrypto::WHIRLPOOL.provider_info("whirlpool")
33
34
  ]
34
35
 
35
36
 
@@ -38,14 +39,21 @@ module Ccrypto
38
39
  end
39
40
 
40
41
  def self.is_supported?(eng)
41
- res = supported.include?(eng)
42
- begin
43
- res = digest(eng) if not res
44
- rescue DigestEngineException => ex
45
- res = false
42
+
43
+ case eng
44
+ when Ccrypto::DigestConfig
45
+ SupportedDigest.include?(eng)
46
+ when String, Symbol
47
+ if eng.is_a?(Symbol)
48
+ engineKeys.include?(eng)
49
+ else
50
+ e = eng.gsub("-","_")
51
+ engineKeys.include?(e.to_sym)
52
+ end
53
+ else
54
+ raise DigestEngineException, "Unknown engine '#{eng}'"
46
55
  end
47
56
 
48
- res
49
57
  end
50
58
 
51
59
  def self.instance(*args, &block)
@@ -59,16 +67,30 @@ module Ccrypto
59
67
  end
60
68
 
61
69
  def self.digest(key)
62
-
63
- res = engineKeys[key]
64
- if is_empty?(res)
65
- teLogger.debug "No digest available for #{key}"
66
- raise DigestEngineException, "Not supported digest engine #{key}"
70
+
71
+ case key
72
+ when Ccrypto::DigestConfig
73
+ DigestEngine.new(OpenSSL::Digest.new(key.provider_config))
74
+ when String, Symbol
75
+ if key.is_a?(Symbol)
76
+ res = engineKeys[key]
77
+ else
78
+ k = key.gsub("-","_")
79
+ res = engineKeys[k.to_sym]
80
+ end
81
+
82
+ if is_empty?(res)
83
+ teLogger.debug "No digest available for #{key}"
84
+ raise DigestEngineException, "Not supported digest engine #{key}"
85
+ else
86
+ teLogger.debug "Found digest #{key.to_sym}"
87
+ DigestEngine.new(OpenSSL::Digest.new(res.provider_config))
88
+ end
89
+
67
90
  else
68
- teLogger.debug "Found digest #{key.to_sym}"
69
- DigestEngine.new(OpenSSL::Digest.new(res.provider_config))
91
+ raise DigestEngineException, "Not supported digest engine #{key}"
70
92
  end
71
-
93
+
72
94
  end
73
95
 
74
96
  def self.engineKeys
@@ -1,5 +1,7 @@
1
1
 
2
2
  require 'openssl'
3
+ if OpenSSL::VERSION < "3.0.0"
4
+
3
5
  module PKeyPatch
4
6
  def to_pem; public_key.to_pem end
5
7
  def to_der; public_key.to_der end
@@ -13,20 +15,51 @@ module PKeyPatch
13
15
  end
14
16
  OpenSSL::PKey::EC::Point.prepend PKeyPatch
15
17
 
18
+ end
19
+
16
20
  require_relative '../keybundle_store/pkcs12'
17
21
  require_relative '../keybundle_store/pem_store'
22
+ require_relative '../ecc_const'
18
23
 
19
24
  module Ccrypto
20
25
  module Ruby
21
26
 
22
27
  class ECCPublicKey < Ccrypto::ECCPublicKey
23
-
28
+
24
29
  def to_bin
25
- @native_pubKey.to_der
30
+ if OpenSSL::VERSION < "3.0.0"
31
+ @native_pubKey.to_der
32
+ else
33
+ const = ECCConst[@native_pubKey.group.curve_name]
34
+ # At 01 April 2023
35
+ # at Ruby 3.2.1/OpenSSL gem 3.1.0/OpenSSL 3.0.2
36
+ # The gem has bug that the encoding is incorrect
37
+ OpenSSL::ASN1::Sequence.new([
38
+ OpenSSL::ASN1::ObjectId.new("2.8.8.128.0"),
39
+ OpenSSL::ASN1::Integer.new(0x0100),
40
+ OpenSSL::ASN1::Integer.new(const),
41
+ OpenSSL::ASN1::BitString.new(@native_pubKey.to_bn)
42
+ ]).to_der
43
+ end
26
44
  end
27
45
 
28
46
  def self.to_key(bin)
29
- ek = OpenSSL::PKey::EC.new(bin)
47
+ if OpenSSL::VERSION > "3.0.0"
48
+ ek = OpenSSL::PKey::EC.new(bin)
49
+ else
50
+ seq = OpenSSL::ASN1Object.decode(bin).value
51
+ envp = ASN1Object.decode(seq[0]).value
52
+ raise KeypairEngineException, "Not ECC public key" if envp != "2.8.8.8.128.0"
53
+ ver = ASN1Object.decode(seq[1]).value
54
+ raise KeypairEngineException, "Unsupported version" if ver != 0x0100
55
+ cv = ASN1Object.decode(seq[2]).value
56
+ curve = ECCConst.invert[cv]
57
+ raise KeypairEngineException, "Unknown curve '#{curve}'" if curve.nil?
58
+ kv = ASN1Object.decode(seq[3]).value
59
+
60
+ ek = OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC::Group.new(curve), kv)
61
+ end
62
+
30
63
  ECCPublicKey.new(ek)
31
64
  end
32
65
 
@@ -49,7 +82,11 @@ module Ccrypto
49
82
 
50
83
  def public_key
51
84
  if @pubKey.nil?
52
- @pubKey = ECCPublicKey.new(@nativeKeypair.public_key)
85
+ #if OpenSSL::VERSION < "3.0.0"
86
+ @pubKey = ECCPublicKey.new(@nativeKeypair.public_key)
87
+ #else
88
+ # @pubKey = ECCPublicKey.new(@nativeKeypair.public_key.to_bn)
89
+ #end
53
90
  end
54
91
  @pubKey
55
92
  end
@@ -65,12 +102,21 @@ module Ccrypto
65
102
  tkey = pubKey
66
103
  when Ccrypto::ECCPublicKey
67
104
  tkey = pubKey.native_pubKey
68
- tkey = tkey.public_key if not tkey.is_a?(OpenSSL::PKey::EC::Point)
105
+ if OpenSSL::VERSION < "3.0.0"
106
+ tkey = tkey.public_key if not tkey.is_a?(OpenSSL::PKey::EC::Point)
107
+ else
108
+ tkey = OpenSSL::PKey::EC.new(tkey)
109
+ end
69
110
  else
70
111
  raise KeypairEngineException, "Unknown public key type #{pubKey.class}"
71
112
  end
72
113
 
73
- raise KeypairEngineException, "OpenSSL::PKey::EC::Point is required. Given #{tkey.inspect}" if not tkey.is_a?(OpenSSL::PKey::EC::Point)
114
+ if OpenSSL::VERSION < "3.0.0"
115
+ raise KeypairEngineException, "OpenSSL::PKey::EC::Point is required. Given #{tkey.inspect}" if not tkey.is_a?(OpenSSL::PKey::EC::Point)
116
+ else
117
+ raise KeypairEngineException, "OpenSSL::PKey::EC is required. Given #{tkey.inspect}" if not tkey.is_a?(OpenSSL::PKey::EC)
118
+ end
119
+
74
120
  @nativeKeypair.dh_compute_key(tkey)
75
121
  end
76
122
 
@@ -171,9 +217,24 @@ module Ccrypto
171
217
 
172
218
  teLogger_tag :r_ecc
173
219
 
220
+ NotAbleToFigureOutOnOpenSSLv2 = [
221
+ "Oakley-EC2N-3",
222
+ "Oakley-EC2N-4"
223
+ ]
224
+
174
225
  def self.supported_curves
175
226
  if @curves.nil?
176
- @curves = OpenSSL::PKey::EC.builtin_curves.map { |c| Ccrypto::ECCConfig.new(c[0]) }
227
+ @curves = []
228
+ OpenSSL::PKey::EC.builtin_curves.sort.map { |c|
229
+
230
+ next if c[0] =~ /^wap/ or NotAbleToFigureOutOnOpenSSLv2.include?(c[0])
231
+
232
+ if c[0] == "prime256v1"
233
+ @curves << Ccrypto::ECCConfig.new(c[0], Ccrypto::KeypairConfig::Algo_Active, true)
234
+ else
235
+ @curves << Ccrypto::ECCConfig.new(c[0])
236
+ end
237
+ }
177
238
  end
178
239
  @curves
179
240
  end
@@ -203,14 +264,28 @@ module Ccrypto
203
264
  end
204
265
 
205
266
  def self.verify(pubKey, val, sign)
206
- uPubKey = pubKey.native_pubKey
207
- if pubKey.native_pubKey.is_a?(OpenSSL::PKey::EC::Point)
208
- uPubKey = OpenSSL::PKey::EC.new(uPubKey.group)
209
- uPubKey.public_key = pubKey.native_pubKey
210
- end
267
+ if OpenSSL::VERSION > "3.0.0"
268
+ p pubKey.native_pubKey
269
+ p pubKey.native_pubKey.methods.sort
270
+ uPubKey = pubKey.native_pubKey
271
+ if uPubKey.is_a?(OpenSSL::PKey::EC::Point)
272
+ res = uPubKey.dsa_verify_asn1(val, sign)
273
+ res
274
+ else
275
+ raise KeypairEngineException, "Unsupported public key type '#{uPubKey.class}'"
276
+ end
211
277
 
212
- res = uPubKey.dsa_verify_asn1(val, sign)
213
- res
278
+ else
279
+ # OpenSSL v2 - Ruby 2.x
280
+ uPubKey = pubKey.native_pubKey
281
+ if pubKey.native_pubKey.is_a?(OpenSSL::PKey::EC::Point)
282
+ uPubKey = OpenSSL::PKey::EC.new(uPubKey.group)
283
+ uPubKey.public_key = pubKey.native_pubKey
284
+ end
285
+
286
+ res = uPubKey.dsa_verify_asn1(val, sign)
287
+ res
288
+ end
214
289
  end
215
290
 
216
291
  end
@@ -0,0 +1,84 @@
1
+
2
+ require 'ed25519'
3
+
4
+ module Ccrypto
5
+ module Ruby
6
+
7
+ class ED25519Exception < StandardError; end
8
+
9
+ class ED25519PublicKey < Ccrypto::ED25519PublicKey
10
+
11
+ end
12
+
13
+ class ED25519KeyBundle
14
+ include Ccrypto::ED25519KeyBundle
15
+
16
+ include TR::CondUtils
17
+
18
+ include TeLogger::TeLogHelper
19
+ teLogger_tag :ed25519_kb
20
+
21
+ def initialize(kp)
22
+ @nativeKeypair = kp
23
+ end
24
+
25
+ def public_key
26
+ if @pubKey.nil?
27
+ @pubKey = ED25519PublicKey.new(@nativeKeypair.verify_key)
28
+ end
29
+ @pubKey
30
+ end
31
+
32
+ def private_key
33
+ ED25519PrivateKey.new(@nativeKeypair)
34
+ end
35
+
36
+ end # ED25519KeyBundle
37
+
38
+ class ED25519Engine
39
+ include TeLogger::TeLogHelper
40
+ teLogger_tag :ed25519_eng
41
+
42
+ def initialize(*args, &block)
43
+ @config = args.first
44
+ teLogger.debug "Config : #{@config}"
45
+ end
46
+
47
+ def generate_keypair(&block)
48
+ teLogger.debug "Generating ED25519 keypair"
49
+ ED25519KeyBundle.new(Ed25519::SigningKey.generate)
50
+ end
51
+
52
+ def sign(val)
53
+
54
+ raise KeypairEngineException, "Keypair is required" if @config.keypair.nil?
55
+ raise KeypairEngineException, "ED25519 keypair is required" if not @config.keypair.is_a?(ED25519KeyBundle)
56
+
57
+ kp = @config.keypair
58
+
59
+ res = kp.nativeKeypair.sign(val)
60
+ teLogger.debug "Data of length #{val.length} signed using ED25519"
61
+
62
+ res
63
+
64
+ end
65
+
66
+ def self.verify(pubKey, val, sign)
67
+ case pubKey
68
+ when Ccrypto::ED25519PublicKey
69
+ uPubKey = pubKey
70
+ else
71
+ raise KeypairEngineException, "Unsupported public key '#{pubKey.class}' for ED25519 operation"
72
+ end
73
+
74
+ begin
75
+ uPubKey.verify(sign, val)
76
+ rescue Ed25519::VerifyError => ex
77
+ false
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end
@@ -136,6 +136,7 @@ module Ccrypto
136
136
 
137
137
  cipher = "AES-256-CBC" if is_empty?(cipher)
138
138
 
139
+ teLogger.debug "Setting P7 encryption cipher #{cipher}"
139
140
  cip = OpenSSL::Cipher.new(cipher)
140
141
 
141
142
  begin