Class: Enzoic::Hashing

Inherits:
Object
  • Object
show all
Defined in:
lib/enzoic/hashing.rb

Class Method Summary collapse

Class Method Details

.argon2(to_hash, salt) ⇒ Object



364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
# File 'lib/enzoic/hashing.rb', line 364

def self.argon2(to_hash, salt)
  time_cost = 3
  mem_cost = 10
  threads = 2
  hash_length = 20
  just_salt = salt

  #$argon2i$v=19$m=65536,t=2,p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG
  if (salt[0..6] == "$argon2")
    # looks like we specified algo info for argon2 in the salt
    salt_values = salt.split("$")
    just_salt = Base64URL.decode(salt_values[4])
    cost_params = salt_values[3].split(",")

    for param in cost_params
      begin
        param_parts = param.split("=")
        if (param_parts[0] == "t")
          time_cost = Integer(param_parts[1])
        elsif (param_parts[0] == "m")
          mem_cost = Math.log2(Integer(param_parts[1])).round
        elsif (param_parts[0] == "p")
          threads = Integer(param_parts[1])
        elsif (param_parts[0] == "l")
          hash_length = Integer(param_parts[1])
        end
      rescue ArgumentError
        # ignore invalid params and just use default
      end
    end

    if (salt_values[1] == "argon2i")
      return Argon2Wrapper.hash_argon2i_encode(to_hash, just_salt, time_cost, mem_cost, threads, hash_length)
    else
      return Argon2Wrapper.hash_argon2d_encode(to_hash, just_salt, time_cost, mem_cost, threads, hash_length)
    end
  else
    return Argon2Wrapper.hash_argon2d_encode(to_hash, just_salt, time_cost, mem_cost, threads, hash_length)
  end
end

.argon2_raw(to_hash, salt) ⇒ Object



323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/enzoic/hashing.rb', line 323

def self.argon2_raw(to_hash, salt)
  time_cost = 3
  mem_cost = 10
  threads = 2
  hash_length = 20
  just_salt = salt

  #$argon2i$v=19$m=65536,t=2,p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG
  if (salt[0..6] == "$argon2")
    # looks like we specified algo info for argon2 in the salt
    salt_values = salt.split("$")
    just_salt = Base64URL.decode(salt_values[4])
    cost_params = salt_values[3].split(",")

    for param in cost_params
      begin
        param_parts = param.split("=")
        if (param_parts[0] == "t")
          time_cost = Integer(param_parts[1])
        elsif (param_parts[0] == "m")
          mem_cost = Math.log2(Integer(param_parts[1])).round
        elsif (param_parts[0] == "p")
          threads = Integer(param_parts[1])
        elsif (param_parts[0] == "l")
          hash_length = Integer(param_parts[1])
        end
      rescue ArgumentError
        # ignore invalid params and just use default
      end
    end

    if (salt_values[1] == "argon2i")
      return Argon2Wrapper.hash_argon2i(to_hash, just_salt, time_cost, mem_cost, threads, hash_length)
    else
      return Argon2Wrapper.hash_argon2d(to_hash, just_salt, time_cost, mem_cost, threads, hash_length)
    end
  else
    return Argon2Wrapper.hash_argon2d(to_hash, just_salt, time_cost, mem_cost, threads, hash_length)
  end
end

.authMeSHA256(to_hash, salt) ⇒ Object



319
320
321
# File 'lib/enzoic/hashing.rb', line 319

def self.authMeSHA256(to_hash, salt)
  return "$SHA$" + salt + "$" + self.sha256(self.sha256(to_hash) + salt);
end

.ave_datalife_diferior(to_hash) ⇒ Object



227
228
229
# File 'lib/enzoic/hashing.rb', line 227

def self.ave_datalife_diferior(to_hash)
  return self.md5(self.md5(to_hash))
end

.bcrypt(to_hash, salt) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/enzoic/hashing.rb', line 76

