ccrypto 0.1.2 → 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.
@@ -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,6 +17,8 @@ module Ccrypto
17
17
 
18
18
  attr_reader :default
19
19
 
20
+ attr_accessor :provider_config
21
+
20
22
  def initialize(status = Algo_Active, default = false)
21
23
  @algo_status = status
22
24
  @default = default
@@ -62,20 +64,28 @@ module Ccrypto
62
64
 
63
65
  class ECCConfig < KeypairConfig
64
66
 
65
- def self.name
66
- "Elliptic Curve (ECC)"
67
+ def self.algo_name
68
+ "Elliptic Curve (ECC) (Classical - Signing and Encryption)"
69
+ end
70
+
71
+ def self.algo_key
72
+ :ecc
67
73
  end
68
74
 
69
- attr_accessor :curve
75
+ attr_reader :curve
70
76
  def initialize(curve = nil, status = Algo_Active, default = false)
71
- @algo = :ecc
77
+ @algo = self.class.algo_key
72
78
  @curve = curve || :prime256v1
73
79
  @curve = @curve.to_sym if not @curve.is_a?(Symbol)
74
80
  super(status, default)
75
81
  end
76
82
 
83
+ def param
84
+ @curve
85
+ end
86
+
77
87
  def to_s
78
- "#{@curve}"
88
+ "ECC - #{@curve}"
79
89
  end
80
90
 
81
91
  def self.supported_curves(&block)
@@ -84,16 +94,25 @@ module Ccrypto
84
94
  end # ECCConfig
85
95
 
86
96
  class RSAConfig < KeypairConfig
87
- def self.name
88
- "RSA"
97
+ def self.algo_name
98
+ "RSA (Classical - Signing and Encryption)"
89
99
  end
90
100
 
91
- attr_accessor :keysize
101
+ def self.algo_key
102
+ :rsa
103
+ end
104
+
105
+ attr_reader :keysize
92
106
  def initialize(keysize = 2048, status = Algo_Active, default = false)
107
+ @algo = self.class.algo_key
93
108
  @keysize = keysize
94
109
  super(status, default)
95
110
  end
96
111
 
112
+ def param
113
+ @keysize
114
+ end
115
+
97
116
  def to_s
98
117
  "RSA-#{keysize} bits"
99
118
  end
@@ -105,25 +124,87 @@ module Ccrypto
105
124
 
106
125
  # ED25519 for data signature
107
126
  class ED25519Config < KeypairConfig
108
- def self.name
109
- "ED25519 (Signing Only)"
127
+ def self.algo_name
128
+ "ED25519 (Classical - Signing Only)"
129
+ end
130
+
131
+ def self.algo_key
132
+ :ed25519
110
133
  end
111
134
 
112
135
  def initialize
113
- algo = :ed25519
136
+ @algo = self.class.algo_key
114
137
  super(Algo_Active, true)
115
138
  end
139
+
140
+ def param
141
+ nil
142
+ end
116
143
  end
117
144
 
118
145
  # X25519 for key exchange
119
146
  class X25519Config < KeypairConfig
120
- def self.name
147
+ def self.algo_name
121
148
  "X25519 (Data Encipherment only)"
122
149
  end
150
+
151
+ def self.algo_key
152
+ :x25519
153
+ end
154
+
123
155
  def initialize
124
- algo = :x25519
156
+ @algo = self.class.algo_key
125
157
  super(Algo_Active, true)
126
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
127
208
  end
128
209
 
129
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