ccrypto 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,11 +3,12 @@
3
3
  module Ccrypto
4
4
  class KDFConfig
5
5
  include AlgoConfig
6
- attr_accessor :algo, :outBitLength
6
+ attr_accessor :algo
7
7
  end
8
8
 
9
9
  class ScryptConfig < KDFConfig
10
- attr_accessor :cost, :blockSize, :parallel, :salt
10
+ attr_accessor :cost, :blocksize, :parallel
11
+ attr_accessor :outBitLength, :salt
11
12
 
12
13
  # https://stackoverflow.com/questions/11126315/what-are-optimal-scrypt-work-factors
13
14
  # Specific good explanation:
@@ -43,35 +44,43 @@ module Ccrypto
43
44
  def initialize
44
45
  @algo = :scrypt
45
46
  @cost = 16384 # 2**14
46
- @blockSize = 8
47
+ @blocksize = 8
47
48
  @parallel = 1
48
49
  @salt = SecureRandom.random_bytes(16)
49
50
  end
50
51
  end
51
52
 
52
53
  class HKDFConfig < KDFConfig
53
- attr_accessor :salt, :info, :digest
54
+ attr_accessor :salt, :digest, :outBitLength
55
+ attr_accessor :info
56
+ attr_accessor :provider_config
54
57
  def initialize
55
58
  @algo = :hkdf
56
59
  @salt = SecureRandom.random_bytes(16)
57
60
  @digest = :sha3_256
58
61
  end
59
- end
62
+ end # HKDFConfig
60
63
 
61
64
  class PBKDF2Config < KDFConfig
62
65
  attr_accessor :salt, :digest, :iter
66
+ attr_accessor :outBitLength
63
67
  def initialize
64
68
  @algo = :pbkdf2
65
69
  @salt = SecureRandom.random_bytes(16)
66
70
  @digest = :sha3_256
67
71
  @iter = rand(300000..500000)
68
72
  end
69
- end
73
+ end # PBKDF2Config
70
74
 
71
75
  class Argon2Config < KDFConfig
72
76
 
73
77
  attr_accessor :cost, :salt, :secret, :parallel, :iter
74
78
  attr_accessor :variant
79
+ attr_accessor :outBitLength
80
+
81
+ def self.variants
82
+ [:argon2d, :argon2i, :argon2id, :argon2_version_10, :argon2_version_13].freeze
83
+ end
75
84
 
76
85
  def initialize
77
86
 
@@ -81,13 +90,18 @@ module Ccrypto
81
90
  @salt = SecureRandom.random_bytes(16)
82
91
 
83
92
  # Secret value which has to be stored in a different secure location from the password hashes
84
- @secret = SecureRandom.random_bytes(16)
93
+ #@secret = SecureRandom.random_bytes(16)
85
94
 
86
- # The RFC recommends 4 GB for backend authentication and 1 GB for frontend authentication.
87
- @cost = 1*1024*1024*1024
95
+ # The RFC recommends 4 GB for backend authentication and 1 GB for frontend authentication.
96
+ # Unit is in Kilobytes. Min is 8 kb. Convert internally to kb hence the value is 8192
97
+ # 1024*1024 = 1048576 (1GB)
98
+ #@cost = 1048576
99
+ # 25 Dec 2023 - Change it to 2**@cont value below
100
+ # 1GB = 2**20 hence the @cont value should be 20 if 1GB RAM is required
101
+ @cont = 20
88
102
 
89
103
  # Choose the Number of CPU-Threads you can afford each call (2 Cores = 4 Threads)
90
- @parallel = 4
104
+ @parallel = 1
91
105
 
92
106
  # Set the number of Iterations each call -> More Iterations = Better Security + more Hashing Time
93
107
  # > 3 Iterations recommended
@@ -103,6 +117,54 @@ module Ccrypto
103
117
 
104
118
  end
105
119
 
