ccrypto-ruby 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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