123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785 |
- import Utils from "../Utils.js";
- import CryptoApi from "babel-loader!crypto-api";
- import MD6 from "node-md6";
- import * as SHA3 from "js-sha3";
- import Checksum from "./Checksum.js";
- import ctph from "ctph.js";
- import ssdeep from "ssdeep.js";
- import bcrypt from "bcryptjs";
- import scrypt from "scryptsy";
- /**
- * Hashing operations.
- *
- * @author n1474335 [n1474335@gmail.com]
- * @copyright Crown Copyright 2016
- * @license Apache-2.0
- *
- * @namespace
- */
- const Hash = {
- /**
- * Generic hash function.
- *
- * @param {string} name
- * @param {ArrayBuffer} input
- * @param {Object} [options={}]
- * @returns {string}
- */
- runHash: function(name, input, options={}) {
- const msg = Utils.arrayBufferToStr(input, false),
- hasher = CryptoApi.getHasher(name, options);
- hasher.update(msg);
- return CryptoApi.encoder.toHex(hasher.finalize());
- },
- /**
- * MD2 operation.
- *
- * @param {ArrayBuffer} input
- * @param {Object[]} args
- * @returns {string}
- */
- runMD2: function (input, args) {
- return Hash.runHash("md2", input);
- },
- /**
- * MD4 operation.
- *
- * @param {ArrayBuffer} input
- * @param {Object[]} args
- * @returns {string}
- */
- runMD4: function (input, args) {
- return Hash.runHash("md4", input);
- },
- /**
- * MD5 operation.
- *
- * @param {ArrayBuffer} input
- * @param {Object[]} args
- * @returns {string}
- */
- runMD5: function (input, args) {
- return Hash.runHash("md5", input);
- },
- /**
- * @constant
- * @default
- */
- MD6_SIZE: 256,
- /**
- * @constant
- * @default
- */
- MD6_LEVELS: 64,
- /**
- * MD6 operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runMD6: function (input, args) {
- const size = args[0],
- levels = args[1],
- key = args[2];
- if (size < 0 || size > 512)
- return "Size must be between 0 and 512";
- if (levels < 0)
- return "Levels must be greater than 0";
- return MD6.getHashOfText(input, size, key, levels);
- },
- /**
- * SHA0 operation.
- *
- * @param {ArrayBuffer} input
- * @param {Object[]} args
- * @returns {string}
- */
- runSHA0: function (input, args) {
- return Hash.runHash("sha0", input);
- },
- /**
- * SHA1 operation.
- *
- * @param {ArrayBuffer} input
- * @param {Object[]} args
- * @returns {string}
- */
- runSHA1: function (input, args) {
- return Hash.runHash("sha1", input);
- },
- /**
- * @constant
- * @default
- */
- SHA2_SIZE: ["512", "256", "384", "224", "512/256", "512/224"],
- /**
- * SHA2 operation.
- *
- * @param {ArrayBuffer} input
- * @param {Object[]} args
- * @returns {string}
- */
- runSHA2: function (input, args) {
- const size = args[0];
- return Hash.runHash("sha" + size, input);
- },
- /**
- * @constant
- * @default
- */
- SHA3_SIZE: ["512", "384", "256", "224"],
- /**
- * SHA3 operation.
- *
- * @param {ArrayBuffer} input
- * @param {Object[]} args
- * @returns {string}
- */
- runSHA3: function (input, args) {
- const size = parseInt(args[0], 10);
- let algo;
- switch (size) {
- case 224:
- algo = SHA3.sha3_224;
- break;
- case 384:
- algo = SHA3.sha3_384;
- break;
- case 256:
- algo = SHA3.sha3_256;
- break;
- case 512:
- algo = SHA3.sha3_512;
- break;
- default:
- return "Invalid size";
- }
- return algo(input);
- },
- /**
- * @constant
- * @default
- */
- KECCAK_SIZE: ["512", "384", "256", "224"],
- /**
- * Keccak operation.
- *
- * @param {ArrayBuffer} input
- * @param {Object[]} args
- * @returns {string}
- */
- runKeccak: function (input, args) {
- const size = parseInt(args[0], 10);
- let algo;
- switch (size) {
- case 224:
- algo = SHA3.keccak224;
- break;
- case 384:
- algo = SHA3.keccak384;
- break;
- case 256:
- algo = SHA3.keccak256;
- break;
- case 512:
- algo = SHA3.keccak512;
- break;
- default:
- return "Invalid size";
- }
- return algo(input);
- },
- /**
- * @constant
- * @default
- */
- SHAKE_CAPACITY: ["256", "128"],
- /**
- * @constant
- * @default
- */
- SHAKE_SIZE: 512,
- /**
- * Shake operation.
- *
- * @param {ArrayBuffer} input
- * @param {Object[]} args
- * @returns {string}
- */
- runShake: function (input, args) {
- const capacity = parseInt(args[0], 10),
- size = args[1];
- let algo;
- if (size < 0)
- return "Size must be greater than 0";
- switch (capacity) {
- case 128:
- algo = SHA3.shake128;
- break;
- case 256:
- algo = SHA3.shake256;
- break;
- default:
- return "Invalid size";
- }
- return algo(input, size);
- },
- /**
- * @constant
- * @default
- */
- RIPEMD_SIZE: ["320", "256", "160", "128"],
- /**
- * RIPEMD operation.
- *
- * @param {ArrayBuffer} input
- * @param {Object[]} args
- * @returns {string}
- */
- runRIPEMD: function (input, args) {
- const size = args[0];
- return Hash.runHash("ripemd" + size, input);
- },
- /**
- * HAS-160 operation.
- *
- * @param {ArrayBuffer} input
- * @param {Object[]} args
- * @returns {string}
- */
- runHAS: function (input, args) {
- return Hash.runHash("has160", input);
- },
- /**
- * @constant
- * @default
- */
- WHIRLPOOL_VARIANT: ["Whirlpool", "Whirlpool-T", "Whirlpool-0"],
- /**
- * Whirlpool operation.
- *
- * @param {ArrayBuffer} input
- * @param {Object[]} args
- * @returns {string}
- */
- runWhirlpool: function (input, args) {
- const variant = args[0].toLowerCase();
- return Hash.runHash(variant, input);
- },
- /**
- * @constant
- * @default
- */
- SNEFRU_ROUNDS: ["8", "4", "2"],
- /**
- * @constant
- * @default
- */
- SNEFRU_SIZE: ["256", "128"],
- /**
- * Snefru operation.
- *
- * @param {ArrayBuffer} input
- * @param {Object[]} args
- * @returns {string}
- */
- runSnefru: function (input, args) {
- return Hash.runHash("snefru", input, {
- rounds: args[0],
- length: args[1]
- });
- },
- /**
- * CTPH operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runCTPH: function (input, args) {
- return ctph.digest(input);
- },
- /**
- * SSDEEP operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runSSDEEP: function (input, args) {
- return ssdeep.digest(input);
- },
- /**
- * @constant
- * @default
- */
- DELIM_OPTIONS: ["Line feed", "CRLF", "Space", "Comma"],
- /**
- * Compare CTPH hashes operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {Number}
- */
- runCompareCTPH: function (input, args) {
- const samples = input.split(Utils.charRep[args[0]]);
- if (samples.length !== 2) throw "Incorrect number of samples.";
- return ctph.similarity(samples[0], samples[1]);
- },
- /**
- * Compare SSDEEP hashes operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {Number}
- */
- runCompareSSDEEP: function (input, args) {
- const samples = input.split(Utils.charRep[args[0]]);
- if (samples.length !== 2) throw "Incorrect number of samples.";
- return ssdeep.similarity(samples[0], samples[1]);
- },
- /**
- * @constant
- * @default
- */
- HMAC_FUNCTIONS: [
- "MD2",
- "MD4",
- "MD5",
- "SHA0",
- "SHA1",
- "SHA224",
- "SHA256",
- "SHA384",
- "SHA512",
- "SHA512/224",
- "SHA512/256",
- "RIPEMD128",
- "RIPEMD160",
- "RIPEMD256",
- "RIPEMD320",
- "HAS160",
- "Whirlpool",
- "Whirlpool-0",
- "Whirlpool-T",
- "Snefru"
- ],
- /**
- * HMAC operation.
- *
- * @param {ArrayBuffer} input
- * @param {Object[]} args
- * @returns {string}
- */
- runHMAC: function (input, args) {
- const key = args[0],
- hashFunc = args[1].toLowerCase(),
- msg = Utils.arrayBufferToStr(input, false),
- hasher = CryptoApi.getHasher(hashFunc);
- // Horrible shim to fix constructor bug. Reported in nf404/crypto-api#8
- hasher.reset = () => {
- hasher.state = {};
- const tmp = new hasher.constructor();
- hasher.state = tmp.state;
- };
- const mac = CryptoApi.getHmac(CryptoApi.encoder.fromUtf(key), hasher);
- mac.update(msg);
- return CryptoApi.encoder.toHex(mac.finalize());
- },
- /**
- * @constant
- * @default
- */
- BCRYPT_ROUNDS: 10,
- /**
- * Bcrypt operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runBcrypt: async function (input, args) {
- const rounds = args[0];
- const salt = await bcrypt.genSalt(rounds);
- return await bcrypt.hash(input, salt, null, p => {
- // Progress callback
- if (ENVIRONMENT_IS_WORKER())
- self.sendStatusMessage(`Progress: ${(p * 100).toFixed(0)}%`);
- });
- },
- /**
- * Bcrypt compare operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runBcryptCompare: async function (input, args) {
- const hash = args[0];
- const match = await bcrypt.compare(input, hash, null, p => {
- // Progress callback
- if (ENVIRONMENT_IS_WORKER())
- self.sendStatusMessage(`Progress: ${(p * 100).toFixed(0)}%`);
- });
- return match ? "Match: " + input : "No match";
- },
- /**
- * Bcrypt parse operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runBcryptParse: async function (input, args) {
- try {
- return `Rounds: ${bcrypt.getRounds(input)}
- Salt: ${bcrypt.getSalt(input)}
- Password hash: ${input.split(bcrypt.getSalt(input))[1]}
- Full hash: ${input}`;
- } catch (err) {
- return "Error: " + err.toString();
- }
- },
- /**
- * @constant
- * @default
- */
- KEY_FORMAT: ["Hex", "Base64", "UTF8", "Latin1"],
- /**
- * @constant
- * @default
- */
- SCRYPT_ITERATIONS: 16384,
- /**
- * @constant
- * @default
- */
- SCRYPT_MEM_FACTOR: 8,
- /**
- * @constant
- * @default
- */
- SCRYPT_PARALLEL_FACTOR: 1,
- /**
- * @constant
- * @default
- */
- SCRYPT_KEY_LENGTH: 64,
- /**
- * Scrypt operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runScrypt: function (input, args) {
- const salt = Utils.convertToByteString(args[0].string || "", args[0].option),
- iterations = args[1],
- memFactor = args[2],
- parallelFactor = args[3],
- keyLength = args[4];
- try {
- const data = scrypt(
- input, salt, iterations, memFactor, parallelFactor, keyLength,
- p => {
- // Progress callback
- if (ENVIRONMENT_IS_WORKER())
- self.sendStatusMessage(`Progress: ${p.percent.toFixed(0)}%`);
- }
- );
- return data.toString("hex");
- } catch (err) {
- return "Error: " + err.toString();
- }
- },
- /**
- * Generate all hashes operation.
- *
- * @param {ArrayBuffer} input
- * @param {Object[]} args
- * @returns {string}
- */
- runAll: function (input, args) {
- const arrayBuffer = input,
- str = Utils.arrayBufferToStr(arrayBuffer, false),
- byteArray = new Uint8Array(arrayBuffer),
- output = "MD2: " + Hash.runMD2(arrayBuffer, []) +
- "\nMD4: " + Hash.runMD4(arrayBuffer, []) +
- "\nMD5: " + Hash.runMD5(arrayBuffer, []) +
- "\nMD6: " + Hash.runMD6(str, []) +
- "\nSHA0: " + Hash.runSHA0(arrayBuffer, []) +
- "\nSHA1: " + Hash.runSHA1(arrayBuffer, []) +
- "\nSHA2 224: " + Hash.runSHA2(arrayBuffer, ["224"]) +
- "\nSHA2 256: " + Hash.runSHA2(arrayBuffer, ["256"]) +
- "\nSHA2 384: " + Hash.runSHA2(arrayBuffer, ["384"]) +
- "\nSHA2 512: " + Hash.runSHA2(arrayBuffer, ["512"]) +
- "\nSHA3 224: " + Hash.runSHA3(arrayBuffer, ["224"]) +
- "\nSHA3 256: " + Hash.runSHA3(arrayBuffer, ["256"]) +
- "\nSHA3 384: " + Hash.runSHA3(arrayBuffer, ["384"]) +
- "\nSHA3 512: " + Hash.runSHA3(arrayBuffer, ["512"]) +
- "\nKeccak 224: " + Hash.runKeccak(arrayBuffer, ["224"]) +
- "\nKeccak 256: " + Hash.runKeccak(arrayBuffer, ["256"]) +
- "\nKeccak 384: " + Hash.runKeccak(arrayBuffer, ["384"]) +
- "\nKeccak 512: " + Hash.runKeccak(arrayBuffer, ["512"]) +
- "\nShake 128: " + Hash.runShake(arrayBuffer, ["128", 256]) +
- "\nShake 256: " + Hash.runShake(arrayBuffer, ["256", 512]) +
- "\nRIPEMD-128: " + Hash.runRIPEMD(arrayBuffer, ["128"]) +
- "\nRIPEMD-160: " + Hash.runRIPEMD(arrayBuffer, ["160"]) +
- "\nRIPEMD-256: " + Hash.runRIPEMD(arrayBuffer, ["256"]) +
- "\nRIPEMD-320: " + Hash.runRIPEMD(arrayBuffer, ["320"]) +
- "\nHAS-160: " + Hash.runHAS(arrayBuffer, []) +
- "\nWhirlpool-0: " + Hash.runWhirlpool(arrayBuffer, ["Whirlpool-0"]) +
- "\nWhirlpool-T: " + Hash.runWhirlpool(arrayBuffer, ["Whirlpool-T"]) +
- "\nWhirlpool: " + Hash.runWhirlpool(arrayBuffer, ["Whirlpool"]) +
- "\nSSDEEP: " + Hash.runSSDEEP(str) +
- "\nCTPH: " + Hash.runCTPH(str) +
- "\n\nChecksums:" +
- "\nFletcher-8: " + Checksum.runFletcher8(byteArray, []) +
- "\nFletcher-16: " + Checksum.runFletcher16(byteArray, []) +
- "\nFletcher-32: " + Checksum.runFletcher32(byteArray, []) +
- "\nFletcher-64: " + Checksum.runFletcher64(byteArray, []) +
- "\nAdler-32: " + Checksum.runAdler32(byteArray, []) +
- "\nCRC-16: " + Checksum.runCRC16(str, []) +
- "\nCRC-32: " + Checksum.runCRC32(str, []);
- return output;
- },
- /**
- * Analyse hash operation.
- *
- * @param {string} input
- * @param {Object[]} args
- * @returns {string}
- */
- runAnalyse: function(input, args) {
- input = input.replace(/\s/g, "");
- let output = "",
- byteLength = input.length / 2,
- bitLength = byteLength * 8,
- possibleHashFunctions = [];
- if (!/^[a-f0-9]+$/i.test(input)) {
- return "Invalid hash";
- }
- output += "Hash length: " + input.length + "\n" +
- "Byte length: " + byteLength + "\n" +
- "Bit length: " + bitLength + "\n\n" +
- "Based on the length, this hash could have been generated by one of the following hashing functions:\n";
- switch (bitLength) {
- case 4:
- possibleHashFunctions = [
- "Fletcher-4",
- "Luhn algorithm",
- "Verhoeff algorithm",
- ];
- break;
- case 8:
- possibleHashFunctions = [
- "Fletcher-8",
- ];
- break;
- case 16:
- possibleHashFunctions = [
- "BSD checksum",
- "CRC-16",
- "SYSV checksum",
- "Fletcher-16"
- ];
- break;
- case 32:
- possibleHashFunctions = [
- "CRC-32",
- "Fletcher-32",
- "Adler-32",
- ];
- break;
- case 64:
- possibleHashFunctions = [
- "CRC-64",
- "RIPEMD-64",
- "SipHash",
- ];
- break;
- case 128:
- possibleHashFunctions = [
- "MD5",
- "MD4",
- "MD2",
- "HAVAL-128",
- "RIPEMD-128",
- "Snefru",
- "Tiger-128",
- ];
- break;
- case 160:
- possibleHashFunctions = [
- "SHA-1",
- "SHA-0",
- "FSB-160",
- "HAS-160",
- "HAVAL-160",
- "RIPEMD-160",
- "Tiger-160",
- ];
- break;
- case 192:
- possibleHashFunctions = [
- "Tiger",
- "HAVAL-192",
- ];
- break;
- case 224:
- possibleHashFunctions = [
- "SHA-224",
- "SHA3-224",
- "ECOH-224",
- "FSB-224",
- "HAVAL-224",
- ];
- break;
- case 256:
- possibleHashFunctions = [
- "SHA-256",
- "SHA3-256",
- "BLAKE-256",
- "ECOH-256",
- "FSB-256",
- "GOST",
- "Grøstl-256",
- "HAVAL-256",
- "PANAMA",
- "RIPEMD-256",
- "Snefru",
- ];
- break;
- case 320:
- possibleHashFunctions = [
- "RIPEMD-320",
- ];
- break;
- case 384:
- possibleHashFunctions = [
- "SHA-384",
- "SHA3-384",
- "ECOH-384",
- "FSB-384",
- ];
- break;
- case 512:
- possibleHashFunctions = [
- "SHA-512",
- "SHA3-512",
- "BLAKE-512",
- "ECOH-512",
- "FSB-512",
- "Grøstl-512",
- "JH",
- "MD6",
- "Spectral Hash",
- "SWIFFT",
- "Whirlpool",
- ];
- break;
- case 1024:
- possibleHashFunctions = [
- "Fowler-Noll-Vo",
- ];
- break;
- default:
- possibleHashFunctions = [
- "Unknown"
- ];
- break;
- }
- return output + possibleHashFunctions.join("\n");
- },
- };
- export default Hash;
|