def self.bcrypt(to_hash, salt)
  # if salt starts with $2y$, first replace with $2a$
  if salt[0..3] == "$2y$"
    y_variant = true
    checked_salt = "$2a$" + salt[4..-1]
  else
    y_variant = false
    checked_salt = salt
  end

  result = BCrypt::Engine.hash_secret(to_hash, checked_salt)

  if y_variant
    # replace with $2y$
    result = "$2y$" + result[4..-1]
  end

  return result
end

.bytes_to_hex(bytes) ⇒ Object



415
416
417
# File 'lib/enzoic/hashing.rb', line 415

def self.bytes_to_hex(bytes)
  return bytes.pack('c*').unpack('H*')[0]
end

.convertToUnsigned(val) ⇒ Object



179
180
181
# File 'lib/enzoic/hashing.rb', line 179

def self.convertToUnsigned(val)
  return [val].pack('L').unpack('L').first
end

.crc32(to_hash) ⇒ Object



64
65
66
# File 'lib/enzoic/hashing.rb', line 64

def self.crc32(to_hash)
  return Zlib.crc32(to_hash, 0).to_s(16)
end

.custom_algorithm1(to_hash, salt) ⇒ Object



151
152
153
# File 'lib/enzoic/hashing.rb', line 151

def self.custom_algorithm1(to_hash, salt)
  return self.bytes_to_hex(self.xor(self.sha512_binary_array(to_hash + salt), self.whirlpool_binary_array(salt + to_hash)))
end

.custom_algorithm10(to_hash, salt) ⇒ Object



311
312
313
# File 'lib/enzoic/hashing.rb', line 311

def self.custom_algorithm10(to_hash, salt)
  return self.sha512(to_hash + ":" + salt)
end

.custom_algorithm2(to_hash, salt) ⇒ Object



155
156
157
# File 'lib/enzoic/hashing.rb', line 155

def self.custom_algorithm2(to_hash, salt)
  return self.md5(to_hash + salt)
end

.custom_algorithm4(to_hash, salt) ⇒ Object



163
164
165
# File 'lib/enzoic/hashing.rb', line 163

def self.custom_algorithm4(to_hash, salt)
  return self.bcrypt(self.md5(to_hash), salt)
end

.custom_algorithm5(to_hash, salt) ⇒ Object



167
168
169
# File 'lib/enzoic/hashing.rb', line 167

def self.custom_algorithm5(to_hash, salt)
  return self.sha256(self.md5(to_hash + salt))
end

.custom_algorithm6(to_hash, salt) ⇒ Object



215
216
217
# File 'lib/enzoic/hashing.rb', line 215

def self.custom_algorithm6(to_hash, salt)
  return self.sha1(to_hash + salt)
end

.custom_algorithm7(to_hash, salt) ⇒ Object



261
262
263
264
265
266
# File 'lib/enzoic/hashing.rb', line 261

def self.custom_algorithm7(to_hash, salt)
  derived_salt = self.sha1(salt)
  return OpenSSL::HMAC.hexdigest("SHA256",
                                 "d2e1a4c569e7018cc142e9cce755a964bd9b193d2d31f02d80bb589c959afd7e",
                                 derived_salt + to_hash)
end

.custom_algorithm9(to_hash, salt) ⇒ Object



268
269
270
271
272
273
274
# File 'lib/enzoic/hashing.rb', line 268

def self.custom_algorithm9(to_hash, salt)
  result = self.sha512(to_hash + salt)
  for i in 0..10 do
    result = self.sha512(result)
  end
  return result
end

.desCrypt(to_hash, salt) ⇒ Object



175
176
177
# File 'lib/enzoic/hashing.rb', line 175

def self.desCrypt(to_hash, salt)
  return UnixCrypt::DES.build(to_hash, salt)
end

.django_md5(to_hash, salt) ⇒ Object



231
232
233
# File 'lib/enzoic/hashing.rb', line 231