106
- end
120
+ end # Argon2Config
121
+
122
+ #
123
+ # BCrypt returns fixed 24 bytes (192 bits) output
124
+ #
125
+ class BCryptConfig < KDFConfig
126
+ # Salt is 16 bytes long
127
+ attr_accessor :salt
128
+ # Cost is exponent 2^cost, range from 4 - 31 inclusive
129
+ attr_accessor :cost
130
+
131
+ # Fixed output length of 24 bytes / 192 bits
132
+ attr_reader :outBitLength, :max_input_byte_length
133
+ attr_reader :salt_length, :cost_lowest_bound, :cost_upper_bound
134
+
135
+ def self.outBitLength
136
+ 192
137
+ end
138
+
139
+ def self.outByteLength
140
+ 24
141
+ end
142
+
143
+ def self.max_input_byte_length
144
+ 72
145
+ end
146
+
147
+ def self.salt_length
148
+ 16
149
+ end
150
+
151
+ def self.cost_lowest_bound
152
+ 4
153
+ end
154
+
155
+ def self.cost_upper_bound
156
+ 31
157
+ end
158
+
159
+ def initialize
160
+ #@salt = SecureRandom.random_bytes(16)
161
+ @cost = 16
162
+ @outBitLength = self.class.outBitLength
163
+ @max_input_byte_length = self.class.max_input_byte_length # 72 # bcrypt can only handle password <= 72 bytes (Java BC)
164
+ @salt_length = self.class.salt_length
165
+ @cost_lowest_bound = self.class.cost_lowest_bound
166
+ @cost_upper_bound = self.class.cost_upper_bound
167
+ end
168
+ end # BCryptConfig
107
169
 
108
170
  end
@@ -4,7 +4,14 @@ module Ccrypto
4
4
  class KeyConfig
5
5
  include AlgoConfig
6
6
 
7
- attr_accessor :algo, :keysize
7
+ attr_reader :algo, :keysize
8
+
9
+ attr_accessor :provider_config
10
+
11
+ def initialize(algo, keysize)
12
+ @algo = algo
13
+ @keysize = keysize
14
+ end
8
15
 
9
16
  def to_s
10
17
  "#{@algo}/#{@keysize}"
@@ -17,7 +17,7 @@ module Ccrypto
17
17
 
18
18
  attr_reader :default
19
19
 
20
- attr_accessor :native_config
20
+ attr_accessor :provider_config
21
21
 
22
22
  def initialize(status = Algo_Active, default = false)
23
23
  @algo_status = status
@@ -64,20 +64,28 @@ module Ccrypto
64
64
 
65
65
  class ECCConfig < KeypairConfig
66
66
 
67
- def self.name
68
- "Elliptic Curve (ECC)"
67
+ def self.algo_name
68
+ "Elliptic Curve (ECC) (Classical - Signing and Encryption)"
69
69
  end
70
70
 
71
- attr_accessor :curve
71
+ def self.algo_key
72
+ :ecc
73
+ end
74
+
75
+ attr_reader :curve
72
76
  def initialize(curve = nil, status = Algo_Active, default = false)
73
- @algo = :ecc
77
+ @algo = self.class.algo_key
74
78
  @curve = curve || :prime256v1
75
79
  @curve = @curve.to_sym if not @curve.is_a?(Symbol)
76
80
  super(status, default)
77
81
  end
78
82
 
83
+ def param
84
+ @curve
85
+ end
86
+
79
87
  def to_s
80
- "#{@curve}"
88
+ "ECC - #{@curve}"
81
89
  end
82
90
 
83
91
  def self.supported_curves(&block)
@@ -86,16 +94,25 @@ module Ccrypto
86
94
  end # ECCConfig
87
95
 
88
96
  class RSAConfig < KeypairConfig
89
- def self.name
90
- "RSA"
97
+ def self.algo_name
98
+ "RSA (Classical - Signing and Encryption)"
91
99
  end
92
100
 
93
- attr_accessor :keysize
101
+ def self.algo_key
102
+ :rsa
103
+ end
104
+
105
+ attr_reader :keysize
94
106
  def initialize(keysize = 2048, status = Algo_Active, default = false)
107
+ @algo = self.class.algo_key
95
108
  @keysize = keysize
96
109
  super(status, default)
97
110
  end
98
111
 
112
+ def param
113
+ @keysize
114
+ end
115
+
99
116
  def to_s
100
117
  "RSA-#{keysize} bits"
101
118
  end
@@ -107,25 +124,87 @@ module Ccrypto
107
124
 
108
125
  # ED25519 for data signature
109
126
  class ED25519Config < KeypairConfig
110
- def self.name
111
- "ED25519 (Signing Only)"
127
+ def self.algo_name
128
+ "ED25519 (Classical - Signing Only)"
129
+ end
130
+
131
+ def self.algo_key
132
+ :ed25519
112
133
  end
