ccrypto-ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/Gemfile +12 -0
  4. data/Gemfile.lock +64 -0
  5. data/README.md +149 -0
  6. data/Rakefile +10 -0
  7. data/bin/console +15 -0
  8. data/bin/setup +8 -0
  9. data/ccrypto-ruby.gemspec +45 -0
  10. data/lib/ccrypto/provider.rb +175 -0
  11. data/lib/ccrypto/ruby/data_conversion.rb +68 -0
  12. data/lib/ccrypto/ruby/engines/asn1_engine.rb +110 -0
  13. data/lib/ccrypto/ruby/engines/asn1_object.rb +19 -0
  14. data/lib/ccrypto/ruby/engines/cipher_engine.rb +170 -0
  15. data/lib/ccrypto/ruby/engines/compression_engine.rb +61 -0
  16. data/lib/ccrypto/ruby/engines/data_conversion_engine.rb +9 -0
  17. data/lib/ccrypto/ruby/engines/decompression_engine.rb +70 -0
  18. data/lib/ccrypto/ruby/engines/digest_engine.rb +127 -0
  19. data/lib/ccrypto/ruby/engines/ecc_engine.rb +218 -0
  20. data/lib/ccrypto/ruby/engines/hkdf_engine.rb +54 -0
  21. data/lib/ccrypto/ruby/engines/hmac_engine.rb +53 -0
  22. data/lib/ccrypto/ruby/engines/pbkdf2_engine.rb +69 -0
  23. data/lib/ccrypto/ruby/engines/pkcs7_engine.rb +179 -0
  24. data/lib/ccrypto/ruby/engines/rsa_engine.rb +300 -0
  25. data/lib/ccrypto/ruby/engines/scrypt_engine.rb +34 -0
  26. data/lib/ccrypto/ruby/engines/secret_key_engine.rb +18 -0
  27. data/lib/ccrypto/ruby/engines/secret_sharing_engine.rb +331 -0
  28. data/lib/ccrypto/ruby/engines/secure_random_engine.rb +34 -0
  29. data/lib/ccrypto/ruby/engines/x509_engine.rb +213 -0
  30. data/lib/ccrypto/ruby/ext/secret_key.rb +24 -0
  31. data/lib/ccrypto/ruby/ext/x509_cert.rb +24 -0
  32. data/lib/ccrypto/ruby/keybundle_store/pem_store.rb +73 -0
  33. data/lib/ccrypto/ruby/keybundle_store/pkcs12.rb +111 -0
  34. data/lib/ccrypto/ruby/utils/comparator.rb +15 -0
  35. data/lib/ccrypto/ruby/utils/memory_buffer.rb +63 -0
  36. data/lib/ccrypto/ruby/utils/native_helper.rb +17 -0
  37. data/lib/ccrypto/ruby/version.rb +7 -0
  38. data/lib/ccrypto/ruby.rb +25 -0
  39. metadata +136 -0
