crack-js
Version:
Javascript library to crack various hashes in hashcat format
1,014 lines (774 loc) • 31.4 kB
JavaScript
var bcrypt = require('bcryptjs');
var CryptoJS = require("crypto-js");
function rstr_sha512(s) {
return CryptoJS.SHA512(CryptoJS.enc.Latin1.parse(s)).toString(CryptoJS.enc.Latin1);
}
function rstr_sha256(s) {
return CryptoJS.SHA256(CryptoJS.enc.Latin1.parse(s)).toString(CryptoJS.enc.Latin1);
}
function _extend_256(source, size_ref) {
var extended = "";
for (var i = 0; i < Math.floor(size_ref / 32); i++)
extended += source;
extended += source.substr(0, size_ref % 32);
return extended;
}
function _extend_512(source, size_ref) {
var extended = "";
for (var i = 0; i < Math.floor(size_ref / 64); i++)
extended += source;
extended += source.substr(0, size_ref % 64);
return extended;
}
// steps 1-12
function _sha512crypt_intermediate(password, salt) {
var digest_b = rstr_sha512(password + salt + password);
var key_len = password.length;
// extend digest b so that it has the same size as password
var digest_b_extended = _extend_512(digest_b, password.length);
var intermediate_input = password + salt + digest_b_extended;
for (var cnt = key_len; cnt > 0; cnt >>= 1) {
if ((cnt & 1) != 0)
intermediate_input += digest_b
else
intermediate_input += password;
}
var intermediate = rstr_sha512(intermediate_input);
return intermediate;
}
function _sha256crypt_intermediate(password, salt) {
var digest_b = rstr_sha256(password + salt + password);
var key_len = password.length;
// extend digest b so that it has the same size as password
var digest_b_extended = _extend_256(digest_b, password.length);
var intermediate_input = password + salt + digest_b_extended;
for (var cnt = key_len; cnt > 0; cnt >>= 1) {
if ((cnt & 1) != 0)
intermediate_input += digest_b
else
intermediate_input += password;
}
var intermediate = rstr_sha256(intermediate_input);
return intermediate;
}
function _rstr_sha256crypt(password, salt, rounds) {
// steps 1-12
var digest_a = _sha256crypt_intermediate(password, salt);
// step 13-15
var dp_input = "";
for (var i = 0; i < password.length; i++)
dp_input += password;
var dp = rstr_sha256(dp_input);
// step 16
var p = _extend_256(dp, password.length);
// step 17-19
var ds_input = "";
for (var i = 0; i < (16 + digest_a.charCodeAt(0)); i++)
ds_input += salt;
var ds = rstr_sha256(ds_input);
// step 20
var s = _extend_256(ds, salt.length);
// step 21
var digest = digest_a;
var c_input = "";
for (var i = 0; i < rounds; i++) {
c_input = "";
if (i & 1)
c_input += p;
else
c_input += digest;
if (i % 3)
c_input += s;
if (i % 7)
c_input += p;
if (i & 1)
c_input += digest;
else
c_input += p;
digest = rstr_sha256(c_input);
}
return digest;
}
function _rstr_sha512crypt(password, salt, rounds) {
// steps 1-12
var digest_a = _sha512crypt_intermediate(password, salt);
// step 13-15
var dp_input = "";
for (var i = 0; i < password.length; i++)
dp_input += password;
var dp = rstr_sha512(dp_input);
// step 16
var p = _extend_512(dp, password.length);
// step 17-19
var ds_input = "";
for (var i = 0; i < (16 + digest_a.charCodeAt(0)); i++)
ds_input += salt;
var ds = rstr_sha512(ds_input);
// step 20
var s = _extend_512(ds, salt.length);
// step 21
var digest = digest_a;
var c_input = "";
for (var i = 0; i < rounds; i++) {
c_input = "";
if (i & 1)
c_input += p;
else
c_input += digest;
if (i % 3)
c_input += s;
if (i % 7)
c_input += p;
if (i & 1)
c_input += digest;
else
c_input += p;
digest = rstr_sha512(c_input);
}
return digest;
};
function sha512crypt(password, salt) {
//sha256 and 512 have similar algorithms than md5
var magic = "$6$";
var rounds;
// parse the magic "$" stuff
var magic_array = salt.split("$");
if (magic_array.length > 1) {
rounds = parseInt(magic_array[2].split("=")[1]);
if (rounds) {
if (rounds < 1000)
rounds = 1000;
if (rounds > 999999999)
rounds = 999999999;
salt = magic_array[3] || salt;
} else {
salt = magic_array[2] || salt;
}
}
// salt is max 16 chars long
salt = salt.substr(0, 16);
var hash = "";
var result = "";
hash = _rstr_sha512crypt(password, salt, rounds || 5000);
result =
to64_triplet(hash, 0, 21, 42) +
to64_triplet(hash, 22, 43, 1) +
to64_triplet(hash, 44, 2, 23) +
to64_triplet(hash, 3, 24, 45) +
to64_triplet(hash, 25, 46, 4) +
to64_triplet(hash, 47, 5, 26) +
to64_triplet(hash, 6, 27, 48) +
to64_triplet(hash, 28, 49, 7) +
to64_triplet(hash, 50, 8, 29) +
to64_triplet(hash, 9, 30, 51) +
to64_triplet(hash, 31, 52, 10) +
to64_triplet(hash, 53, 11, 32) +
to64_triplet(hash, 12, 33, 54) +
to64_triplet(hash, 34, 55, 13) +
to64_triplet(hash, 56, 14, 35) +
to64_triplet(hash, 15, 36, 57) +
to64_triplet(hash, 37, 58, 16) +
to64_triplet(hash, 59, 17, 38) +
to64_triplet(hash, 18, 39, 60) +
to64_triplet(hash, 40, 61, 19) +
to64_triplet(hash, 62, 20, 41) +
to64_single(hash, 63);
return magic + salt + "$" + result;
}
function sha256crypt(password, salt) {
//sha256 and 512 have similar algorithms than md5
var magic = "$5$";
var rounds;
// parse the magic "$" stuff
var magic_array = salt.split("$");
if (magic_array.length > 1) {
rounds = parseInt(magic_array[2].split("=")[1]);
if (rounds) {
if (rounds < 1000)
rounds = 1000;
if (rounds > 999999999)
rounds = 999999999;
salt = magic_array[3] || salt;
} else {
salt = magic_array[2] || salt;
}
}
// salt is max 16 chars long
salt = salt.substr(0, 16);
var hash = "";
var result = "";
hash = _rstr_sha256crypt(password, salt, rounds || 5000);
var result =
to64_triplet(hash, 0, 10, 20) +
to64_triplet(hash, 21, 1, 11) +
to64_triplet(hash, 12, 22, 2) +
to64_triplet(hash, 3, 13, 23) +
to64_triplet(hash, 24, 4, 14) +
to64_triplet(hash, 15, 25, 5) +
to64_triplet(hash, 6, 16, 26) +
to64_triplet(hash, 27, 7, 17) +
to64_triplet(hash, 18, 28, 8) +
to64_triplet(hash, 9, 19, 29) +
to64_double(hash, 31, 30);
return magic + salt + "$" + result;
}
function to64(v, n) {
const ascii64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var s = "";
while (--n >= 0) {
s += ascii64.charAt(v & 0x3f);
v >>= 6;
}
return s;
}
function to64_triplet(str, idx0, idx1, idx2) {
var v = (str.charCodeAt(idx0) << 16) |
(str.charCodeAt(idx1) << 8) |
(str.charCodeAt(idx2));
return to64(v, 4);
}
function to64_double(str, idx0, idx1) {
var v = (str.charCodeAt(idx0) << 8) |
str.charCodeAt(idx1);
return to64(v, 3);
}
function to64_single(str, idx0) {
var v = str.charCodeAt(idx0);
return to64(v, 2);
}
function md5crypt(password, salt) {
var pwlen = password.length;
var da = password + "$1$" + salt;
var db = password + salt + password;
var db_digest = CryptoJS.MD5(db);
for (pwlen; pwlen > 0; pwlen -= 16) {
if (pwlen > 16)
da = da.concat(db_digest.toString(CryptoJS.enc.Latin1));
else
da = da.concat(db_digest.toString(CryptoJS.enc.Latin1).substring(0, pwlen));
}
for (var i = password.length; i != 0; i >>= 1) {
if (i % 2 == 1)
da += '\0';
else
da += password.charAt(0);
}
var dc_digest = CryptoJS.MD5(CryptoJS.enc.Latin1.parse(da));
for (i = 0; i < 1000; i++) {
var tmp = "";
if (i & 1)
tmp += password;
else
tmp += dc_digest.toString(CryptoJS.enc.Latin1);
if (i % 3) {
tmp += salt;
}
if (i % 7)
tmp += password;
if (i & 1)
tmp += dc_digest.toString(CryptoJS.enc.Latin1);
else
tmp += password;
dc_digest = CryptoJS.MD5(CryptoJS.enc.Latin1.parse(tmp));
}
var hash = "$1$" + salt + "$" +
to64_triplet(dc_digest.toString(CryptoJS.enc.Latin1), 0, 6, 12) +
to64_triplet(dc_digest.toString(CryptoJS.enc.Latin1), 1, 7, 13) +
to64_triplet(dc_digest.toString(CryptoJS.enc.Latin1), 2, 8, 14) +
to64_triplet(dc_digest.toString(CryptoJS.enc.Latin1), 3, 9, 15) +
to64_triplet(dc_digest.toString(CryptoJS.enc.Latin1), 4, 10, 5) +
to64_single(dc_digest.toString(CryptoJS.enc.Latin1), 11);
return hash;
}
(function(Math) {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var Hasher = C_lib.Hasher;
var C_algo = C.algo;
// Constants table
var S = [
[3, 7, 11, 19],
[3, 5, 9, 13],
[3, 9, 11, 15]
];
var FF = 0x00000000;
var GG = 0x5a827999;
var HH = 0x6ed9eba1;
/**
* MD4 hash algorithm.
*/
var MD4 = C_algo.MD4 = Hasher.extend({
_doReset: function() {
this._hash = new WordArray.init([
0x67452301, 0xefcdab89,
0x98badcfe, 0x10325476
]);
},
_doProcessBlock: function(M, offset) {
// Swap endian
for (var i = 0; i < 16; i++) {
// Shortcuts
var offset_i = offset + i;
var M_offset_i = M[offset_i];
M[offset_i] = (
(((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) |
(((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00)
);
}
// Shortcuts
var H = this._hash.words;
var M_offset_0 = M[offset + 0];
var M_offset_1 = M[offset + 1];
var M_offset_2 = M[offset + 2];
var M_offset_3 = M[offset + 3];
var M_offset_4 = M[offset + 4];
var M_offset_5 = M[offset + 5];
var M_offset_6 = M[offset + 6];
var M_offset_7 = M[offset + 7];
var M_offset_8 = M[offset + 8];
var M_offset_9 = M[offset + 9];
var M_offset_10 = M[offset + 10];
var M_offset_11 = M[offset + 11];
var M_offset_12 = M[offset + 12];
var M_offset_13 = M[offset + 13];
var M_offset_14 = M[offset + 14];
var M_offset_15 = M[offset + 15];
// Working varialbes
var a = H[0];
var b = H[1];
var c = H[2];
var d = H[3];
// Computation
a = CC(FFF, FF, a, b, c, d, M_offset_0, S[0][0]);
d = CC(FFF, FF, d, a, b, c, M_offset_1, S[0][1]);
c = CC(FFF, FF, c, d, a, b, M_offset_2, S[0][2]);
b = CC(FFF, FF, b, c, d, a, M_offset_3, S[0][3]);
a = CC(FFF, FF, a, b, c, d, M_offset_4, S[0][0]);
d = CC(FFF, FF, d, a, b, c, M_offset_5, S[0][1]);
c = CC(FFF, FF, c, d, a, b, M_offset_6, S[0][2]);
b = CC(FFF, FF, b, c, d, a, M_offset_7, S[0][3]);
a = CC(FFF, FF, a, b, c, d, M_offset_8, S[0][0]);
d = CC(FFF, FF, d, a, b, c, M_offset_9, S[0][1]);
c = CC(FFF, FF, c, d, a, b, M_offset_10, S[0][2]);
b = CC(FFF, FF, b, c, d, a, M_offset_11, S[0][3]);
a = CC(FFF, FF, a, b, c, d, M_offset_12, S[0][0]);
d = CC(FFF, FF, d, a, b, c, M_offset_13, S[0][1]);
c = CC(FFF, FF, c, d, a, b, M_offset_14, S[0][2]);
b = CC(FFF, FF, b, c, d, a, M_offset_15, S[0][3]);
a = CC(GGG, GG, a, b, c, d, M_offset_0, S[1][0]);
d = CC(GGG, GG, d, a, b, c, M_offset_4, S[1][1]);
c = CC(GGG, GG, c, d, a, b, M_offset_8, S[1][2]);
b = CC(GGG, GG, b, c, d, a, M_offset_12, S[1][3]);
a = CC(GGG, GG, a, b, c, d, M_offset_1, S[1][0]);
d = CC(GGG, GG, d, a, b, c, M_offset_5, S[1][1]);
c = CC(GGG, GG, c, d, a, b, M_offset_9, S[1][2]);
b = CC(GGG, GG, b, c, d, a, M_offset_13, S[1][3]);
a = CC(GGG, GG, a, b, c, d, M_offset_2, S[1][0]);
d = CC(GGG, GG, d, a, b, c, M_offset_6, S[1][1]);
c = CC(GGG, GG, c, d, a, b, M_offset_10, S[1][2]);
b = CC(GGG, GG, b, c, d, a, M_offset_14, S[1][3]);
a = CC(GGG, GG, a, b, c, d, M_offset_3, S[1][0]);
d = CC(GGG, GG, d, a, b, c, M_offset_7, S[1][1]);
c = CC(GGG, GG, c, d, a, b, M_offset_11, S[1][2]);
b = CC(GGG, GG, b, c, d, a, M_offset_15, S[1][3]);
a = CC(HHH, HH, a, b, c, d, M_offset_0, S[2][0]);
d = CC(HHH, HH, d, a, b, c, M_offset_8, S[2][1]);
c = CC(HHH, HH, c, d, a, b, M_offset_4, S[2][2]);
b = CC(HHH, HH, b, c, d, a, M_offset_12, S[2][3]);
a = CC(HHH, HH, a, b, c, d, M_offset_2, S[2][0]);
d = CC(HHH, HH, d, a, b, c, M_offset_10, S[2][1]);
c = CC(HHH, HH, c, d, a, b, M_offset_6, S[2][2]);
b = CC(HHH, HH, b, c, d, a, M_offset_14, S[2][3]);
a = CC(HHH, HH, a, b, c, d, M_offset_1, S[2][0]);
d = CC(HHH, HH, d, a, b, c, M_offset_9, S[2][1]);
c = CC(HHH, HH, c, d, a, b, M_offset_5, S[2][2]);
b = CC(HHH, HH, b, c, d, a, M_offset_13, S[2][3]);
a = CC(HHH, HH, a, b, c, d, M_offset_3, S[2][0]);
d = CC(HHH, HH, d, a, b, c, M_offset_11, S[2][1]);
c = CC(HHH, HH, c, d, a, b, M_offset_7, S[2][2]);
b = CC(HHH, HH, b, c, d, a, M_offset_15, S[2][3]);
// Intermediate hash value
H[0] = (H[0] + a) | 0;
H[1] = (H[1] + b) | 0;
H[2] = (H[2] + c) | 0;
H[3] = (H[3] + d) | 0;
},
_doFinalize: function() {
// Shortcuts
var data = this._data;
var dataWords = data.words;
var nBitsTotal = this._nDataBytes * 8;
var nBitsLeft = data.sigBytes * 8;
// Add padding
dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000);
var nBitsTotalL = nBitsTotal;
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = (
(((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) |
(((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00)
);
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
(((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) |
(((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00)
);
data.sigBytes = (dataWords.length + 1) * 4;
// Hash final blocks
this._process();
// Shortcuts
var hash = this._hash;
var H = hash.words;
// Swap endian
for (var i = 0; i < 4; i++) {
// Shortcut
var H_i = H[i];
H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) |
(((H_i << 24) | (H_i >>> 8)) & 0xff00ff00);
}
// Return final computed hash
return hash;
},
clone: function() {
var clone = Hasher.clone.call(this);
clone._hash = this._hash.clone();
return clone;
}
});
function ROTL(num, cnt) {
return (num << cnt) | (num >>> (32 - cnt));
}
function CC(f, k, a, b, c, d, x, s) {
return ROTL((a + f(b, c, d) + x + k), s);
}
function FFF(x, y, z) {
return ((x & y) | ((~x) & z));
}
function GGG(x, y, z) {
return ((x & y) | (x & z) | (y & z));
}
function HHH(x, y, z) {
return (x ^ y ^ z);
}
/**
* Shortcut function to the hasher's object interface.
*
* @param {WordArray|string} message The message to hash.
*
* @return {WordArray} The hash.
*
* @static
*
* @example
*
* var hash = CryptoJS.MD4('message');
* var hash = CryptoJS.MD4(wordArray);
*/
C.MD4 = Hasher._createHelper(MD4);
/**
* Shortcut function to the HMAC's object interface.
*
* @param {WordArray|string} message The message to hash.
* @param {WordArray|string} key The secret key.
*
* @return {WordArray} The HMAC.
*
* @static
*
* @example
*
* var hmac = CryptoJS.HmacMD4(message, key);
*/
C.HmacMD4 = Hasher._createHmacHelper(MD4);
})(Math);
function mysql323Hash(password) {
let nr = 1345345333;
let nr2 = 305419889;
let add = 7;
for (let i = 0; i < password.length; i++) {
let ch = password.charCodeAt(i);
nr ^= ((nr & 63) + add) * ch + (nr << 8);
nr2 += (nr2 << 8) ^ nr;
add += ch;
}
let hash = (nr >>> 0).toString(16) + (nr2 >>> 0).toString(16);
while (hash.length < 16) {
hash = '0' + hash;
}
return hash;
}
function netntlmv2Hash(username,domain,challenge,blob,password)
{
let wordsNtlm = CryptoJS.enc.Hex.parse(CryptoJS.MD4(CryptoJS.enc.Utf16LE.parse(password)).toString().toUpperCase());
var usernameDomain=CryptoJS.enc.Utf16LE.parse(username.toUpperCase()+domain)
var ntlmv2hash=CryptoJS.HmacMD5(usernameDomain,wordsNtlm);
var resultHash=CryptoJS.HmacMD5(CryptoJS.enc.Hex.parse(challenge+blob),ntlmv2hash);
return CryptoJS.enc.Hex.stringify(resultHash);
}
export function verifyHash(password, hash, hashType) {
switch (hashType) {
case 'jwt':
return verifyJWT(password, hash);
case 'netntlmv2':
return verifyNetNTLMV2(password, hash);
case 'ntlm':
return verifyNTLM(password, hash);
case 'md5':
return verifyMD5(password, hash);
case 'sha1':
return verifySHA1(password, hash);
case 'sha256':
return verifySHA256(password, hash);
case 'sha512':
return verifySHA512(password, hash);
case 'bcrypt':
return verifyBcrypt(password, hash);
case 'md5crypt':
return verifyMD5CRYPT(password, hash);
case 'sha256crypt':
return verifySHA256CRYPT(password, hash);
case 'sha512crypt':
return verifySHA512CRYPT(password, hash);
case 'hmac-md5':
return verifyHMAC_MD5(password, hash);
case 'hmac-sha1':
return verifyHMAC_SHA1(password, hash);
case 'hmac-sha256':
return verifyHMAC_SHA256(password, hash);
case 'hmac-sha512':
return verifyHMAC_SHA512(password, hash);
case 'mysql323':
return verify_mysql323(password, hash);
default:
throw new Error(`Unsupported hash type: ${hashType}`);
}
}
export function measureSpeed(hashType) {
let hash=false;
switch (hashType) {
case 'jwt': hash= "eyJhbGciOiJIUzI1NiJ9.eyIzNDM2MzQyMCI6NTc2ODc1NDd9.f1nXZ3V_Hrr6ee-AFCTLaHRnrkiKmio2t3JqwL32guY";break;
case 'netntlmv2': hash= "admin::N46iSNekpT:08ca45b7d7ea58ee:88dcbe4446168966a153a0064958dac6:5c7830315c7830310000000000000b45c67103d07d7b95acd12ffa11230e0000000052920b85f78d013c31cdb3b92f5d765c783030";break;
case 'ntlm': hash= "b4b9b02e6f09a9bd760f388b67351e2b";break;
case 'md5': hash= "8743b52063cd84097a65d1633f5c74f5";break;
case 'sha1': hash= "b89eaac7e61417341b710b727768294d0e6a277b";break;
case 'sha256': hash= "127e6fbfe24a750e72930c220a8e138275656b8e5d8f48a98c3c92df2caba935";break;
case 'sha512': hash= "82a9dda829eb7f8ffe9fbe49e45d47d2dad9664fbb7adf72492e3c81ebd3e29134d9bc12212bf83c6840f10e8246b9db54a4859b7ccd0123d86e5872c1e5082f";break;
case 'bcrypt': hash= "$2a$05$LhayLxezLhK1LhWvKxCyLOj0j1u.Kj0jZ0pEmm134uzrQlFvQJLF6";break;
case 'md5crypt': hash= "$1$28772684$iEwNOgGugqO9.bIz5sk8k/";break;
case 'sha256crypt': hash= "$5$rounds=5000$GX7BopJZJxPc/KEK$le16UF8I2Anb.rOrn22AUPWvzUETDGefUmAV8AZkGcD";break;
case 'sha512crypt': hash= "$6$52450745$k5ka2p8bFuSmoVT1tzOyyuaREkkKBcCNqoDKzYiJL9RaE8yMnPgh2XzzF0NDrUhgrcLwg78xs1w5pJiypEdFX/";break;
case 'mysql323': hash= "7196759210defdc0";break;
case 'hmac-md5': hash= "bfd280436f45fa38eaacac3b00518f29:1234";break;
case 'hmac-sha1': hash= "d89c92b4400b15c39e462a8caa939ab40c3aeeea:1234";break;
case 'hmac-sha256': hash= "8efbef4cec28f228fa948daaf4893ac3638fbae81358ff9020be1d7a9a509fc6:1234";break;
case 'hmac-sha512': hash= "7cce966f5503e292a51381f238d071971ad5442488f340f98e379b3aeae2f33778e3e732fcc2f7bdc04f3d460eebf6f8cb77da32df25500c09160dd3bf7d2a6b:1234";break;
default:
throw new Error(`Unsupported hash type: ${hashType}`);
}
const duration = 5000;
const startTime = Date.now();
let count = 0;
while (Date.now() - startTime < duration) {
verifyHash("hashcat", hash, hashType);
count++;
}
return Math.floor( count / (duration / 1000));
}
export function isFast(hashType) {
switch (hashType) {
case 'ntlm': return true;
case 'md5':return true;
case 'sha1': return true;
case 'sha256':return true;
case 'sha512': return true;
case 'mysql323':return true;
default:
return false;
}
}
export function isValidHash(hash, hashType) {
switch (hashType) {
case 'jwt': return /^([A-Za-z0-9-_]+={0,2})\.([A-Za-z0-9-_]+={0,2})\.([A-Za-z0-9-_]+={0,2})$/.test(hash);
case 'netntlmv2': return /^[^:]+::[^:]+:[a-fA-F0-9]{16}:[a-fA-F0-9]{32,64}:[a-fA-F0-9]+$/.test(hash);
case 'ntlm': return /^[a-fA-F0-9]{32}$/.test(hash);
case 'md5': return /^[a-fA-F0-9]{32}$/.test(hash);
case 'sha1': return /^[a-fA-F0-9]{40}$/.test(hash);
case 'sha256': return /^[a-fA-F0-9]{64}$/.test(hash);
case 'sha512': return /^[a-fA-F0-9]{128}$/.test(hash);
case 'bcrypt': return /^\$2[aby]?\$[0-9]{2}\$[./A-Za-z0-9]{53}$/.test(hash);
case 'md5crypt':return /^\$1\$[./A-Za-z0-9]{1,8}\$[./A-Za-z0-9]{22}$/.test(hash);
case 'sha256crypt':return /^\$5\$(rounds=\d+\$)?[./A-Za-z0-9]{1,16}\$[./A-Za-z0-9]{43,86}$/.test(hash);
case 'sha512crypt':return /^\$6\$(rounds=\d+\$)?[./A-Za-z0-9]{1,16}\$[./A-Za-z0-9]{86,}$/.test(hash);
case 'mysql323':return /^[a-fA-F0-9]{16}$/.test(hash);
case 'hmac-md5': return /^[a-fA-F0-9]{32}:[A-Za-z0-9_]+$/.test(hash);
case 'hmac-sha1': return /^[a-fA-F0-9]{40}:[A-Za-z0-9_]+$/.test(hash);
case 'hmac-sha256': return /^[a-fA-F0-9]{64}:[A-Za-z0-9_]+$/.test(hash);
case 'hmac-sha512': return /^[a-fA-F0-9]{128}:[A-Za-z0-9_]+$/.test(hash);
default:
throw new Error(`Unsupported hash type: ${hashType}`);
}
}
export function getPossibleHashTypes(hash) {
let possibleHashTypes=[];
for (let i = 0; i < availableHashTypes.length; i++) {
if(isValidHash(hash,availableHashTypes[i]))possibleHashTypes.push(availableHashTypes[i]);
}
return possibleHashTypes;
}
function verifyNetNTLMV2(password,hash)
{
let parts = hash.split(":");
if (parts.length < 6) return false
var username = parts[0];
var domain = parts[2];
var challenge = parts[3];
var targetHash = parts[4];
var blob = parts[5];
var targetHashCalculated=netntlmv2Hash(username,domain,challenge,blob,password);
return targetHashCalculated === targetHash;
}
function verifyMD5CRYPT(password, hash) {
const hashToVerify =md5crypt(password,hash.split("$")[2])
return hashToVerify === hash;
}
function verifySHA256CRYPT(password, hash) {
var magic_array = hash.split("$");
var salt;
var rounds;
var rest;
if (magic_array.length > 1) {
rounds = parseInt(magic_array[2].split("=")[1]);
if (rounds) {
salt = magic_array[3];
rest= magic_array[4];
} else {
salt = magic_array[2];
rest= magic_array[3];
}
}
else return false;
var formatted_hash="$5$"+salt+"$"+rest;
const hashToVerify =sha256crypt(password,hash)
return hashToVerify === formatted_hash;
}
function verifySHA512CRYPT(password, hash) {
var magic_array = hash.split("$");
var rounds;
var salt;
var rest;
if (magic_array.length > 1) {
rounds = parseInt(magic_array[2].split("=")[1]);
if (rounds) {
salt = magic_array[3];
rest= magic_array[4];
} else {
salt = magic_array[2];
rest= magic_array[3];
}
}
else return false;
var formatted_hash="$6$"+salt+"$"+rest;
const hashToVerify =sha512crypt(password,hash)
return hashToVerify === formatted_hash;
}
function verifyJWT(password,hash)
{
const jwtParts = hash.split(".");
var clearedToken=String(jwtParts[0])+"."+String(jwtParts[1]);
const header = JSON.parse(atob(jwtParts[0]));
if (!header.alg)
return false;
let signature=false;
let alg=header.alg.toLowerCase();
switch(alg)
{
case "hs256":signature=CryptoJS.HmacSHA256(String(clearedToken),String(password)).toString(CryptoJS.enc.Base64).replaceAll("=","").replaceAll("+","-").replaceAll('/','_');break;
case "hs384":signature=CryptoJS.HmacSHA384(String(clearedToken),String(password)).toString(CryptoJS.enc.Base64).replaceAll("=","").replaceAll("+","-").replaceAll('/','_');break;
case "hs512":signature=CryptoJS.HmacSHA512(String(clearedToken),String(password)).toString(CryptoJS.enc.Base64).replaceAll("=","").replaceAll("+","-").replaceAll('/','_');break;
default: return false;
}
if (jwtParts[2] == signature)
return true
return false;
}
function verifyNTLM(password, hash) {
const hashToVerify =CryptoJS.MD4(CryptoJS.enc.Utf16LE.parse(password)).toString().toUpperCase();
return hashToVerify === hash.toString().toUpperCase();
}
function verifyMD5(password, hash) {
const hashToVerify = CryptoJS.MD5(password).toString(CryptoJS.enc.Hex);
return hashToVerify === hash.toLowerCase();
}
function verifySHA1(password, hash) {
const hashToVerify = CryptoJS.SHA1(password).toString(CryptoJS.enc.Hex);
return hashToVerify === hash.toLowerCase();
}
function verifySHA256(password, hash) {
const hashToVerify = CryptoJS.SHA256(password).toString(CryptoJS.enc.Hex);
return hashToVerify === hash.toLowerCase();
}
function verifySHA512(password, hash) {
const hashToVerify = CryptoJS.SHA512(password).toString(CryptoJS.enc.Hex);
return hashToVerify === hash.toLowerCase();
}
function verifyBcrypt(password, hash) {
return bcrypt.compareSync(password, hash);
}
function verifyHMAC_MD5(password, hash) {
const parts = hash.split(":");
let hashToVerify=null;
if (parts.length == 2)
{
hashToVerify = CryptoJS.HmacMD5(password, parts[1]).toString(CryptoJS.enc.Hex);
return hashToVerify === parts[0].toLowerCase();
}
hashToVerify = CryptoJS.HmacMD5(password, password).toString(CryptoJS.enc.Hex);
return hashToVerify === hash.toLowerCase();
}
function verifyHMAC_SHA1(password, hash) {
const parts = hash.split(":");
let hashToVerify=null;
if (parts.length == 2)
{
hashToVerify = CryptoJS.HmacSHA1(password, parts[1]).toString(CryptoJS.enc.Hex);
if(hashToVerify === parts[0].toLowerCase())return true;
hashToVerify = CryptoJS.HmacSHA1(parts[1],password).toString(CryptoJS.enc.Hex);
if(hashToVerify === parts[0].toLowerCase())return true;
return false;
}
hashToVerify = CryptoJS.HmacSHA1(password, password).toString(CryptoJS.enc.Hex);
return hashToVerify === hash.toLowerCase();
}
function verifyHMAC_SHA256(password, hash) {
const parts = hash.split(":");
let hashToVerify=null;
if (parts.length == 2)
{
hashToVerify = CryptoJS.HmacSHA256(password, parts[1]).toString(CryptoJS.enc.Hex);
if(hashToVerify === parts[0].toLowerCase())return true;
hashToVerify = CryptoJS.HmacSHA256(parts[1],password).toString(CryptoJS.enc.Hex);
if(hashToVerify === parts[0].toLowerCase())return true;
return false;
}
hashToVerify = CryptoJS.HmacSHA256(password, password).toString(CryptoJS.enc.Hex);
return hashToVerify === hash.toLowerCase();
}
function verifyHMAC_SHA512(password, hash) {
const parts = hash.split(":");
let hashToVerify=null;
if (parts.length == 2)
{
hashToVerify = CryptoJS.HmacSHA512(password, parts[1]).toString(CryptoJS.enc.Hex);
if(hashToVerify === parts[0].toLowerCase())return true;
hashToVerify = CryptoJS.HmacSHA512(parts[1],password).toString(CryptoJS.enc.Hex);
if(hashToVerify === parts[0].toLowerCase())return true;
return false;
}
hashToVerify = CryptoJS.HmacSHA512(password, password).toString(CryptoJS.enc.Hex);
return hashToVerify === hash.toLowerCase();
}
function verify_mysql323(password,hash) {
let calculatedHash = mysql323Hash(password);
return calculatedHash.toLowerCase() === hash.toLowerCase();
}
export const availableHashTypes = ['md5crypt','sha256crypt','sha512crypt','ntlm', 'md5', 'sha1','sha256','sha512', 'bcrypt','netntlmv2','hmac-md5','hmac-sha1','hmac-sha256','hmac-sha512','mysql323','jwt'];