113
134
 
114
135
  def initialize
115
- algo = :ed25519
136
+ @algo = self.class.algo_key
116
137
  super(Algo_Active, true)
117
138
  end
139
+
140
+ def param
141
+ nil
142
+ end
118
143
  end
119
144
 
120
145
  # X25519 for key exchange
121
146
  class X25519Config < KeypairConfig
122
- def self.name
147
+ def self.algo_name
123
148
  "X25519 (Data Encipherment only)"
124
149
  end
150
+
151
+ def self.algo_key
152
+ :x25519
153
+ end
154
+
125
155
  def initialize
126
- algo = :x25519
156
+ @algo = self.class.algo_key
127
157
  super(Algo_Active, true)
128
158
  end
159
+
160
+ def param
161
+ nil
162
+ end
163
+ end
164
+
165
+ # PQ Crystal Kyber
166
+ class CrystalKyberConfig < KeypairConfig
167
+ def self.algo_name
168
+ "Crystal Kyber (PQC - Signing)"
169
+ end
170
+ def self.algo_key
171
+ :crystal_kyber
172
+ end
173
+
174
+ attr_reader :param
175
+ def initialize(kyberParam, default = false)
176
+ @param = kyberParam
177
+ @algo = self.class.algo_key
178
+ super(Algo_Active, default)
179
+ end
180
+
181
+ def to_s
182
+ "PQ Crystal Kyber #{@param}"
183
+ end
184
+ end
185
+
186
+ # PQ Crystal Dlithium
187
+ class CrystalDilithiumConfig < KeypairConfig
188
+ # has unintended consequences during YAML dump and load
189
+ #def self.name
190
+ # "PQ Crystal Dilithium Family (for Signing)"
191
+ #end
192
+ def self.algo_name
193
+ "Crystal Dilithium (PQC - Encryption)"
194
+ end
195
+ def self.algo_key
196
+ :crystal_dilithium
197
+ end
198
+ attr_reader :param
199
+ def initialize(param, default = false)
200
+ @param = param
201
+ @algo = self.class.algo_key
202
+ super(Algo_Active, default)
203
+ end
204
+
205
+ def to_s
206
+ "PQ Crystal Dilithium #{@param}"
207
+ end
129
208
  end
130
209
 
131
210
  end
@@ -7,5 +7,12 @@ module Ccrypto
7
7
  attr_accessor :split_into
8
8
  attr_accessor :required_parts
9
9
 
10
+ def initialize(val = {})
11
+ if val.is_a?(Hash)
12
+ @split_into = val[:split_into]
13
+ @required_parts = val[:required_parts]
14
+ end
15
+ end
16
+
10
17
  end
11
18
  end
@@ -27,7 +27,7 @@ module Ccrypto
27
27
  attr_accessor :issuer_path_len
28
28
 
29
29
  def initialize
30
- @hashAlgo = Ccrypto::SHA256
30
+ @hashAlgo = :sha256
31
31
  @serial = SecureRandom.hex(16)
32
32
  @subj_key_id = true
33
33
  @auth_key_id = true
@@ -231,6 +231,7 @@ module Ccrypto
231
231
  @not_after = @not_before.advance(adv)
232
232
 
233
233
  end
234
+ alias_method :valid_for, :validity
234
235
 
235
236
  def match_issuer_not_before(issuer_not_before)
236
237
  if not_empty?(issuer_not_before)
@@ -314,12 +315,12 @@ module Ccrypto
314
315
  emailProtection: "Email protection",
315
316
  timeStamping: "Time stamping",
316
317
  OCSPSigning: "Online Cert Status Protocol signing",
317
- ipSecIKE: "IPSec Initial Key Exchange",
318
- msCodeInd: "Microsoft Code Ind",
319
- msCodeCom: "Microsoft Code Com",
320
- msCtlsign: "Microsoft CTL Sign",
321
- msEFS: "Microsoft EFS",
322
- dvcs: "DVCS purposes"
318
+ #ipSecIKE: "IPSec Initial Key Exchange",
319
+ #msCodeInd: "Microsoft Code Ind",
320
+ #msCodeCom: "Microsoft Code Com",
321
+ #msCtlsign: "Microsoft CTL Sign",
322
+ #msEFS: "Microsoft EFS",
323
+ #dvcs: "DVCS purposes"
323
324
  }