@@ -0,0 +1,170 @@
1
+
2
+ require_relative '../data_conversion'
3
+
4
+ module Ccrypto
5
+ module Ruby
6
+ class CipherEngine
7
+ include TR::CondUtils
8
+ include DataConversion
9
+
10
+ include TeLogger::TeLogHelper
11
+
12
+ teLogger_tag :r_cipher_eng
13
+
14
+ def self.supported_ciphers
15
+ if @sCipher.nil?
16
+ @sCipher = OpenSSL::Cipher.ciphers
17
+ end
18
+
19
+ @sCipher
20
+
21
+ end
22
+
23
+ def self.is_supported_cipher?(c)
24
+ case c
25
+ 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
33
+ false
34
+ end
35
+ else
36
+ raise Ccrypto::CipherEngineException, "Unsupported input #{c} to check supported cipher"
37
+ end
38
+ end
39
+
40
+ def self.to_openssl_spec(spec)
41
+ res = []
42
+
43
+ teLogger.debug "to_openssl_spec #{spec}"
44
+ case spec.algo
45
+ when :blowfish
46
+ res << "bf"
47
+ else
48
+ res << spec.algo
49
+ end
50
+
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
60
+
61
+ def initialize(*args, &block)
62
+ @spec = args.first
63
+
64
+ #teLogger = TteLogger.new
65
+ teLogger.debug "Cipher spec : #{@spec}"
66
+
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
81
+
82
+ case @spec.cipherOps
83
+ when :encrypt, :enc
84
+ teLogger.debug "Operation encrypt"
85
+ @cipher.encrypt
86
+ when :decrypt, :dec
87
+ teLogger.debug "Operation decrypt"
88
+ @cipher.decrypt
89
+ else
90
+ raise Ccrypto::CipherEngineException, "Cipher operation (encrypt/decrypt) must be given"
91
+ end
92
+
93
+
94
+ if @spec.has_iv?
95
+ teLogger.debug "IV from spec"
96
+ @cipher.iv = @spec.iv
97
+ teLogger.debug "IV : #{to_hex(@spec.iv)}"
98
+ else
99
+ teLogger.debug "Generate random IV"
100
+ @spec.iv = @cipher.random_iv
101
+ teLogger.debug "IV : #{to_hex(@spec.iv)}"
102
+ end
103
+
104
+
105
+ if @spec.has_key?
106
+ teLogger.debug "Key from spec"
107
+ case @spec.key
108
+ when Ccrypto::SecretKey
109
+ @cipher.key = @spec.key.to_bin
110
+ when String
111
+ @cipher.key = @spec.key
112
+ else
113
+ raise Ccrypto::CipherEngineException, "Unknown key type for processing #{@spec.key}"
114
+ end
115
+ else
116
+ teLogger.debug "Generate random Key"
117
+ @spec.key = @cipher.random_key
118
+ end
119
+
120
+
121
+ if @spec.is_mode?(:gcm)
122
+
123
+ if not_empty?(@spec.auth_data)
124
+ teLogger.debug "Setting auth data"
125
+ @cipher.auth_data = @spec.auth_data
126
+ end
127
+
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
132
+ end
133
+
134
+ end
135
+
136
+ end
137
+
138
+ def update(val)
139
+ @cipher.update(val)
140
+ end
141
+
142
+ def final(val = nil)
143
+ res = []
144
+
145
+ begin
146
+
147
+ if not_empty?(val)
148
+ res << @cipher.update(val)
149
+ end
150
+
151
+ res << @cipher.final
152
+
153
+ rescue Exception => ex
154
+ raise CipherEngineException, ex
155
+ end
156
+
157
+ if @spec.is_mode?(:gcm) and @spec.is_encrypt_cipher_mode?
158
+ @spec.auth_tag = @cipher.auth_tag
159
+ end
160
+
161
+ res.join
162
+ end
163
+
164
+ def reset
165
+ @cipher.reset
166
+ end
167
+
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,61 @@
1
+
2
+
3
+ module Ccrypto
4
+ module Ruby
5
+ class Compression
6
+
7
+ include TeLogger::TeLogHelper
8
+
9
+ teLogger_tag :r_compression
10
+
11
+ def initialize(*args, &block)
12
+
13
+ @config = args.first
14
+ raise CompressionError, "Compress Config is expected. Given #{@config}" if not @config.is_a?(Ccrypto::CompressionConfig)
15
+
16
+ if block
17
+
18
+ outPath = block.call(:out_path)
19
+ if is_empty?(outPath)
20
+ outFile = block.call(:out_file)
21
+ raise CompressionError, "Given out_file required to support write() call" if not outFile.respond_to?(:write)
22
+ @out = outFile
23
+ else
24
+ @out = Tempfile.new(SecureRandom.hex(24))
25
+ end
26
+
27
+ @intBufSize = block.call(:int_buf_size) || 102400
28
+
29
+ else
30
+ @intBufSize = 102400
31
+
32
+ end
33
+
34
+ case @config.level
35
+ when :best_compression
36
+ teLogger.debug "Best compression"
37
+ @eng = Zlib::Deflate.new(Zlib::BEST_COMPRESSION)
38
+ when :best_speed
39
+ teLogger.debug "Best compression"
40
+ @eng = Zlib::Deflate.new(Zlib::BEST_SPEED)
41
+ when :no_compression
42
+ teLogger.debug "No compression"
43
+ @eng = Zlib::Deflate.new(Zlib::NO_COMPRESSION)
44
+ else
45
+ teLogger.debug "Default compression"
46
+ @eng = Zlib::Deflate.new(Zlib::DEFAULT_COMPRESSION)
47
+ end
48
+
49
+ end
50
+
51
+ def update(val)
52
+ @eng.deflate(val, Zlib::SYNC_FLUSH)
53
+ end
54
+
55
+ def final
56
+
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,9 @@
1
+
2
+
3
+ module Ccrypto
4
+ module Ruby
5
+ class DataConversionEngine
6
+ extend DataConversion
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,70 @@
1
+
2
+
3
+ module Ccrypto
4
+ module Ruby
5
+ class Decompression
6
+
7
+ def initialize(*args, &block)
8
+ if block
9
+
10
+ outPath = block.call(:out_path)
11
+ if is_empty?(outPath)
12
+ outFile = block.call(:out_file)
13
+ raise CompressionError, "Given out_file required to support write() call" if not outFile.respond_to?(:write)
14
+ @out = outFile
15
+ else
16
+ @out = Tempfile.new(SecureRandom.hex(16))
17
+ end
18
+
19
+ @intBufSize = block.call(:int_buf_size) || 102400
20
+
21
+ else
22
+ @intBufSize = 102400
23
+
24
+ end
25
+
26
+ @eng = Zlib::Inflate.new
27
+
28
+ #@in = Tempfile.new(SecureRandom.hex(16))
29
+ end
30
+
31
+ def update(val)
32
+ begin
33
+ @eng.inflate(val)
34
+ rescue Zlib::DataError
35
+ end
36
+ end
37
+
38
+ def final
39
+
40
+ #eng = Zlib::Inflate.new
41
+
42
+ #@in.seek(0)
43
+
44
+ #intBuf = false
45
+ #if @out.nil?
46
+ # @out = StringIO.new
47
+ # intBuf = true
48
+ #end
49
+
50
+ #chunk = 102400
51
+ #loop do
52
+ # compressed = @in.read(chunk)
53
+ # res = eng.inflate(compressed) #, Zlib::SYNC_FLUSH)
54
+ # @out.write(res)
55
+
56
+ # break if @in.eof?
57
+ #end
58
+
59
+ #if intBuf
60
+ # @out.string
61
+ #else
62
+ # @out
63
+ #end
64
+
65
+ end
66
+
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,127 @@
1
+
2
+ require_relative '../data_conversion'
3
+
4
+ module Ccrypto
5
+ module Ruby
6
+ class DigestEngine
7
+ include Ccrypto::Ruby::DataConversion
8
+ include TR::CondUtils
9
+
10
+ include TeLogger::TeLogHelper
11
+
12
+ teLogger_tag :r_digest
13
+
14
+ SupportedDigest = [
15
+ Ccrypto::SHA1.provider_info("sha1"),
16
+ Ccrypto::SHA224.provider_info("sha224"),
17
+ Ccrypto::SHA256.provider_info("sha256"),
18
+ Ccrypto::SHA384.provider_info("sha384"),
19
+ Ccrypto::SHA512.provider_info("sha512"),
20
+ Ccrypto::SHA512_224.provider_info("sha512-224"),
21
+ Ccrypto::SHA512_256.provider_info("sha512-256"),
22
+ Ccrypto::SHA3_224.provider_info("sha3-224"),
23
+ Ccrypto::SHA3_256.provider_info("sha3-256"),
24
+ Ccrypto::SHA3_384.provider_info("sha3-384"),
25
+ Ccrypto::SHA3_512.provider_info("sha3-512"),
26
+ Ccrypto::SHAKE128.provider_info("shake128"),
27
+ Ccrypto::SHAKE256.provider_info("shake256"),
28
+ Ccrypto::BLAKE2b512.provider_info("BLAKE2b512"),
29
+ Ccrypto::BLAKE2s256.provider_info("BLAKE2s256"),
30
+ Ccrypto::SM3.provider_info("SM3"),
31
+ Ccrypto::RIPEMD160.provider_info("RIPEMD160"),
32
+ Ccrypto::WHIRLPOOL.provider_info("whirlpool")
33
+ ]
34
+
35
+
36
+ def self.supported
37
+ SupportedDigest
38
+ end
39
+
40
+ 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
46
+ end
47
+
48
+ res
49
+ end
50
+
51
+ def self.instance(*args, &block)
52
+ conf = args.first
53
+ if not_empty?(conf.provider_config)
54
+ teLogger.debug "Creating digest engine #{conf.provider_config}"
55
+ DigestEngine.new(OpenSSL::Digest.new(conf.provider_config))
56
+ else
57
+ raise DigestEngineException, "Given digest config #{conf.algo} does not have provider key mapping. Most likely this config is not supported by provider #{Ccrypto::Ruby::Provider.provider_name}"
58
+ end
59
+ end
60
+
61
+ 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}"
67
+ else
68
+ teLogger.debug "Found digest #{key.to_sym}"
69
+ DigestEngine.new(OpenSSL::Digest.new(res.provider_config))
70
+ end
71
+
72
+ end
73
+
74
+ def self.engineKeys
75
+ if @engineKeys.nil?
76
+ @engineKeys = {}
77
+ supported.map do |e|
78
+ @engineKeys[e.algo.to_sym] = e
79
+ end
80
+ end
81
+ @engineKeys
82
+ end
83
+
84
+ def initialize(inst)
85
+ @inst = inst
86
+ end
87
+
88
+ def native_digest_engine
89
+ @inst
90
+ end
91
+ alias_method :native_instance, :native_digest_engine
92
+
93
+ def digest(val, output = :binary)
94
+ digest_update(val)
95
+ digest_final(output)
96
+ end
97
+
98
+ def digest_update(val)
99
+ case val
100
+ when MemoryBuffer
101
+ @inst.update(val.bytes)
102
+ else
103
+ @inst.update(val)
104
+ end
105
+ end
106
+
107
+ def digest_final(output = :binary)
108
+
109
+ res = @inst.digest
110
+ @inst.reset
111
+ case output
112
+ when :hex
113
+ to_hex(res)
114
+ when :b64
115
+ to_b64(res)
116
+ else
117
+ res
118
+ end
119
+ end
120
+
121
+ def reset
122
+ @inst.reset
123
+ end
124
+
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,218 @@
1
+
2
+ require 'openssl'
3
+ module PKeyPatch
4
+ def to_pem; public_key.to_pem end
5
+ def to_der; public_key.to_der end
6
+
7
+ #private
8
+ def public_key
9
+ key = ::OpenSSL::PKey::EC.new group
10
+ key.public_key = self
11
+ key
12
+ end
13
+ end
14
+ OpenSSL::PKey::EC::Point.prepend PKeyPatch
15
+
16
+ require_relative '../keybundle_store/pkcs12'
17
+ require_relative '../keybundle_store/pem_store'
18
+
19
+ module Ccrypto
20
+ module Ruby
21
+
22
+ class ECCPublicKey < Ccrypto::ECCPublicKey
23
+
24
+ def to_bin
25
+ @native_pubKey.to_der
26
+ end
27
+
28
+ def self.to_key(bin)
29
+ ek = OpenSSL::PKey::EC.new(bin)
30
+ ECCPublicKey.new(ek)
31
+ end
32
+
33
+ end
34
+
35
+ class ECCKeyBundle
36
+ include Ccrypto::ECCKeyBundle
37
+ include TR::CondUtils
38
+
39
+ include PKCS12Store
40
+ include PEMStore
41
+
42
+ include TeLogger::TeLogHelper
43
+
44
+ teLogger_tag :r_ecc_keybundle
45
+
46
+ def initialize(keypair)
47
+ @nativeKeypair = keypair
48
+ end
49
+
50
+ def public_key
51
+ if @pubKey.nil?
52
+ @pubKey = ECCPublicKey.new(@nativeKeypair.public_key)
53
+ end
54
+ @pubKey
55
+ end
56
+
57
+ def private_key
58
+ ECCPrivateKey.new(@nativeKeypair)
59
+ end
60
+
61
+ def derive_dh_shared_secret(pubKey)
62
+
63
+ case pubKey
64
+ when OpenSSL::PKey::EC::Point
65
+ tkey = pubKey
66
+ when Ccrypto::ECCPublicKey
67
+ tkey = pubKey.native_pubKey
68
+ tkey = tkey.public_key if not tkey.is_a?(OpenSSL::PKey::EC::Point)
69
+ else
70
+ raise KeypairEngineException, "Unknown public key type #{pubKey.class}"
71
+ end
72
+
73
+ raise KeypairEngineException, "OpenSSL::PKey::EC::Point is required. Given #{tkey.inspect}" if not tkey.is_a?(OpenSSL::PKey::EC::Point)
74
+ @nativeKeypair.dh_compute_key(tkey)
75
+ end
76
+
77
+ def is_public_key_equal?(pubKey)
78
+
79
+ case pubKey
80
+ when OpenSSL::PKey::EC
81
+ targetKey = pubKey
82
+ when ECCKeyBundle
83
+ targetKey = pubKey.public_key
84
+ when ECCPublicKey
85
+ targetKey = pubKey.native_pubKey
86
+ else
87
+ raise KeypairEngineException, "Unknown public key type #{pubKey.class}"
88
+ end
89
+
90
+ public_key.to_bin == targetKey.to_der
91
+ end
92
+
93
+ def to_storage(format, &block)
94
+ case format
95
+ when :pkcs12, :p12
96
+ to_pkcs12 do |key|
97
+ case key
98
+ when :keypair
99
+ @nativeKeypair
100
+ else
101
+ block.call(key) if block
102
+ end
103
+ end
104
+
105
+ when :pem
106
+ to_pem do |key|
107
+ case key
108
+ when :keypair
109
+ @nativeKeypair
110
+ else
111
+ block.call(key) if block
112
+ end
113
+ end
114
+
115
+ else
116
+ raise KeyBundleStorageException, "Unknown storage format #{format}"
117
+ end
118
+ end
119
+
120
+ def self.from_storage(bin, &block)
121
+ raise KeypairEngineException, "Given data to load is empty" if is_empty?(bin)
122
+
123
+ case bin
124
+ when String
125
+ begin
126
+ teLogger.debug "Given String to load from storage"
127
+ if is_pem?(bin)
128
+ self.from_pem(bin, &block)
129
+ else
130
+ # binary buffer
131
+ teLogger.debug "Given binary to load from storage"
132
+ self.from_pkcs12(bin,&block)
133
+ end
134
+ rescue Ccrypto::Ruby::PKCS12Store::PKCS12StoreException => ex
135
+ raise KeyBundleStorageException, ex
136
+ end
137
+ else
138
+ raise KeyBundleStorageException, "Unsupported input type #{bin}"
139
+ end
140
+
141
+ end
142
+
143
+ def equal?(kp)
144
+ if kp.respond_to?(:to_der)
145
+ @nativeKeypair.to_der == kp.to_der
146
+ else
147
+ @nativeKeypair == kp
148
+ #false
149
+ end
150
+ end
151
+
152
+ def method_missing(mtd, *args, &block)
153
+ if @nativeKeypair.respond_to?(mtd)
154
+ teLogger.debug "Sending to nativeKeypair #{mtd}"
155
+ @nativeKeypair.send(mtd,*args, &block)
156
+ else
157
+ super
158
+ end
159
+ end
160
+
161
+ def respond_to_missing?(mtd, *args, &block)
162
+ @nativeKeypair.respond_to?(mtd)
163
+ end
164
+
165
+ end
166
+
167
+ class ECCEngine
168
+ include TR::CondUtils
169
+
170
+ include TeLogger::TeLogHelper
171
+
172
+ teLogger_tag :r_ecc
173
+
174
+ def self.supported_curves
175
+ if @curves.nil?
176
+ @curves = OpenSSL::PKey::EC.builtin_curves.map { |c| Ccrypto::ECCConfig.new(c[0]) }
177
+ end
178
+ @curves
179
+ end
180
+
181
+ def initialize(*args, &block)
182
+ @config = args.first
183
+ raise KeypairEngineException, "1st parameter must be a #{Ccrypto::KeypairConfig.class} object" if not @config.is_a?(Ccrypto::KeypairConfig)
184
+ teLogger.debug "Config #{@config}"
185
+ end
186
+
187
+ def generate_keypair(&block)
188
+ teLogger.debug "Generating keypair of curve #{@config.curve}"
189
+ kp = OpenSSL::PKey::EC.generate(@config.curve.to_s)
190
+ #teLogger.debug "Generated keypair #{kp.inspect}"
191
+ ECCKeyBundle.new(kp)
192
+ end
193
+
194
+ def sign(val)
195
+ raise KeypairEngineException, "Keypair is required" if @config.keypair.nil?
196
+ raise KeypairEngineException, "ECC keypair is required" if not @config.keypair.is_a?(ECCKeyBundle)
197
+ kp = @config.keypair
198
+
199
+ res = kp.nativeKeypair.dsa_sign_asn1(val)
200
+ teLogger.debug "Data of length #{val.length} signed "
201
+
202
+ res
203
+ end
204
+
205
+ 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
211
+
212
+ res = uPubKey.dsa_verify_asn1(val, sign)
213
+ res
214
+ end
215
+
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,54 @@
1
+
2
+ require_relative '../data_conversion'
3
+
4
+ module Ccrypto
5
+ module Ruby
6
+ class HKDFEngine
7
+ include DataConversion
8
+ include TR::CondUtils
9
+
10
+ def initialize(*args, &block)
11
+ @config = args.first
12
+
13
+ raise KDFEngineException, "KDF config is expected" if not @config.is_a?(Ccrypto::KDFConfig)
14
+ raise KDFEngineException, "Output bit length (outBitLength) value is not given or not a positive value (#{@config.outBitLength})" if is_empty?(@config.outBitLength) or @config.outBitLength <= 0
15
+
16
+
17
+ @config.salt = SecureRandom.random_bytes(16) if is_empty?(@config.salt)
18
+ end
19
+
20
+ def derive(input, output = :binary)
21
+
22
+ digest = init_digest(@config.digest)
23
+
24
+ @config.info = "" if @config.info.nil?
25
+
26
+ res = OpenSSL::KDF.hkdf(input, salt: @config.salt, info: @config.info, length: @config.outBitLength/8, hash: digest)
27
+
28
+ case output
29
+ when :hex
30
+ to_hex(res)
31
+ when :b64
32
+ to_b64(res)
33
+ else
34
+ res
35
+ end
36
+ end
37
+
38
+ private
39
+ def init_digest(algo)
40
+ if DigestEngine.is_supported?(algo)
41
+ conf = DigestEngine.engineKeys[algo]
42
+ if not_empty?(conf)
43
+ OpenSSL::Digest.new(conf.provider_config)
44
+ else
45
+ raise DigestEngineException, "Algo config '#{algo}' not found"
46
+ end
47
+ else
48
+ raise DigestEngineException, "Digest algo '#{algo}' is not supported"
49
+ end
50
+ end
51
+
52
+ end
53
+ end
54
+ end