enzoic 1.0.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: f384606d64ea5eac9f13b2467ab4e494d7043312
4
- data.tar.gz: 7f3d428ada763102e27d26aba7ee5172169e5bee
2
+ SHA256:
3
+ metadata.gz: 2af7917c4ee90414cdffeda3948ce2a0642f523f6c44fe07db64deab4f5b6e25
4
+ data.tar.gz: 4cdfeb61e75c47f95132e9a0c644f89a987597a48685038ac7308dba66e008ee
5
5
  SHA512:
6
- metadata.gz: 7a6da77a5e86c97d835e50378c67423c6197f771d5647216d9c7613d7cf402ff6705dbf9e20fce28796bf8957741a3d7459c6dbec0aead19f0ff9e3a7bc4b09e
7
- data.tar.gz: 20356c44bacd22fa24ea58ee85515acecb44326b4fc5b46ee233ad0b132727b8b61594053e2c91df1a4c5300277f0bcda1c7691acf14ed5b126e59bc265e55b1
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,19 +43,40 @@ 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
48
50
  puts("Credentials are not compromised")
49
51
  end
50
52
 
53
+ # Check whether a specific set of credentials are compromised, using the optional
54
+ # lastCheckData parameter.
55
+ # lastCheckDate is the timestamp for the last check you performed for this user.
56
+ # If the DateTime you provide for the last check is greater than the timestamp Enzoic has
57
+ # for the last breach affecting this user, the check will not be performed.
58
+ # This can be used to substantially increase performance.
59
+ if enzoic.check_credentials("test@enzoic.com", "password-to-test", DateTime.parse("2019-07-15T19:57:43.000Z"))
60
+ puts("Credentials are compromised")
61
+ else
62
+ puts("Credentials are not compromised")
63
+ end
64
+
51
65
  # get all exposures for a given user
66
+ # see https://www.enzoic.com/docs-exposures-api/#get-exposures for more information
52
67
  exposures = enzoic.get_exposures_for_user("test@enzoic.com")
53
68
  puts(exposures.count.to_s + " exposures found for test@enzoic.com")
54
69
 
55
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
56
72
  details = enzoic.get_exposure_details(exposures.exposures[0])
