enzoic 1.0.3 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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