enzoic 1.1.3 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 193cc6ee5e5585ea3a76add970ce69feb44c2383
4
- data.tar.gz: a77cdcf48592e05a9f06ef1ad486467002f2df30
2
+ SHA256:
3
+ metadata.gz: 2af7917c4ee90414cdffeda3948ce2a0642f523f6c44fe07db64deab4f5b6e25
4
+ data.tar.gz: 4cdfeb61e75c47f95132e9a0c644f89a987597a48685038ac7308dba66e008ee
5
5
  SHA512:
6
- metadata.gz: 641ca919dd26147fe4e06550923f380f2b54eb0959372171f57a4f17ff2bcd5f98adcd446d3d39e9f0205910671307c7e78b6954ffa77e0ad58513f25ca31084
7
- data.tar.gz: 9acf2c9d120dc0292f136b7583ba0d36f2aacd4c7e9fe52de19ec2c6468f7f42738e939250893345fe1fdc6e5d77b44e203db2558b34b0a541303365515b393d
6
+ metadata.gz: 557fadc6dab20d5d76d2098466c31728ecba0a1fcd16ce9cd13a798817239bb791012691b37130b7e64dd7275728d83c9f89bdfeda10dbde0b369faf705f8ecf
7
+ data.tar.gz: 420af16ed93a7696969a74fbfcd13e491e23f934a9f15712fe42fc3eb777e6cdcf51751ac4ebc2bfa28b250fc7d17c3107f10989a524c4f1779811254423cc50
data/README.md CHANGED
@@ -35,6 +35,7 @@ require 'enzoic'
35
35
  enzoic = Enzoic::Enzoic.new(apiKey: YOUR_API_KEY, secret: YOUR_API_SECRET)
36
36
 
37
37
  # Check whether a password has been compromised
38
+ # see https://www.enzoic.com/docs-passwords-api/ for more information
38
39
  if enzoic.check_password("password-to-test")
39
40
  puts("Password is compromised")
40
41
  else
@@ -42,6 +43,7 @@ else
42
43
  end
43
44
 
44
45
  # Check whether a specific set of credentials are compromised
46
+ # see https://www.enzoic.com/docs-credentials-api/ for more information
45
47
  if enzoic.check_credentials("test@enzoic.com", "password-to-test")
46
48
  puts("Credentials are compromised")
47
49
  else
@@ -53,7 +55,7 @@ end
53
55
  # lastCheckDate is the timestamp for the last check you performed for this user.
54
56
  # If the DateTime you provide for the last check is greater than the timestamp Enzoic has
55
57
  # for the last breach affecting this user, the check will not be performed.
56
- # This can be used to substantially increase performance.
58
+ # This can be used to substantially increase performance.
57
59
  if enzoic.check_credentials("test@enzoic.com", "password-to-test", DateTime.parse("2019-07-15T19:57:43.000Z"))
58
60
  puts("Credentials are compromised")
59
61
  else
@@ -61,12 +63,20 @@ else
61
63
  end
62
64
 
63
65
  # get all exposures for a given user
66
+ # see https://www.enzoic.com/docs-exposures-api/#get-exposures for more information
64
67
  exposures = enzoic.get_exposures_for_user("test@enzoic.com")
65
68
  puts(exposures.count.to_s + " exposures found for test@enzoic.com")
66
69
 
67
70
  # now get the full details for the first exposure found
71
+ # see https://www.enzoic.com/docs-exposures-api/#get-exposure-details for more information
68
72
  details = enzoic.get_exposure_details(exposures.exposures[0])
69
73
  puts("First exposure for test@enzoic.com was " + details.title)