57
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
+
58
80
  ```
59
81
 
60
82
  More information in reference format can be found below.
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
@@ -0,0 +1,20 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>English</string>
7
+ <key>CFBundleIdentifier</key>
8
+ <string>com.apple.xcode.dsym.argon2</string>
9
+ <key>CFBundleInfoDictionaryVersion</key>
10
+ <string>6.0</string>
11
+ <key>CFBundlePackageType</key>
12
+ <string>dSYM</string>
13
+ <key>CFBundleSignature</key>
14
+ <string>????</string>
15
+ <key>CFBundleShortVersionString</key>
16
+ <string>1.0</string>
17
+ <key>CFBundleVersion</key>
18
+ <string>1</string>
19
+ </dict>
20
+ </plist>
@@ -0,0 +1,20 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>English</string>
7
+ <key>CFBundleIdentifier</key>
8
+ <string>com.apple.xcode.dsym.libargon2.0.dylib</string>
9
+ <key>CFBundleInfoDictionaryVersion</key>
10
+ <string>6.0</string>
11
+ <key>CFBundlePackageType</key>
12
+ <string>dSYM</string>
13
+ <key>CFBundleSignature</key>
14
+ <string>????</string>
15
+ <key>CFBundleShortVersionString</key>
16
+ <string>1.0</string>
17
+ <key>CFBundleVersion</key>
18
+ <string>1</string>
19
+ </dict>
20
+ </plist>
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.0.3".freeze
4
+ VERSION = "1.2.0".freeze
5
5
  end
data/lib/enzoic.rb CHANGED
@@ -15,79 +15,109 @@ 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)
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
- hashes_required = account_response["passwordHashesRequired"]
37
38
 
38
- bcrypt_count = 0
39
- query_string = ""
39
+ # if lastCheckTimestamp was provided, see if we need to go any further
40
+ if Date.parse(account_response["lastBreachDate"]) > last_check_timestamp
41
+ hashes_required = account_response["passwordHashesRequired"]
40
42
 
41
- for i in 0..hashes_required.length - 1 do
42
- hash_spec = hashes_required[i]
43
+ bcrypt_count = 0
44
+ query_string = ""
45
+ credential_hashes = []
43
46
 
44
- # bcrypt gets far too expensive for good response time if there are many of them to calculate.
45
- # some mostly garbage accounts have accumulated a number of them in our DB and if we happen to hit one it
46
- # kills performance, so short circuit out after at most 2 BCrypt hashes
47
- if (hash_spec["hashType"] != PasswordType::BCrypt || bcrypt_count <= 2)
48
- if (hash_spec["hashType"] == PasswordType::BCrypt)
49
- bcrypt_count = bcrypt_count + 1
50
- end
47
+ hashes_required.each do |hash_spec|
48
+ # bcrypt gets far too expensive for good response time if there are many of them to calculate.
49
+ # some mostly garbage accounts have accumulated a number of them in our DB and if we happen to hit one it
50
+ # kills performance, so short circuit out after at most 2 BCrypt hashes
51
+ if hash_spec["hashType"] != PasswordType::BCrypt || bcrypt_count <= 2
52
+ if hash_spec["hashType"] == PasswordType::BCrypt
53
+ bcrypt_count = bcrypt_count + 1
54
+ end
55
+
56
+ if hash_spec["hashType"] != nil
57
+ credential_hash = calc_credential_hash(username.downcase, password, account_response["salt"], hash_spec)
51
58
 
52
- if (hash_spec["hashType"] != nil)
53
- credential_hash = calc_credential_hash(username, password, account_response["salt"], hash_spec);
59
+ if credential_hash != nil
60
+ credential_hashes << credential_hash
54
61
 
55
- if (credential_hash != nil)
56
- if (query_string.length == 0)
57
- query_string = query_string + "?hashes=" + CGI.escape(credential_hash);
58
- else
59
- 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])
64
+ else
65
+ query_string = query_string + "&partialHashes=" + CGI.escape(credential_hash[0..6])
66
+ end
60
67
  end
61
68
  end
62
69
  end
63
70
  end
64
- end
65
71
 
66
- if (query_string.length > 0)
67
- creds_response = make_rest_call(
68
- @baseURL + Constants::CREDENTIALS_API_PATH + query_string, "GET", nil)
69
- return creds_response != "404"
72
+ if query_string.length > 0
73
+ creds_response = make_rest_call(
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
84
+ end
70
85
  end
71
86
 
72
87
  return false
73
88
  end
74
89
 
75
90
  def check_password(password)
91
+ md5 = Hashing.md5(password)
92
+ sha1 = Hashing.sha1(password)
93
+ sha256 = Hashing.sha256(password)
94
+
76
95
  response = make_rest_call(
77
- @baseURL + Constants::PASSWORDS_API_PATH +
78
- "?md5=" + Hashing.md5(password) +
79
- "&sha1=" + Hashing.sha1(password) +
80
- "&sha256=" + Hashing.sha256(password),
81
- "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
+ '}')
102
+
103
+ if response != "404"
104
+ result = JSON.parse(response, object_class: OpenStruct)
82
105
 
83
- return response != "404"
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
84
114
  end
85
115
 
86
116
  def get_exposures_for_user(username)
87
- response = make_rest_call(@baseURL + Constants::EXPOSURES_API_PATH + "?username=" + Hashing.sha256(username),
88
- "GET", nil)
117
+ response = make_rest_call(@baseURL + Constants::EXPOSURES_API_PATH + "?username=" + Hashing.sha256(username.downcase),
118
+ "GET", nil)
89
119
 
90
- if (response == "404")
120
+ if response == "404"
91
121
  # don't have this email in the DB - return empty response
92
122
  return JSON.parse('{ "count": 0, "exposures": [] }', object_class: OpenStruct)
93
123
  else
@@ -98,9 +128,9 @@ module Enzoic
98
128
 
99
129
  def get_exposure_details(exposure_id)
100
130
  response = make_rest_call(@baseURL + Constants::EXPOSURES_API_PATH + "?id=" + CGI.escape(exposure_id),
101
- "GET", nil)
131
+ "GET", nil)
102
132
 
103
- if (response != "404")
133
+ if response != "404"
104
134
  # deserialize response
105
135
  return JSON.parse(response, object_class: OpenStruct)
106
136
  else
@@ -108,82 +138,176 @@ module Enzoic
108
138
  end
109
139
  end
110
140
 
111
- private
112
- def make_rest_call(rest_url, method, body)
113
- begin
114
- response = RestClient::Request.execute(method: method, url: rest_url,
115
- headers: { content_type: :json, accept: :json, authorization: @authString })
116
- return response.body
117
- rescue RestClient::NotFound
118
- return "404"
119
- 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)
120
152
  end
153
+ end
121
154
 
122
- def calc_credential_hash(username, password, salt, hash_spec)
123
- password_hash = calc_password_hash(hash_spec["hashType"], password, hash_spec["salt"])
155
+ private
124
156
 
125
- if (password_hash != nil)
126
- return Hashing.argon2_raw(username + "$" + password_hash, salt)
127
- else
128
- return nil
129
- 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"
130
165
  end
166
+ end
131
167
 
132
- def calc_password_hash(password_type, password, salt)
133
- case password_type
134
- when PasswordType::MD5
135
- return Hashing.md5(password)
136
- when PasswordType::SHA1
137
- return Hashing.sha1(password)
138
- when PasswordType::SHA256
139
- return Hashing.sha256(password)
140
- when PasswordType::SHA512
141
- return Hashing.sha512(password)
142
- when PasswordType::IPBoard_MyBB
143
- if (salt != nil && salt.length > 0)
144
- return Hashing.mybb(password, salt)
145
- end
146
- when PasswordType::VBulletinPre3_8_5
147
- if (salt != nil && salt.length > 0)
148
- return Hashing.vbulletin(password, salt)
149
- end
150
- when PasswordType::VBulletinPost3_8_5
151
- if (salt != nil && salt.length > 0)
152
- return Hashing.vbulletin(password, salt)
153
- end
154
- when PasswordType::BCrypt
155
- if (salt != nil && salt.length > 0)
156
- return Hashing.bcrypt(password, salt)
157
- end
158
- when PasswordType::CRC32
159
- return Hashing.crc32(password)
160
- when PasswordType::PHPBB3
161
- if (salt != nil && salt.length > 0)
162
- return Hashing.phpbb3(password, salt)
163
- end
164
- when PasswordType::CustomAlgorithm1
165
- if (salt != nil && salt.length > 0)
166
- return Hashing.custom_algorithm1(password, salt)
167
- end
168
- when PasswordType::CustomAlgorithm2
169
- if (salt != nil && salt.length > 0)
170
- return Hashing.custom_algorithm2(password, salt)
171
- end
172
- when PasswordType::MD5Crypt
173
- if (salt != nil && salt.length > 0)
174
- return Hashing.md5crypt(password, salt)
175
- end
176
- when PasswordType::CustomAlgorithm4
177
- if (salt != nil && salt.length > 0)
178
- return Hashing.custom_algorithm4(password, salt)
179
- end
180
- end
168
+ def calc_credential_hash(username, password, salt, hash_spec)
169
+ password_hash = calc_password_hash(hash_spec["hashType"], password, hash_spec["salt"])
181
170
 
171
+ if password_hash != nil
172
+ return Hashing.argon2_raw(username.downcase + "$" + password_hash, salt)
173
+ else
182
174
  return nil
183
175
  end
176
+ end
184
177
 
185
- def calc_auth_string(apiKey, secret)
186
- 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
187
306
  end
307
+ end
308
+
309
+ def calc_auth_string(api_key, secret)
310
+ return "basic " + Base64.strict_encode64(api_key + ":" + secret)
311
+ end
188
312
  end
189
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.0.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-07-02 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
@@ -230,9 +230,11 @@ files:
230
230
  - Rakefile
231
231
  - enzoic.gemspec
232
232
  - ext/.DS_Store
233
+ - ext/argon2-wrapper/.DS_Store
233
234
  - ext/argon2-wrapper/Makefile
234
235
  - ext/argon2-wrapper/argon2-wrapper.c
235
236
  - ext/argon2-wrapper/extconf.rb
237
+ - ext/argon2-wrapper/libargon2-wrapper.bundle
236
238
  - ext/argon2_import/.DS_Store
237
239
  - ext/digest/whirlpool/extconf.rb
238
240
  - ext/digest/whirlpool/whirlpool-algorithm.c
@@ -251,7 +253,10 @@ files:
251
253
  - ext/phc-winner-argon2/Makefile
252
254
  - ext/phc-winner-argon2/README.md
253
255
  - ext/phc-winner-argon2/appveyor.yml
256
+ - ext/phc-winner-argon2/argon2
254
257
  - ext/phc-winner-argon2/argon2-specs.pdf
258
+ - ext/phc-winner-argon2/argon2.dSYM/Contents/Info.plist
259
+ - ext/phc-winner-argon2/argon2.dSYM/Contents/Resources/DWARF/argon2
255
260
  - ext/phc-winner-argon2/export.sh
256
261
  - ext/phc-winner-argon2/include/argon2.h
257
262
  - ext/phc-winner-argon2/kats/argon2d
@@ -278,27 +283,37 @@ files:
278
283
  - ext/phc-winner-argon2/latex/pics/generic.pdf
279
284
  - ext/phc-winner-argon2/latex/pics/power-distribution.jpg
280
285
  - ext/phc-winner-argon2/latex/tradeoff.bib
286
+ - ext/phc-winner-argon2/libargon2.0.dylib
287
+ - ext/phc-winner-argon2/libargon2.0.dylib.dSYM/Contents/Info.plist
288
+ - ext/phc-winner-argon2/libargon2.0.dylib.dSYM/Contents/Resources/DWARF/libargon2.0.dylib
289
+ - ext/phc-winner-argon2/libargon2.a
281
290
  - ext/phc-winner-argon2/libargon2.pc
282
291
  - ext/phc-winner-argon2/man/argon2.1
283
292
  - ext/phc-winner-argon2/src/argon2.c
293
+ - ext/phc-winner-argon2/src/argon2.o
284
294
  - ext/phc-winner-argon2/src/bench.c
285
295
  - ext/phc-winner-argon2/src/blake2/blake2-impl.h
286
296
  - ext/phc-winner-argon2/src/blake2/blake2.h
287
297
  - ext/phc-winner-argon2/src/blake2/blake2b.c
298
+ - ext/phc-winner-argon2/src/blake2/blake2b.o
288
299
  - ext/phc-winner-argon2/src/blake2/blamka-round-opt.h
289
300
  - ext/phc-winner-argon2/src/blake2/blamka-round-ref.h
290
301
  - ext/phc-winner-argon2/src/core.c
291
302
  - ext/phc-winner-argon2/src/core.h
303
+ - ext/phc-winner-argon2/src/core.o
292
304
  - ext/phc-winner-argon2/src/encoding.c
293
305
  - ext/phc-winner-argon2/src/encoding.h
306
+ - ext/phc-winner-argon2/src/encoding.o
294
307
  - ext/phc-winner-argon2/src/genkat.c
295
308
  - ext/phc-winner-argon2/src/genkat.h
296
309
  - ext/phc-winner-argon2/src/opt.c
297
310
  - ext/phc-winner-argon2/src/ref.c
311
+ - ext/phc-winner-argon2/src/ref.o
298
312
  - ext/phc-winner-argon2/src/run.c
299
313
  - ext/phc-winner-argon2/src/test.c
300
314
  - ext/phc-winner-argon2/src/thread.c
301
315
  - ext/phc-winner-argon2/src/thread.h
316
+ - ext/phc-winner-argon2/src/thread.o
302
317
  - ext/phc-winner-argon2/vs2015/Argon2Opt/Argon2Opt.vcxproj
303
318
  - ext/phc-winner-argon2/vs2015/Argon2Opt/Argon2Opt.vcxproj.filters
304
319
  - ext/phc-winner-argon2/vs2015/Argon2OptBench/Argon2OptBench.vcxproj
@@ -346,8 +361,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
346
361
  - !ruby/object:Gem::Version
347
362
  version: '0'
348
363
  requirements: []
349
- rubyforge_project:
350
- rubygems_version: 2.5.2.3
364
+ rubygems_version: 3.0.3.1
351
365
  signing_key:
352
366
  specification_version: 4
353
367
  summary: Ruby library for Enzoic API