def self.django_md5(to_hash, salt)
  return "md5$" + salt + "$" + self.md5(salt + to_hash)
end

.django_sha1(to_hash, salt) ⇒ Object



235
236
237
# File 'lib/enzoic/hashing.rb', line 235

def self.django_sha1(to_hash, salt)
  return "sha1$" + salt + "$" + self.sha1(salt + to_hash)
end

.hex_to_bytes(hex) ⇒ Object



419
420
421
# File 'lib/enzoic/hashing.rb', line 419

def self.hex_to_bytes(hex)
  hex.scan(/../).map { |x| x.hex }.pack('c*')
end

.hmac_sha1_salt_as_hash(to_hash, salt) ⇒ Object



315
316
317
# File 'lib/enzoic/hashing.rb', line 315

def self.hmac_sha1_salt_as_hash(to_hash, salt)
  return OpenSSL::HMAC.hexdigest("sha1", salt, to_hash)
end

.md5(to_hash) ⇒ Object



12
13
14
# File 'lib/enzoic/hashing.rb', line 12

def self.md5(to_hash)
  return Digest::MD5.hexdigest to_hash
end

.md5_binary(to_hash) ⇒ Object



16
17
18
# File 'lib/enzoic/hashing.rb', line 16

def self.md5_binary(to_hash)
  return Digest::MD5.digest(to_hash).bytes
end

.md5_binary_array(to_hash_bytes) ⇒ Object



20
21
22
# File 'lib/enzoic/hashing.rb', line 20

def self.md5_binary_array(to_hash_bytes)
  return Digest::MD5.digest(to_hash_bytes.pack('c*')).bytes
end

.md5crypt(to_hash, salt) ⇒ Object



159
160
161
# File 'lib/enzoic/hashing.rb', line 159

def self.md5crypt(to_hash, salt)
  return UnixCrypt::MD5.build(to_hash, salt.start_with?("$1$") ? salt[3..salt.length] : salt)
end

.mybb(to_hash, salt) ⇒ Object



68
69
70
# File 'lib/enzoic/hashing.rb', line 68

def self.mybb(to_hash, salt)
  return self.md5(self.md5(salt) + self.md5(to_hash))
end

.mySQLPost4_1(to_hash) ⇒ Object



207
208
209
# File 'lib/enzoic/hashing.rb', line 207

def self.mySQLPost4_1(to_hash)
  return "*" + self.bytes_to_hex(self.sha1_binary_array(self.sha1_binary(to_hash)));
end

.mySQLPre4_1(to_hash) ⇒ Object



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/enzoic/hashing.rb', line 183

def self.mySQLPre4_1(to_hash)
  nr = 1345345333
  add = 7
  nr2 = 0x12345671

  for i in 0..to_hash.length - 1 do
    c = to_hash[i]

    if c == " " || c == "\t"
      next
    end

    tmp = c.ord
    nr = nr ^ ((((nr & 63) + add) * tmp) + (self.convertToUnsigned(nr << 8)))
    nr2 += (self.convertToUnsigned(nr2 << 8)) ^ nr
    add += tmp
  end

  result1 = nr & ((self.convertToUnsigned(1 << 31)) - 1)
  result2 = nr2 & ((self.convertToUnsigned(1 << 31)) - 1)

  return result1.to_s(16) + result2.to_s(16)
end

.ntlm(to_hash) ⇒ Object



247
248
249
250
251
# File 'lib/enzoic/hashing.rb', line 247

def self.ntlm(to_hash)
  pwd = to_hash.dup
  pwd = pwd.dup.force_encoding('UTF-8').encode(Encoding::UTF_16LE, Encoding::UTF_8).force_encoding('UTF-8')
  OpenSSL::Digest::MD4.hexdigest pwd
end

.osCommerce_AEF(to_hash, salt) ⇒ Object