324
325
 
325
326
 
@@ -371,6 +372,7 @@ module Ccrypto
371
372
  def add_custom_extension(oid, value, type = :string, critical = false)
372
373
  custom_extension[oid] = { type: type, value: value, critical: critical }
373
374
  end
375
+ alias_method :add_domain_extension, :add_custom_extension
374
376
 
375
377
  def custom_extension
376
378
  if @custom_extension.nil?
@@ -378,6 +380,7 @@ module Ccrypto
378
380
  end
379
381
  @custom_extension
380
382
  end
383
+ alias_method :domain_extension, :custom_extension
381
384
 
382
385
  end
383
386
  end
@@ -16,7 +16,7 @@ module Ccrypto
16
16
  attr_accessor :hashAlgo
17
17
 
18
18
  def initialize
19
- @hashAlgo = Ccrypto::SHA256
19
+ @hashAlgo = :sha256
20
20
  end
21
21
 
22
22
  def org_unit
@@ -0,0 +1,122 @@
1
+
2
+ module Ccrypto
3
+
4
+ class DigestMatcherError < StandardError; end
5
+
6
+ #
7
+ # Match specific digest algo into common name inside the Ccrypto realm.
8
+ # The name is essential to let program to decide what to do
9
+ # Indirectly this should be the master list of supported digest algo
10
+ # inside the library
11
+ #
12
+ class DigestMatcher
13
+
14
+ MatcherTestStr = "antrapol ensures data is secure when and where you want it to be".freeze
15
+
16
+ #
17
+ # Here is how the digest table value is generated
18
+ #
19
+ def self.generate_digest(digestConf)
20
+ raise DigestMatcherError, "CCrypto::DigestConfig is required. Given '#{digestConf}'" if not digestConf.is_a?(Ccrypto::DigestConfig)
21
+
22
+ dig = Ccrypto::AlgoFactory.engine(digestConf)
23
+
24
+ if digestConf.has_fixed_input_len_byte?
25
+ len = digestConf.fixed_input_len_byte
26
+ if len <= MatcherTestStr.length
27
+ dat = MatcherTestStr[0...digestConf.fixed_input_len_byte]
28
+ else
29
+ dat = "#{MatcherTestStr} #{MatcherTestStr[0..(len-MatcherTestStr.length)-2]}"
30
+ end
31
+
32
+ logger.debug "Digest #{digestConf.inspect} has fixed_input_len_byte #{digestConf.fixed_input_len_byte}. Test data length : #{dat.length}"
33
+
34
+ else
35
+ dat = MatcherTestStr[0...8]
36
+ logger.debug "Digest #{digestConf.inspect} has no fixed input length restriction. Test data length : #{dat.length}"
37
+
38
+ end
39
+
40
+ dig.digest(dat, :b64)
41
+ end
42
+
43
+ def self.find_digest_key(digest)
44
+ if @dtable.nil?
45
+ # key is always symbol
46
+ # Decision to use symbol instead of string is symbol has limited way to encode:
47
+ # e.g. not able to include space or "-"
48
+ # If use String the permutation has more combination which increase the chance of
49
+ # ambiguity
50
+ @dtable = {
51
+ blake2b160: "0pLDxiKPKtVreDFhuDjDyeHwbB4=",
52
+ blake2b256: "gNdYJkgjFG3iRHjbAh6ov3csxZnR21iPv2v2kLoQjfg=",
53
+ blake2b384: "CbsfQsXyD35cMGZua4e6zx8BbGcSj0l56gOiiALVnKlYpCxWmpTYMjJxAmeVgjMu",
54
+ blake2b512: "QiiQhD4DndbOlaZMczD78BAdovWG5UM3Ba4XtmiXGKVvosPFgMn3xnb5qZ0DmKCgMrCLNwNulpIZrBukfMImww==",
55
+ blake2s128: "3jy26+gJFpYpyw1fTS6cgA==",
56
+ blake2s160: "wTZb6KBFCN3wt21wFW8hAzs3Io0=",
57
+ blake2s224: "+eHnZDIeFdj0VFK7OzETys8HzPzE+02DHIPI3A==",
58
+ blake2s256: "PD5L2mMOlSI6pJHT6Va/x6EDas0vZKjWPJ2+3nE/9Jk=",
59
+ blake3256: "nZKbHB35VnexVgZ+6TQ2i7rDjBjy/yPPeZn2FHAvqo0=",
60
+ dstu7564_256: "OL9g8GSInAjTmNYKwiA7wzIAq3sElpJvK7gsDcPKvz0=",
61
+ dstu7564_384: "IS9kM7dStF5pnxTdnJHMzQzZH/RB4vtowHPzBUjpr0EYE2rFCIC+L7Iw/EUTQUDG",
62
+ dstu7564_512: "vHf5CRg+eE9369X66djajCEvZDO3UrReaZ8U3ZyRzM0M2R/0QeL7aMBz8wVI6a9BGBNqxQiAvi+yMPxFE0FAxg==",
63
+ gost3411: "V4SIGhgZ3iwbrELe0AtK4f0i1YWaLoiNtVXCsqEQ1Wk=",
64
+ gost3411_2012_256: "gVQfx7U8Vd5XiKS0EjGFgbGVu0ZGj0hPRvoGz+F62FE=",
65
+ gost3411_2012_512: "ZMzHqL34UQyUSOvJgHBYlxJg7F+nTL/Qk2BU6fmDa7l968I2D47GDVL+3aA6LG8ZCvRyLAzbh/MvsKlX833WKQ==",
66
+ haraka256: "2pKCohySDK5bQx1G4H2C+4u8f1B09JQRnBo6f01xQHQ=",
67
+ haraka512: "g6KV4sJyErkk+HXWdTm7PH/RruqQAwploXK6dMhHC+w=",
68
+ keccak224: "3gFqjSP2Pc91QyH5xdaHck6aAoWnR+mjHbtFBg==",
69
+ keccak256: "96OfrPDMlOaRrQSfgbnFzrBhTDIRu0SPqEReyblUJ4k=",
70
+ keccak288: "v6vOPybqNq/Nmh2F675IzjWC2fjPBXl4grIb5SDKPU/uiMWj",
71
+ keccak384: "x/pKD7QmWywC14LYltOluCDH0U74S3YZONomZlTwQep+HGud70cYOQ/7ie+sMml6",
72
+ keccak512: "jSKQMB0fPrQV2zqYeSw59iDvwMsQwyE300dt5hNg4xPD69JP5W56v78LoV3jakJ+x4c+ZIE8NudPH5mGLo9Iag==",
73
+ parallelhash128_256: "bfpgOoHKnrqUHTrOj0bMa6WZRTSrEYIcidQaOG//A2M=",
74
+ parallelhash256_512: "c9DA3ooYlZNbGtxQgmfDrCltzXTmoTSmyJPO+2DrDcxcCUSodsOHctslFg/RbCVeN7LXh+sPXOd9NfRuaLPPxQ==",
75
+ ripemd128: "icy8Y0N0gU8O87hG+MwR1Q==",
76
+ ripemd160: "flnmtKvfan+4WH97spKi8XtAHrE=",
77
+ ripemd256: "Mf7adgrLqqrcpxZ752ad6v6tU7prl9FnBq2TYNPPoWk=",
78
+ ripemd320: "YdBKsjywQJ7bmByl+6Zn9J6RWAUeyeYmvSM3SoCImv028PIuHO8m3w==",
79
+ sha1: "RwUUHm8U866yoBNfGM4V2Ad2/D4=",
80
+ sha224: "zpQtV56miDL6LejIkXJ30o+9OtqcRsGq+EZX/A==",
81
+ sha256: "sNTq2sf8uzHKDiUt+Y1Vr/HVrW8AgLevQZ/HHKJubDA=",
82
+ sha384: "5KqG3DsSm6KxmAeS+buH0avldfM2DcR1b9GMRZjlK1F5jR5Lwg0TGbRRJ5U3ylFB",
83
+ sha512: "T7J7I3/VFMRSKt8q8KrWi9fsnzjXpFNEvoL5eVGI1Vt0HHfmFH5SHNg6L4X3l5GBcg6X6zlUBSqZk1QiKy8b4g==",
84
+ sha512_224: "On15IMF7xtTypEN2zlbl9LMD0++AX7Vo0uEGGw==",
85
+ sha512_256: "t1xIQgjCiIapNoseg1q3DdQQO7rngCga9ewqZ44EqOg=",
86
+ sha3_224: "VjXrA6pwc0z7BFPaGFCLGWB6o5LaOKAw8XGs1A==",
87
+ sha3_256: "raUIZ+3KcfEJTtcCzQCSTmZPcZFhlOVUsjDghhfhPxo=",
88
+ sha3_384: "wiBHqnLyOzMl228JaQq8Zd5E9GFJQlY3lWIE/14AyQbY0csl3wUPoqmIFEBJ5EVz",
89
+ sha3_512: "5fNjwalHgZL2ROHQNtsdJhVIkrXOXCOfTZg0kNXGuGrDVCwl9ERVAG5wHNXKDFW/D72gqoW0XDUIwDt+DMyzyw==",
90
+ shake128_256: "ChxTTokFs354PoInE4eXcZU3RLslAjBAgogFUlZKAr8=",
91
+ shake256_512: "1c+ERFraWmph91mdDe7LEpmcjgl3fYocO4a5L09DBM7BsuUMrgXC/QOwW9Ug6U7bqzpLa2Wot9K1ilEhy9lsUw==",
92
+ skein1024_1024: "LSCcR3WLi7KbAn30M8xDbZVn/DA0UJcJj4PrO/IH1nwFJ3Hac9v5XC1ckHvUzmQeaygzV1yyDbqnvmnhFx8WWRNhJ6/9doUHt5pPdH9czupjV1F1J0CrjFbgnQaruyAEWPJ/roOpWR28sVohAiXlZT73/jvFA1qUn46kFr1KOFo=",
93
+ skein1024_384: "py97erCjOPwWNv4kE7KoV5op22Lkh0xq/JM5hw6ezu2+5Vm9ylvCgESbCFrgn+uy",
94
+ skein1024_512: "OnAy/fSXBykZpAFSkqfmRFPtiFe2SpEeGH8JVY1jhllbhOqGyLyL+flY9Buymc8O+bkRM95IZphkwgD1R5nlmw==",
95
+ skein256_128: "2IzEhmqfdrBzNJli8v9tHA==",
96
+ skein256_160: "mBFGB+cBumPVLdjNHg06szlvwNo=",
97
+ skein256_224: "ZG8Ia4m2/8W2+zI76zpensT84xYjZZeQBNmCOw==",
98
+ skein256_256: "s3hhdiS2r+nTJxE2f0Vkx0MvDvPc9j35zbXbziDkovM=",
99
+ skein512_128: "bb17DoKVvzqyA4IconI3vg==",
100
+ skein512_160: "BzoVjJObMVkGMx+sa7uLS/kNCIk=",
101
+ skein512_224: "LlxCIHa9sHm+g7wXTOesVpjSrk7TvOYMC5AknQ==",
102
+ skein512_256: "4UUxlYOSqITg96ZtlBYBUtQeh1mLgOuoMFP47SmJ4RA=",
103
+ skein512_384: "EDoBTYO6G2mbBCfYuan1lIuazB+ToGP4gUB8uj+248SUd0r57tY1mWEfOMQOoSiS",
104
+ skein512_512: "94/CDISu4nyY2Pobuq9N5lGA0Jdybc3gfdudSmUbuHdXYdjnameJt9UvunQIO9MCufG0QyEgOBsjBNasPw46XQ==",
105
+ sm3: "X1mEgSOAmjzrvU5jci1e2iK42HVyYvROhpxp0BiKw2s=",
106
+ tiger: "Y5UJEZq2ZEFkoOFSak1WmRcstCFuRe9H",
107
+ tuplehash128_256: "xTUUf5y3DDNvfYEY19ezdXygpzcx33nnpexAzU81HR4=",
108
+ tuplehash256_512: "Ey2RfbNNCYMu9CpmEwNq+BMrd90TPCCPV1fgefGdY9bNObnb76l+z+ju3ZPZ12+eGAz3xTXAX7HKOWqrw/8r2w==",
109
+ whirlpool: "CsHu74qufeIg1eG72WDiydOO+CkPg5XDIzMFL4izDmFg+YHWE/v1g/RYzTD3BipFUWrrHKz+1itoYTxuJ4w+Mg=="
110
+ }
111
+ end
112
+
113
+ @dtable.invert[digest]
114
+ end
115
+
116
+ private
117
+ def self.logger
118
+ Ccrypto.logger(:digest_matcher)
119
+ end
120
+
121
+ end
122
+ end