74
+
75
+ # get all passwords for a given user - requires special approval, contact Enzoic sales
76
+ # see https://www.enzoic.com/docs-raw-passwords-api/ for more information
77
+ user_passwords = enzoic.get_passwords_for_user("eicar_0@enzoic.com")
78
+ puts("First password for eicar_0@enzoic.com was " + user_passwords.passwords[0].password)
79
+
70
80
  ```
71
81
 
72
82
  More information in reference format can be found below.
data/Rakefile CHANGED
@@ -20,9 +20,9 @@ Rake::ExtensionTask.new('whirlpool', gemspec) do |ext|
20
20
  ext.lib_dir = 'lib/digest'
21
21
  end
22
22
 
23
- # Rake::ExtensionTask.new('argon2-wrapper', gemspec) do |ext|
24
- # ext.ext_dir = 'ext/argon2-wrapper'
25
- # ext.lib_dir = 'lib/enzoic'
26
- # end
23
+ Rake::ExtensionTask.new('argon2-wrapper', gemspec) do |ext|
24
+ ext.ext_dir = 'ext/argon2-wrapper'
25
+ ext.lib_dir = 'lib/enzoic'
26
+ end
27
27
 
28
28
  task :default => :test
data/enzoic.gemspec CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.add_dependency 'unix-crypt', '~> 1.3'
28
28
  spec.add_dependency 'base64url', '~> 1.0', '>= 1.0.1'
29
29
 
30
- spec.add_development_dependency "bundler", '~> 2.0.2', '>= 2.0.2'
30
+ spec.add_development_dependency "bundler", '~> 2.2.11', '>= 2.2.11'
31
31
  spec.add_development_dependency "rake", '~> 10.4', '>= 10.4.2'
32
32
  spec.add_development_dependency "test-unit", '~> 3.2', '>= 3.2.4'
33
33
  spec.add_development_dependency "rake-compiler", '~> 1.0', '>= 1.0.4'
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -24,6 +24,14 @@ module Enzoic
24
24
  return Digest::SHA1.hexdigest to_hash
25
25
  end
26
26
 
27
+ def self.sha1_binary(to_hash)
28
+ return Digest::SHA1.digest(to_hash).bytes
29
+ end
30
+
31
+ def self.sha1_binary_array(to_hash_bytes)
32
+ return Digest::SHA1.digest(to_hash_bytes.pack('c*')).bytes
33
+ end
34
+
27
35
  def self.sha256(to_hash)
28
36
  return Digest::SHA256.hexdigest to_hash
29
37
  end
@@ -91,7 +99,7 @@ module Enzoic
91
99
 
92
100
  itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
93
101
  to_hash_bytes = to_hash.bytes
94
- count = 2**itoa64.index(salt[3])
102
+ count = 2 ** itoa64.index(salt[3])
95
103
  justsalt = salt[4..12]
96
104
 
97
105
  hash = self.md5_binary(justsalt + to_hash)
@@ -148,13 +156,146 @@ module Enzoic
148
156
  end
149
157
 
150
158
  def self.md5crypt(to_hash, salt)
151
- return UnixCrypt::MD5.build(to_hash, salt.start_with?("$1$") ? salt[3..salt.length] : salt);
159
+ return UnixCrypt::MD5.build(to_hash, salt.start_with?("$1$") ? salt[3..salt.length] : salt)
152
160
  end
153
161
 
154
162
  def self.custom_algorithm4(to_hash, salt)
155
163
  return self.bcrypt(self.md5(to_hash), salt)
156
164
  end
157
165
 
166
+ def self.custom_algorithm5(to_hash, salt)
167
+ return self.sha256(self.md5(to_hash + salt))
168
+ end
169
+
170
+ def self.osCommerce_AEF(to_hash, salt)
171
+ return self.md5(salt + to_hash)
172
+ end
173
+
174
+ def self.desCrypt(to_hash, salt)
175
+ return UnixCrypt::DES.build(to_hash, salt)
176
+ end
177
+
178
+ def self.convertToUnsigned(val)
179
+ return [val].pack('L').unpack('L').first
180
+ end
181
+
182
+ def self.mySQLPre4_1(to_hash)
183
+ nr = 1345345333
184
+ add = 7
185
+ nr2 = 0x12345671
186
+
187
+ for i in 0..to_hash.length - 1 do
188
+ c = to_hash[i]
189
+
190
+ if c == " " || c == "\t"
191
+ next
192
+ end
193
+
194
+ tmp = c.ord
195
+ nr = nr ^ ((((nr & 63) + add) * tmp) + (self.convertToUnsigned(nr << 8)))
196
+ nr2 += (self.convertToUnsigned(nr2 << 8)) ^ nr
197
+ add += tmp
198
+ end
199
+
200
+ result1 = nr & ((self.convertToUnsigned(1 << 31)) - 1)
201
+ result2 = nr2 & ((self.convertToUnsigned(1 << 31)) - 1)
202
+
203
+ return result1.to_s(16) + result2.to_s(16)
204
+ end
205
+
206
+ def self.mySQLPost4_1(to_hash)
207
+ return "*" + self.bytes_to_hex(self.sha1_binary_array(self.sha1_binary(to_hash)));
208
+ end
209
+
210
+ def self.punBB(to_hash, salt)
211
+ return self.sha1(salt + self.sha1(to_hash))
212
+ end
213
+
214
+ def self.custom_algorithm6(to_hash, salt)
215
+ return self.sha1(to_hash + salt)
216
+ end
217
+
218
+ def self.partial_md5_20(to_hash)
219
+ return self.md5(to_hash)[0..19]
220
+ end
221
+
222
+ def self.partial_md5_29(to_hash)
223
+ return self.md5(to_hash)[0..28]
224
+ end
225
+
226
+ def self.ave_datalife_diferior(to_hash)
227
+ return self.md5(self.md5(to_hash))
228
+ end
229
+
230
+ def self.django_md5(to_hash, salt)
231
+ return "md5$" + salt + "$" + self.md5(salt + to_hash)
232
+ end
233
+
234
+ def self.django_sha1(to_hash, salt)
235
+ return "sha1$" + salt + "$" + self.sha1(salt + to_hash)
236
+ end
237
+
238
+ def self.pligg_cms(to_hash, salt)
239
+ return salt + self.sha1(salt + to_hash)
240
+ end
241
+
242
+ def self.runcms_smf1_1(to_hash, salt)
243
+ return self.sha1(salt + to_hash)
244
+ end
245
+
246
+ def self.ntlm(to_hash)
247
+ pwd = to_hash.dup
248
+ pwd = pwd.dup.force_encoding('UTF-8').encode(Encoding::UTF_16LE, Encoding::UTF_8).force_encoding('UTF-8')
249
+ OpenSSL::Digest::MD4.hexdigest pwd
250
+ end
251
+
252
+ def self.sha1dash(to_hash, salt)
253
+ return self.sha1("--" + salt + "--" + to_hash + "--")
254
+ end
255
+
256
+ def self.sha384(to_hash)
257
+ return Digest::SHA384.hexdigest to_hash
258
+ end
259
+
260
+ def self.custom_algorithm7(to_hash, salt)
261
+ derived_salt = self.sha1(salt)
262
+ return OpenSSL::HMAC.hexdigest("SHA256",
263
+ "d2e1a4c569e7018cc142e9cce755a964bd9b193d2d31f02d80bb589c959afd7e",
264
+ derived_salt + to_hash)
265
+ end
266
+
267
+ def self.custom_algorithm9(to_hash, salt)
268
+ result = self.sha512(to_hash + salt)
269
+ for i in 0..10 do
270
+ result = self.sha512(result)
271
+ end
272
+ return result
273
+ end
274
+
275
+ def self.sha512crypt(to_hash, salt)
276
+ return UnixCrypt::SHA512.build(to_hash, salt.start_with?("$6$") ? salt[3..salt.length] : salt)
277
+ end
278
+
279
+ def self.custom_algorithm10(to_hash, salt)
280
+ return self.sha512(to_hash + ":" + salt)
281
+ end
282
+
283
+ def self.sha256crypt(to_hash, salt)
284
+ salt_to_use = salt
285
+ if salt_to_use.start_with?("$5$")
286
+ salt_to_use = salt_to_use[3..salt.length];
287
+ end
288
+ if salt_to_use.start_with?("rounds=")
289
+ salt_to_use = salt_to_use[salt_to_use.index("$") + 1..salt_to_use.length]
290
+ end
291
+
292
+ return UnixCrypt::SHA256.build(to_hash, salt_to_use)
293
+ end
294
+
295
+ def self.authMeSHA256(to_hash, salt)
296
+ return "$SHA$" + salt + "$" + self.sha256(self.sha256(to_hash) + salt);
297
+ end
298
+
158
299
  def self.argon2_raw(to_hash, salt)
159
300
  time_cost = 3
160
301
  mem_cost = 10
@@ -238,13 +379,13 @@ module Enzoic
238
379
  end
239
380
 
240
381
  def self.xor(byte_array1, byte_array2)
241
- result = Array.new(byte_array1.length);
382
+ result = Array.new(byte_array1.length);
242
383
 
243
- for i in 0..byte_array1.length - 1 do
244
- result[i] = byte_array1[i] ^ byte_array2[i];
245
- end
384
+ for i in 0..byte_array1.length - 1 do
385
+ result[i] = byte_array1[i] ^ byte_array2[i];
386
+ end
246
387
 
247
- return result;
388
+ return result;
248
389
  end
249
390
 
250
391
  def self.bytes_to_hex(bytes)
@@ -18,6 +18,32 @@ module Enzoic
18
18
  SHA512 = 14
19
19
  MD5Crypt = 16
20
20
  CustomAlgorithm4 = 17
21
+ CustomAlgorithm5 = 18
22
+ OsCommerce_AEF = 19
23
+ DESCrypt = 20
24
+ MySQLPre4_1 = 21
25
+ MySQLPost4_1 = 22
26
+ PeopleSoft = 23
27
+ PunBB = 24
28
+ CustomAlgorithm6 = 25
29
+ PartialMD5_20 = 26
30
+ AVE_DataLife_Diferior = 27
31
+ DjangoMD5 = 28
32
+ DjangoSHA1 = 29
33
+ PartialMD5_29 = 30
34
+ PliggCMS = 31
35
+ RunCMS_SMF1_1 = 32
36
+ NTLM = 33
37
+ SHA1Dash = 34
38
+ SHA384 = 35
39
+ CustomAlgorithm7 = 36
40
+ CustomAlgorithm8 = 37
41
+ CustomAlgorithm9 = 38
42
+ SHA512Crypt = 39
43
+ CustomAlgorithm10 = 40
44
+ SHA256Crypt = 41
45
+ AuthMeSHA256 = 42
46
+
21
47
  Unknown = 97
22
48
  UnusablePassword = 98
23
49
  None = 99
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  # Standard Gem version constant.
3
3
  module Enzoic
4
- VERSION = "1.1.3".freeze
4
+ VERSION = "1.2.0".freeze
5
5
  end
data/lib/enzoic.rb CHANGED
@@ -15,61 +15,72 @@ module Enzoic
15
15
  # to access the Enzoic API.
16
16
  class Enzoic
17
17
  def initialize(options = {})
18
- @apiKey = options[:apiKey] || '';
18
+ @apiKey = options[:apiKey] || ''
19
19
  raise EnzoicFail, "No API key provided" if @apiKey == ''
20
- @secret = options[:secret] || '';
20
+ @secret = options[:secret] || ''
21
21
  raise EnzoicFail, "No Secret provided" if @secret == ''
22
22
  @baseURL = options[:baseURL] || "https://api.enzoic.com/v1"
23
23
  @authString = calc_auth_string(@apiKey, @secret)
24
24
  end
25
25
 
26
- def check_credentials(username, password, lastCheckTimestamp = Date.new(1980, 1, 1))
26
+ def check_credentials(username, password, last_check_timestamp = Date.new(1980, 1, 1))
27
27
  raise EnzoicFail, "API key/Secret not set" if !@authString || @authString == ''
28
28
 
29
- response = make_rest_call(@baseURL + Constants::ACCOUNTS_API_PATH + "?username=" + Hashing.sha256(username), "GET", nil)
29
+ response = make_rest_call(@baseURL + Constants::ACCOUNTS_API_PATH +
30
+ "?username=" + Hashing.sha256(username.downcase),
31
+ "GET", nil)
30
32
 
31
- if (response == "404")
33
+ if response == "404"
32
34
  return false
33
35
  end
34
36
 
35
37
  account_response = JSON.parse(response)
36
38
 
37
39
  # if lastCheckTimestamp was provided, see if we need to go any further
38
- if (Date.parse(account_response["lastBreachDate"]) > lastCheckTimestamp)
40
+ if Date.parse(account_response["lastBreachDate"]) > last_check_timestamp
39
41
  hashes_required = account_response["passwordHashesRequired"]
40
42
 
41
43
  bcrypt_count = 0
42
44
  query_string = ""
45
+ credential_hashes = []
43
46
 
44
- for i in 0..hashes_required.length - 1 do
45
- hash_spec = hashes_required[i]
46
-
47
+ hashes_required.each do |hash_spec|
47
48
  # bcrypt gets far too expensive for good response time if there are many of them to calculate.
48
49
  # some mostly garbage accounts have accumulated a number of them in our DB and if we happen to hit one it
49
50
  # kills performance, so short circuit out after at most 2 BCrypt hashes
50
- if (hash_spec["hashType"] != PasswordType::BCrypt || bcrypt_count <= 2)
51
- if (hash_spec["hashType"] == PasswordType::BCrypt)
51
+ if hash_spec["hashType"] != PasswordType::BCrypt || bcrypt_count <= 2
52
+ if hash_spec["hashType"] == PasswordType::BCrypt
52
53
  bcrypt_count = bcrypt_count + 1
53
54
  end
54
55
 
55
- if (hash_spec["hashType"] != nil)
56
- credential_hash = calc_credential_hash(username, password, account_response["salt"], hash_spec);
56
+ if hash_spec["hashType"] != nil
57
+ credential_hash = calc_credential_hash(username.downcase, password, account_response["salt"], hash_spec)
58
+
59
+ if credential_hash != nil
60
+ credential_hashes << credential_hash
57
61
 
58
- if (credential_hash != nil)
59
- if (query_string.length == 0)
60
- query_string = query_string + "?hashes=" + CGI.escape(credential_hash);
62
+ if query_string.length == 0
63
+ query_string = query_string + "?partialHashes=" + CGI.escape(credential_hash[0..6])
61
64
  else
62
- query_string = query_string + "&hashes=" + CGI.escape(credential_hash);
65
+ query_string = query_string + "&partialHashes=" + CGI.escape(credential_hash[0..6])
63
66
  end
64
67
  end
65
68
  end
66
69
  end
67
70
  end
68
71
 
69
- if (query_string.length > 0)
72
+ if query_string.length > 0
70
73
  creds_response = make_rest_call(
71
- @baseURL + Constants::CREDENTIALS_API_PATH + query_string, "GET", nil)
72
- return creds_response != "404"
74
+ @baseURL + Constants::CREDENTIALS_API_PATH + query_string, "GET", nil)
75
+
76
+ if creds_response != "404"
77
+ creds_result = JSON.parse(creds_response, object_class: OpenStruct)
78
+ creds_result.candidateHashes.each do |candidateHash|
79
+ if credential_hashes.include? candidateHash
80
+ return true
81
+ end
82
+ end
83
+ end
73
84
  end
74
85
  end
75
86
 
@@ -77,21 +88,36 @@ module Enzoic
77
88
  end
78
89
 
79
90
  def check_password(password)
91
+ md5 = Hashing.md5(password)
92
+ sha1 = Hashing.sha1(password)
93
+ sha256 = Hashing.sha256(password)
94
+
80
95
  response = make_rest_call(
81
- @baseURL + Constants::PASSWORDS_API_PATH +
82
- "?md5=" + Hashing.md5(password) +
83
- "&sha1=" + Hashing.sha1(password) +
84
- "&sha256=" + Hashing.sha256(password),
85
- "GET", nil)
96
+ @baseURL + Constants::PASSWORDS_API_PATH, "POST",
97
+ '{' +
98
+ '"partialMD5":"' + md5[0..6] + '",' +
99
+ '"partialSHA1":"' + sha1[0..6] + '",' +
100
+ '"partialSHA256":"' + sha256[0..6] + '"' +
101
+ '}')
86
102
 
87
- return response != "404"
103
+ if response != "404"
104
+ result = JSON.parse(response, object_class: OpenStruct)
105
+
106
+ result.candidates.each do |candidate|
107
+ if candidate.md5 == md5 || candidate.sha1 == sha1 || candidate.sha256 == sha256
108
+ return true
109
+ end
110
+ end
111
+ end
112
+
113
+ return false
88
114
  end
89
115
 
90
116
  def get_exposures_for_user(username)
91
- response = make_rest_call(@baseURL + Constants::EXPOSURES_API_PATH + "?username=" + Hashing.sha256(username),
92
- "GET", nil)
117
+ response = make_rest_call(@baseURL + Constants::EXPOSURES_API_PATH + "?username=" + Hashing.sha256(username.downcase),
118
+ "GET", nil)
93
119
 
94
- if (response == "404")
120
+ if response == "404"
95
121
  # don't have this email in the DB - return empty response
96
122
  return JSON.parse('{ "count": 0, "exposures": [] }', object_class: OpenStruct)
97
123
  else
@@ -102,9 +128,9 @@ module Enzoic
102
128
 
103
129
  def get_exposure_details(exposure_id)
104
130
  response = make_rest_call(@baseURL + Constants::EXPOSURES_API_PATH + "?id=" + CGI.escape(exposure_id),
105
- "GET", nil)
131
+ "GET", nil)
106
132
 
107
- if (response != "404")
133
+ if response != "404"
108
134
  # deserialize response
109
135
  return JSON.parse(response, object_class: OpenStruct)
110
136
  else
@@ -112,82 +138,176 @@ module Enzoic
112
138
  end
113
139
  end
114
140
 
115
- private
116
- def make_rest_call(rest_url, method, body)
117
- begin
118
- response = RestClient::Request.execute(method: method, url: rest_url,
119
- headers: { content_type: :json, accept: :json, authorization: @authString })
120
- return response.body
121
- rescue RestClient::NotFound
122
- return "404"
123
- end
141
+ def get_passwords_for_user(username)
142
+ response = make_rest_call(@baseURL + Constants::ACCOUNTS_API_PATH + "?username=" +
143
+ Hashing.sha256(username.downcase) + "&includePasswords=1",
144
+ "GET", nil)
145
+
146
+ if response == "404"
147
+ # don't have this email in the DB - return empty response
148
+ return JSON.parse('{ "lastBreachDate": null, "passwords": [] }', object_class: OpenStruct)
149
+ else
150
+ # deserialize response
151
+ return JSON.parse(response, object_class: OpenStruct)
124
152
  end
153
+ end
125
154
 
126
- def calc_credential_hash(username, password, salt, hash_spec)
127
- password_hash = calc_password_hash(hash_spec["hashType"], password, hash_spec["salt"])
155
+ private
128
156
 
129
- if (password_hash != nil)
130
- return Hashing.argon2_raw(username + "$" + password_hash, salt)
131
- else
132
- return nil
133
- end
157
+ def make_rest_call(rest_url, method, body)
158
+ begin
159
+ response = RestClient::Request.execute(method: method, url: rest_url,
160
+ payload: body,
161
+ headers: { content_type: :json, accept: :json, authorization: @authString })
162
+ return response.body
163
+ rescue RestClient::NotFound
164
+ return "404"
134
165
  end
166
+ end
135
167
 
136
- def calc_password_hash(password_type, password, salt)
137
- case password_type
138
- when PasswordType::MD5
139
- return Hashing.md5(password)
140
- when PasswordType::SHA1
141
- return Hashing.sha1(password)
142
- when PasswordType::SHA256
143
- return Hashing.sha256(password)
144
- when PasswordType::SHA512
145
- return Hashing.sha512(password)
146
- when PasswordType::IPBoard_MyBB
147
- if (salt != nil && salt.length > 0)
148
- return Hashing.mybb(password, salt)
149
- end
150
- when PasswordType::VBulletinPre3_8_5
151
- if (salt != nil && salt.length > 0)
152
- return Hashing.vbulletin(password, salt)
153
- end
154
- when PasswordType::VBulletinPost3_8_5
155
- if (salt != nil && salt.length > 0)
156
- return Hashing.vbulletin(password, salt)
157
- end
158
- when PasswordType::BCrypt
159
- if (salt != nil && salt.length > 0)
160
- return Hashing.bcrypt(password, salt)
161
- end
162
- when PasswordType::CRC32
163
- return Hashing.crc32(password)
164
- when PasswordType::PHPBB3
165
- if (salt != nil && salt.length > 0)
166
- return Hashing.phpbb3(password, salt)
167
- end
168
- when PasswordType::CustomAlgorithm1
169
- if (salt != nil && salt.length > 0)
170
- return Hashing.custom_algorithm1(password, salt)
171
- end
172
- when PasswordType::CustomAlgorithm2
173
- if (salt != nil && salt.length > 0)
174
- return Hashing.custom_algorithm2(password, salt)
175
- end
176
- when PasswordType::MD5Crypt
177
- if (salt != nil && salt.length > 0)
178
- return Hashing.md5crypt(password, salt)
179
- end
180
- when PasswordType::CustomAlgorithm4
181
- if (salt != nil && salt.length > 0)
182
- return Hashing.custom_algorithm4(password, salt)
183
- end
184
- end
168
+ def calc_credential_hash(username, password, salt, hash_spec)
169
+ password_hash = calc_password_hash(hash_spec["hashType"], password, hash_spec["salt"])
185
170
 
171
+ if password_hash != nil
172
+ return Hashing.argon2_raw(username.downcase + "$" + password_hash, salt)
173
+ else
186
174
  return nil
187
175
  end
176
+ end
188
177
 
189
- def calc_auth_string(apiKey, secret)
190
- return "basic " + Base64.strict_encode64(apiKey + ":" + secret);
178
+ def calc_password_hash(password_type, password, salt)
179
+ case password_type
180
+ when PasswordType::MD5
181
+ return Hashing.md5(password)
182
+ when PasswordType::SHA1
183
+ return Hashing.sha1(password)
184
+ when PasswordType::SHA256
185
+ return Hashing.sha256(password)
186
+ when PasswordType::SHA512
187
+ return Hashing.sha512(password)
188
+ when PasswordType::IPBoard_MyBB
189
+ if salt != nil && salt.length > 0
190
+ return Hashing.mybb(password, salt)
191
+ end
192
+ when PasswordType::VBulletinPre3_8_5
193
+ if salt != nil && salt.length > 0
194
+ return Hashing.vbulletin(password, salt)
195
+ end
196
+ when PasswordType::VBulletinPost3_8_5
197
+ if salt != nil && salt.length > 0
198
+ return Hashing.vbulletin(password, salt)
199
+ end
200
+ when PasswordType::BCrypt
201
+ if salt != nil && salt.length > 0
202
+ return Hashing.bcrypt(password, salt)
203
+ end
204
+ when PasswordType::CRC32
205
+ return Hashing.crc32(password)
206
+ when PasswordType::PHPBB3
207
+ if salt != nil && salt.length > 0
208
+ return Hashing.phpbb3(password, salt)
209
+ end
210
+ when PasswordType::CustomAlgorithm1
211
+ if salt != nil && salt.length > 0
212
+ return Hashing.custom_algorithm1(password, salt)
213
+ end
214
+ when PasswordType::CustomAlgorithm2
215
+ if salt != nil && salt.length > 0
216
+ return Hashing.custom_algorithm2(password, salt)
217
+ end
218
+ when PasswordType::MD5Crypt
219
+ if salt != nil && salt.length > 0
220
+ return Hashing.md5crypt(password, salt)
221
+ end
222
+ when PasswordType::CustomAlgorithm4
223
+ if salt != nil && salt.length > 0
224
+ return Hashing.custom_algorithm4(password, salt)
225
+ end
226
+ when PasswordType::CustomAlgorithm5
227
+ if salt != nil && salt.length > 0
228
+ return Hashing.custom_algorithm5(password, salt)
229
+ end
230
+ when PasswordType::OsCommerce_AEF
231
+ if salt != nil && salt.length > 0
232
+ return Hashing.osCommerce_AEF(password, salt)
233
+ end
234
+ when PasswordType::DESCrypt
235
+ if salt != nil && salt.length > 0
236
+ return Hashing.desCrypt(password, salt)
237
+ end
238
+ when PasswordType::MySQLPre4_1
239
+ return Hashing.mySQLPre4_1(password)
240
+ when PasswordType::MySQLPost4_1
241
+ return Hashing.mySQLPost4_1(password)
242
+ when PasswordType::PunBB
243
+ if salt != nil && salt.length > 0
244
+ return Hashing.punBB(password, salt)
245
+ end
246
+ when PasswordType::CustomAlgorithm6
247
+ if salt != nil && salt.length > 0
248
+ return Hashing.custom_algorithm6(password, salt)
249
+ end
250
+ when PasswordType::PartialMD5_20
251
+ return Hashing.partial_md5_20(password)
252
+ when PasswordType::AVE_DataLife_Diferior
253
+ return Hashing.ave_datalife_diferior(password)
254
+ when PasswordType::DjangoMD5
255
+ if salt != nil && salt.length > 0
256
+ return Hashing.django_md5(password, salt)
257
+ end
258
+ when PasswordType::DjangoSHA1
259
+ if salt != nil && salt.length > 0
260
+ return Hashing.django_sha1(password, salt)
261
+ end
262
+ when PasswordType::PartialMD5_29
263
+ return Hashing.partial_md5_29(password)
264
+ when PasswordType::PliggCMS
265
+ if salt != nil && salt.length > 0
266
+ return Hashing.pligg_cms(password, salt)
267
+ end
268
+ when PasswordType::RunCMS_SMF1_1
269
+ if salt != nil && salt.length > 0
270
+ return Hashing.runcms_smf1_1(password, salt)
271
+ end
272
+ when PasswordType::NTLM
273
+ return Hashing.ntlm(password)
274
+ when PasswordType::SHA1Dash
275
+ if salt != nil && salt.length > 0
276
+ return Hashing.sha1dash(password, salt)
277
+ end
278
+ when PasswordType::SHA384
279
+ return Hashing.sha384(password)
280
+ when PasswordType::CustomAlgorithm7
281
+ if salt != nil && salt.length > 0
282
+ return Hashing.custom_algorithm7(password, salt)
283
+ end
284
+ when PasswordType::CustomAlgorithm9
285
+ if salt != nil && salt.length > 0
286
+ return Hashing.custom_algorithm9(password, salt)
287
+ end
288
+ when PasswordType::SHA512Crypt
289
+ if salt != nil && salt.length > 0
290
+ return Hashing.sha512crypt(password, salt)
291
+ end
292
+ when PasswordType::CustomAlgorithm10
293
+ if salt != nil && salt.length > 0
294
+ return Hashing.custom_algorithm10(password, salt)
295
+ end
296
+ when PasswordType::SHA256Crypt
297
+ if salt != nil && salt.length > 0
298
+ return Hashing.sha256crypt(password, salt)
299
+ end
300
+ when PasswordType::AuthMeSHA256
301
+ if salt != nil && salt.length > 0
302
+ return Hashing.authMeSHA256(password, salt)
303
+ end
304
+ else
305
+ return nil
191
306
  end
307
+ end
308
+
309
+ def calc_auth_string(api_key, secret)
310
+ return "basic " + Base64.strict_encode64(api_key + ":" + secret)
311
+ end
192
312
  end
193
313
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enzoic
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Enzoic
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-08-27 00:00:00.000000000 Z
11
+ date: 2022-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -116,22 +116,22 @@ dependencies:
116
116
  name: bundler
117
117
  requirement: !ruby/object:Gem::Requirement
118
118
  requirements:
119
- - - "~>"
120
- - !ruby/object:Gem::Version
121
- version: 2.0.2
122
119
  - - ">="
123
120
  - !ruby/object:Gem::Version
124
- version: 2.0.2
121
+ version: 2.2.11
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 2.2.11
125
125
  type: :development
126
126
  prerelease: false
127
127
  version_requirements: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: 2.0.2
132
129
  - - ">="
133
130
  - !ruby/object:Gem::Version
134
- version: 2.0.2
131
+ version: 2.2.11
132
+ - - "~>"
133
+ - !ruby/object:Gem::Version
134
+ version: 2.2.11
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: rake
137
137
  requirement: !ruby/object:Gem::Requirement
@@ -307,8 +307,8 @@ files:
307
307
  - ext/phc-winner-argon2/src/genkat.c
308
308
  - ext/phc-winner-argon2/src/genkat.h
309
309
  - ext/phc-winner-argon2/src/opt.c
310
- - ext/phc-winner-argon2/src/opt.o
311
310
  - ext/phc-winner-argon2/src/ref.c
311
+ - ext/phc-winner-argon2/src/ref.o
312
312
  - ext/phc-winner-argon2/src/run.c
313
313
  - ext/phc-winner-argon2/src/test.c
314
314
  - ext/phc-winner-argon2/src/thread.c
@@ -361,8 +361,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
361
361
  - !ruby/object:Gem::Version
362
362
  version: '0'
363
363
  requirements: []
364
- rubyforge_project:
365
- rubygems_version: 2.5.2.3
364
+ rubygems_version: 3.0.3.1
366
365
  signing_key:
367
366
  specification_version: 4
368
367
  summary: Ruby library for Enzoic API
Binary file