171
172
173
# File 'lib/enzoic/hashing.rb', line 171

def self.osCommerce_AEF(to_hash, salt)
  return self.md5(salt + to_hash)
end

.partial_md5_20(to_hash) ⇒ Object



219
220
221
# File 'lib/enzoic/hashing.rb', line 219

def self.partial_md5_20(to_hash)
  return self.md5(to_hash)[0..19]
end

.partial_md5_29(to_hash) ⇒ Object



223
224
225
# File 'lib/enzoic/hashing.rb', line 223

def self.partial_md5_29(to_hash)
  return self.md5(to_hash)[0..28]
end

.phpbb3(to_hash, salt) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/enzoic/hashing.rb', line 96

def self.phpbb3(to_hash, salt)
  if !salt.start_with?("$H$")
    return ""
  end

  itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  to_hash_bytes = to_hash.bytes
  count = 2 ** itoa64.index(salt[3])
  justsalt = salt[4..12]

  hash = self.md5_binary(justsalt + to_hash)
  loop do
    hash = self.md5_binary_array(hash.push(to_hash_bytes).flatten!)
    count = count - 1;
    break if count == 0
  end

  hashout = ""
  i = 0
  count = 16
  value = 0

  loop do
    value = hash[i] + (hash[i] < 0 ? 256 : 0)
    i = i + 1
    hashout = hashout + itoa64[value & 63]
    if i < count
      value = value | (hash[i] + (hash[i] < 0 ? 256 : 0)) << 8;
    end

    hashout = hashout + itoa64[(value >> 6) & 63]
    i = i + 1
    if (i >= count)
      break
    end

    if (i < count)
      value = value | (hash[i] + (hash[i] < 0 ? 256 : 0)) << 16
    end

    hashout = hashout + itoa64[(value >> 12) & 63]

    i = i + 1
    if (i >= count)
      break
    end

    hashout = hashout + itoa64[(value >> 18) & 63]

    break if i == count
  end

  return salt + hashout
end

.pligg_cms(to_hash, salt) ⇒ Object



239
240
241
# File 'lib/enzoic/hashing.rb', line 239

def self.pligg_cms(to_hash, salt)
  return salt + self.sha1(salt + to_hash)
end

.punBB(to_hash, salt) ⇒ Object



211
212
213
# File 'lib/enzoic/hashing.rb', line 211

def self.punBB(to_hash, salt)
  return self.sha1(salt + self.sha1(to_hash))
end

.runcms_smf1_1(to_hash, salt) ⇒ Object



243
244
245
# File 'lib/enzoic/hashing.rb', line 243

def self.runcms_smf1_1(to_hash, salt)
  return self.sha1(salt + to_hash)
end

.sha1(to_hash) ⇒ Object



24
25
26
# File 'lib/enzoic/hashing.rb', line 24

def self.sha1(to_hash)
  return Digest::SHA1.hexdigest to_hash
end

.sha1_binary(to_hash) ⇒ Object



28
29
30
# File 'lib/enzoic/hashing.rb', line 28

def self.sha1_binary(to_hash)
  return Digest::SHA1.digest(to_hash).bytes
end

.sha1_binary_array(to_hash_bytes) ⇒ Object



32
33
34
# File 'lib/enzoic/hashing.rb', line 32

def self.sha1_binary_array(to_hash_bytes)
  return Digest::SHA1.digest(to_hash_bytes.pack('c*')).bytes
end

.sha1dash(to_hash, salt) ⇒ Object



253
254
255
# File 'lib/enzoic/hashing.rb', line 253

def self.sha1dash(to_hash, salt)
  return self.sha1("--" + salt + "--" + to_hash + "--")
end

.sha256(to_hash) ⇒ Object



36
37
38
# File 'lib/enzoic/hashing.rb', line 36

def self.sha256(to_hash)
  return Digest::SHA256.hexdigest to_hash
end

.sha256crypt(to_hash, salt) ⇒ Object



