From ede8b465e1463915a3d7808d4681906f223b43b8 Mon Sep 17 00:00:00 2001 From: Luca Conte Date: Mon, 17 Feb 2025 16:52:37 +0100 Subject: [PATCH] add hashers --- controllers/module-controller.js | 25 ++ elements/MD5Hasher.js | 11 + elements/SHA256Hasher.js | 11 + index.html | 3 + modules/md5.js | 402 +++++++++++++++++++++++++++++++ modules/sha256.js | 107 ++++++++ 6 files changed, 559 insertions(+) create mode 100644 controllers/module-controller.js create mode 100644 elements/MD5Hasher.js create mode 100644 elements/SHA256Hasher.js create mode 100644 modules/md5.js create mode 100644 modules/sha256.js diff --git a/controllers/module-controller.js b/controllers/module-controller.js new file mode 100644 index 0000000..b73c5e2 --- /dev/null +++ b/controllers/module-controller.js @@ -0,0 +1,25 @@ +class ModuleController { + static STATUS_UNLOADED = 0; + static STATUS_LOADING = 1; + static STATUS_LOADED = 2; + + static MODULES = { + "md5": { file: "md5.js", status: this.STATUS_UNLOADED }, + "sha256": { file: "sha256.js", status: this.STATUS_UNLOADED }, + }; + + static loadModule(module) { + if (module.status == this.STATUS_UNLOADED) { + + module.status = this.STATUS_LOADING; + + let script = document.createElement("script"); + script.src = "modules/" + module.file; + document.body.appendChild(script); + + script.addEventListener("load", () => { + module.status = this.STATUS_LOADED; + }); + } + } +} \ No newline at end of file diff --git a/elements/MD5Hasher.js b/elements/MD5Hasher.js new file mode 100644 index 0000000..5ca4969 --- /dev/null +++ b/elements/MD5Hasher.js @@ -0,0 +1,11 @@ +class MD5Hasher extends Converter { + constructor() { + super("MD5 Hasher", [ + { label : "Hash", conversionFunction : (d) => md5(d) }, + ]); + + ModuleController.loadModule(ModuleController.MODULES.md5); + + this.outputs[0].type = "string"; + } +} \ No newline at end of file diff --git a/elements/SHA256Hasher.js b/elements/SHA256Hasher.js new file mode 100644 index 0000000..09b2bba --- /dev/null +++ b/elements/SHA256Hasher.js @@ -0,0 +1,11 @@ +class SHA256Hasher extends Converter { + constructor() { + super("SHA256 Hasher", [ + { label : "Hash", conversionFunction : (d) => SHA256(d.toString()) }, + ]); + + ModuleController.loadModule(ModuleController.MODULES.sha256); + + this.outputs[0].type = "string"; + } +} \ No newline at end of file diff --git a/index.html b/index.html index 37fe91a..b03fde4 100644 --- a/index.html +++ b/index.html @@ -14,10 +14,13 @@ + + + diff --git a/modules/md5.js b/modules/md5.js new file mode 100644 index 0000000..263b1c5 --- /dev/null +++ b/modules/md5.js @@ -0,0 +1,402 @@ +/* + * JavaScript MD5 + * https://github.com/blueimp/JavaScript-MD5 + * + * Copyright 2011, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * https://opensource.org/licenses/MIT + * + * Based on + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for more info. + */ + +/* global define */ + +/* eslint-disable strict */ + +;(function ($) { + 'use strict' + + /** + * Add integers, wrapping at 2^32. + * This uses 16-bit operations internally to work around bugs in interpreters. + * + * @param {number} x First integer + * @param {number} y Second integer + * @returns {number} Sum + */ + function safeAdd(x, y) { + var lsw = (x & 0xffff) + (y & 0xffff) + var msw = (x >> 16) + (y >> 16) + (lsw >> 16) + return (msw << 16) | (lsw & 0xffff) + } + + /** + * Bitwise rotate a 32-bit number to the left. + * + * @param {number} num 32-bit number + * @param {number} cnt Rotation count + * @returns {number} Rotated number + */ + function bitRotateLeft(num, cnt) { + return (num << cnt) | (num >>> (32 - cnt)) + } + + /** + * Basic operation the algorithm uses. + * + * @param {number} q q + * @param {number} a a + * @param {number} b b + * @param {number} x x + * @param {number} s s + * @param {number} t t + * @returns {number} Result + */ + function md5cmn(q, a, b, x, s, t) { + return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b) + } + /** + * Basic operation the algorithm uses. + * + * @param {number} a a + * @param {number} b b + * @param {number} c c + * @param {number} d d + * @param {number} x x + * @param {number} s s + * @param {number} t t + * @returns {number} Result + */ + function md5ff(a, b, c, d, x, s, t) { + return md5cmn((b & c) | (~b & d), a, b, x, s, t) + } + /** + * Basic operation the algorithm uses. + * + * @param {number} a a + * @param {number} b b + * @param {number} c c + * @param {number} d d + * @param {number} x x + * @param {number} s s + * @param {number} t t + * @returns {number} Result + */ + function md5gg(a, b, c, d, x, s, t) { + return md5cmn((b & d) | (c & ~d), a, b, x, s, t) + } + /** + * Basic operation the algorithm uses. + * + * @param {number} a a + * @param {number} b b + * @param {number} c c + * @param {number} d d + * @param {number} x x + * @param {number} s s + * @param {number} t t + * @returns {number} Result + */ + function md5hh(a, b, c, d, x, s, t) { + return md5cmn(b ^ c ^ d, a, b, x, s, t) + } + /** + * Basic operation the algorithm uses. + * + * @param {number} a a + * @param {number} b b + * @param {number} c c + * @param {number} d d + * @param {number} x x + * @param {number} s s + * @param {number} t t + * @returns {number} Result + */ + function md5ii(a, b, c, d, x, s, t) { + return md5cmn(c ^ (b | ~d), a, b, x, s, t) + } + + /** + * Calculate the MD5 of an array of little-endian words, and a bit length. + * + * @param {Array} x Array of little-endian words + * @param {number} len Bit length + * @returns {Array} MD5 Array + */ + function binlMD5(x, len) { + /* append padding */ + x[len >> 5] |= 0x80 << len % 32 + x[(((len + 64) >>> 9) << 4) + 14] = len + + var i + var olda + var oldb + var oldc + var oldd + var a = 1732584193 + var b = -271733879 + var c = -1732584194 + var d = 271733878 + + for (i = 0; i < x.length; i += 16) { + olda = a + oldb = b + oldc = c + oldd = d + + a = md5ff(a, b, c, d, x[i], 7, -680876936) + d = md5ff(d, a, b, c, x[i + 1], 12, -389564586) + c = md5ff(c, d, a, b, x[i + 2], 17, 606105819) + b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330) + a = md5ff(a, b, c, d, x[i + 4], 7, -176418897) + d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426) + c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341) + b = md5ff(b, c, d, a, x[i + 7], 22, -45705983) + a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416) + d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417) + c = md5ff(c, d, a, b, x[i + 10], 17, -42063) + b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162) + a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682) + d = md5ff(d, a, b, c, x[i + 13], 12, -40341101) + c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290) + b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329) + + a = md5gg(a, b, c, d, x[i + 1], 5, -165796510) + d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632) + c = md5gg(c, d, a, b, x[i + 11], 14, 643717713) + b = md5gg(b, c, d, a, x[i], 20, -373897302) + a = md5gg(a, b, c, d, x[i + 5], 5, -701558691) + d = md5gg(d, a, b, c, x[i + 10], 9, 38016083) + c = md5gg(c, d, a, b, x[i + 15], 14, -660478335) + b = md5gg(b, c, d, a, x[i + 4], 20, -405537848) + a = md5gg(a, b, c, d, x[i + 9], 5, 568446438) + d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690) + c = md5gg(c, d, a, b, x[i + 3], 14, -187363961) + b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501) + a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467) + d = md5gg(d, a, b, c, x[i + 2], 9, -51403784) + c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473) + b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734) + + a = md5hh(a, b, c, d, x[i + 5], 4, -378558) + d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463) + c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562) + b = md5hh(b, c, d, a, x[i + 14], 23, -35309556) + a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060) + d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353) + c = md5hh(c, d, a, b, x[i + 7], 16, -155497632) + b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640) + a = md5hh(a, b, c, d, x[i + 13], 4, 681279174) + d = md5hh(d, a, b, c, x[i], 11, -358537222) + c = md5hh(c, d, a, b, x[i + 3], 16, -722521979) + b = md5hh(b, c, d, a, x[i + 6], 23, 76029189) + a = md5hh(a, b, c, d, x[i + 9], 4, -640364487) + d = md5hh(d, a, b, c, x[i + 12], 11, -421815835) + c = md5hh(c, d, a, b, x[i + 15], 16, 530742520) + b = md5hh(b, c, d, a, x[i + 2], 23, -995338651) + + a = md5ii(a, b, c, d, x[i], 6, -198630844) + d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415) + c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905) + b = md5ii(b, c, d, a, x[i + 5], 21, -57434055) + a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571) + d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606) + c = md5ii(c, d, a, b, x[i + 10], 15, -1051523) + b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799) + a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359) + d = md5ii(d, a, b, c, x[i + 15], 10, -30611744) + c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380) + b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649) + a = md5ii(a, b, c, d, x[i + 4], 6, -145523070) + d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379) + c = md5ii(c, d, a, b, x[i + 2], 15, 718787259) + b = md5ii(b, c, d, a, x[i + 9], 21, -343485551) + + a = safeAdd(a, olda) + b = safeAdd(b, oldb) + c = safeAdd(c, oldc) + d = safeAdd(d, oldd) + } + return [a, b, c, d] + } + + /** + * Convert an array of little-endian words to a string + * + * @param {Array} input MD5 Array + * @returns {string} MD5 string + */ + function binl2rstr(input) { + var i + var output = '' + var length32 = input.length * 32 + for (i = 0; i < length32; i += 8) { + output += String.fromCharCode((input[i >> 5] >>> i % 32) & 0xff) + } + return output + } + + /** + * Convert a raw string to an array of little-endian words + * Characters >255 have their high-byte silently ignored. + * + * @param {string} input Raw input string + * @returns {Array} Array of little-endian words + */ + function rstr2binl(input) { + var i + var output = [] + output[(input.length >> 2) - 1] = undefined + for (i = 0; i < output.length; i += 1) { + output[i] = 0 + } + var length8 = input.length * 8 + for (i = 0; i < length8; i += 8) { + output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << i % 32 + } + return output + } + + /** + * Calculate the MD5 of a raw string + * + * @param {string} s Input string + * @returns {string} Raw MD5 string + */ + function rstrMD5(s) { + return binl2rstr(binlMD5(rstr2binl(s), s.length * 8)) + } + + /** + * Calculates the HMAC-MD5 of a key and some data (raw strings) + * + * @param {string} key HMAC key + * @param {string} data Raw input string + * @returns {string} Raw MD5 string + */ + function rstrHMACMD5(key, data) { + var i + var bkey = rstr2binl(key) + var ipad = [] + var opad = [] + var hash + ipad[15] = opad[15] = undefined + if (bkey.length > 16) { + bkey = binlMD5(bkey, key.length * 8) + } + for (i = 0; i < 16; i += 1) { + ipad[i] = bkey[i] ^ 0x36363636 + opad[i] = bkey[i] ^ 0x5c5c5c5c + } + hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8) + return binl2rstr(binlMD5(opad.concat(hash), 512 + 128)) + } + + /** + * Convert a raw string to a hex string + * + * @param {string} input Raw input string + * @returns {string} Hex encoded string + */ + function rstr2hex(input) { + var hexTab = '0123456789abcdef' + var output = '' + var x + var i + for (i = 0; i < input.length; i += 1) { + x = input.charCodeAt(i) + output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f) + } + return output + } + + /** + * Encode a string as UTF-8 + * + * @param {string} input Input string + * @returns {string} UTF8 string + */ + function str2rstrUTF8(input) { + return unescape(encodeURIComponent(input)) + } + + /** + * Encodes input string as raw MD5 string + * + * @param {string} s Input string + * @returns {string} Raw MD5 string + */ + function rawMD5(s) { + return rstrMD5(str2rstrUTF8(s)) + } + /** + * Encodes input string as Hex encoded string + * + * @param {string} s Input string + * @returns {string} Hex encoded string + */ + function hexMD5(s) { + return rstr2hex(rawMD5(s)) + } + /** + * Calculates the raw HMAC-MD5 for the given key and data + * + * @param {string} k HMAC key + * @param {string} d Input string + * @returns {string} Raw MD5 string + */ + function rawHMACMD5(k, d) { + return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d)) + } + /** + * Calculates the Hex encoded HMAC-MD5 for the given key and data + * + * @param {string} k HMAC key + * @param {string} d Input string + * @returns {string} Raw MD5 string + */ + function hexHMACMD5(k, d) { + return rstr2hex(rawHMACMD5(k, d)) + } + + /** + * Calculates MD5 value for a given string. + * If a key is provided, calculates the HMAC-MD5 value. + * Returns a Hex encoded string unless the raw argument is given. + * + * @param {string} string Input string + * @param {string} [key] HMAC key + * @param {boolean} [raw] Raw output switch + * @returns {string} MD5 output + */ + function md5(string, key, raw) { + if (!key) { + if (!raw) { + return hexMD5(string) + } + return rawMD5(string) + } + if (!raw) { + return hexHMACMD5(key, string) + } + return rawHMACMD5(key, string) + } + + if (typeof define === 'function' && define.amd) { + define(function () { + return md5 + }) + } else if (typeof module === 'object' && module.exports) { + module.exports = md5 + } else { + $.md5 = md5 + } +})(this) \ No newline at end of file diff --git a/modules/sha256.js b/modules/sha256.js new file mode 100644 index 0000000..0dad789 --- /dev/null +++ b/modules/sha256.js @@ -0,0 +1,107 @@ +/** +* +* Secure Hash Algorithm (SHA256) +* http://www.webtoolkit.info/ +* +* Original code by Angel Marin, Paul Johnston. +* +**/ + +function SHA256(s){ + var chrsz = 8; + var hexcase = 0; + function safe_add (x, y) { + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); + } + function S (X, n) { return ( X >>> n ) | (X << (32 - n)); } + function R (X, n) { return ( X >>> n ); } + function Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); } + function Maj(x, y, z) { return ((x & y) ^ (x & z) ^ (y & z)); } + function Sigma0256(x) { return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); } + function Sigma1256(x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); } + function Gamma0256(x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); } + function Gamma1256(x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); } + function core_sha256 (m, l) { + var K = new Array(0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2); + var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19); + var W = new Array(64); + var a, b, c, d, e, f, g, h, i, j; + var T1, T2; + m[l >> 5] |= 0x80 << (24 - l % 32); + m[((l + 64 >> 9) << 4) + 15] = l; + for ( var i = 0; i>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32); + } + return bin; + } + function Utf8Encode(string) { + string = string.replace(/\r\n/g,"\n"); + var utftext = ""; + for (var n = 0; n < string.length; n++) { + var c = string.charCodeAt(n); + if (c < 128) { + utftext += String.fromCharCode(c); + } + else if((c > 127) && (c < 2048)) { + utftext += String.fromCharCode((c >> 6) | 192); + utftext += String.fromCharCode((c & 63) | 128); + } + else { + utftext += String.fromCharCode((c >> 12) | 224); + utftext += String.fromCharCode(((c >> 6) & 63) | 128); + utftext += String.fromCharCode((c & 63) | 128); + } + } + return utftext; + } + function binb2hex (binarray) { + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i++) { + str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + + hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); + } + return str; + } + s = Utf8Encode(s); + return binb2hex(core_sha256(str2binb(s), s.length * chrsz)); +} \ No newline at end of file