276
277
278
# File 'lib/enzoic/hashing.rb', line 276

def self.sha256crypt(to_hash, salt)
  return self.sha_crypt("5", UnixCrypt::SHA256, to_hash, salt)
end

.sha384(to_hash) ⇒ Object



257
258
259
# File 'lib/enzoic/hashing.rb', line 257

def self.sha384(to_hash)
  return Digest::SHA384.hexdigest to_hash
end

.sha512(to_hash) ⇒ Object



40
41
42
# File 'lib/enzoic/hashing.rb', line 40

def self.sha512(to_hash)
  return Digest::SHA512.hexdigest to_hash
end

.sha512_binary(to_hash) ⇒ Object



44
45
46
# File 'lib/enzoic/hashing.rb', line 44

def self.sha512_binary(to_hash)
  return Digest::SHA512.digest to_hash
end

.sha512_binary_array(to_hash) ⇒ Object



48
49
50
# File 'lib/enzoic/hashing.rb', line 48

def self.sha512_binary_array(to_hash)
  return Digest::SHA512.digest(to_hash).bytes
end

.sha512crypt(to_hash, salt) ⇒ Object



280
281
282
# File 'lib/enzoic/hashing.rb', line 280

def self.sha512crypt(to_hash, salt)
  return self.sha_crypt("6", UnixCrypt::SHA512, to_hash, salt)
end

.sha_crypt(crypt_version, crypter, to_hash, salt) ⇒ Object



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
# File 'lib/enzoic/hashing.rb', line 284

def self.sha_crypt(crypt_version, crypter, to_hash, salt)
  # special handling if the salt contains an embedded rounds specifier
  if salt.start_with?("$" + crypt_version + "$") && salt.include?("$rounds=")
    # extract rounds
    rounds_starting_idx = salt.index("$rounds=") + 8
    rounds = salt[rounds_starting_idx..salt.length]
    salt_portion = rounds[rounds.index("$") + 1..rounds.length]

    begin
      rounds = Integer(rounds[0..rounds.index("$") - 1])
    rescue ArgumentError
      rounds = 5000
    end

    result = crypter.build(to_hash, salt_portion, rounds)

    # if the default rounds of 5000 was used, add this back in to the resultant hash as this library, unlike most,
    # will strip it out.
    if rounds == 5000
      result = result[0..2] + "rounds=5000$" + result[3..result.length]
    end

    return result
  end
  return crypter.build(to_hash, salt.start_with?("$" + crypt_version + "$") ? salt[3..salt.length] : salt)
end

.vbulletin(to_hash, salt) ⇒ Object



72
73
74
# File 'lib/enzoic/hashing.rb', line 72

def self.vbulletin(to_hash, salt)
  return self.md5(self.md5(to_hash) + salt)
end

.whirlpool(to_hash) ⇒ Object



52
53
54
# File 'lib/enzoic/hashing.rb', line 52

def self.whirlpool(to_hash)
  return Digest::Whirlpool.hexdigest(to_hash)
end

.whirlpool_binary(to_hash) ⇒ Object



56
57
58
# File 'lib/enzoic/hashing.rb', line 56

def self.whirlpool_binary(to_hash)
  return Digest::Whirlpool.digest(to_hash)
end

.whirlpool_binary_array(to_hash) ⇒ Object



60
61
62
# File 'lib/enzoic/hashing.rb', line 60

def self.whirlpool_binary_array(to_hash)
  return Digest::Whirlpool.digest(to_hash).bytes
end

.xor(byte_array1, byte_array2) ⇒ Object



405
406
407
408
409
410
411
412
413
# File 'lib/enzoic/hashing.rb', line 405

def self.xor(byte_array1, byte_array2)
  result = Array.new(byte_array1.length);

  for i in 0..byte_array1.length - 1 do
    result[i] = byte_array1[i] ^ byte_array2[i];
  end

  return result;
end