Hash.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. import Utils from "../Utils.js";
  2. import CryptoApi from "crypto-api";
  3. import MD6 from "node-md6";
  4. import * as SHA3 from "js-sha3";
  5. import Checksum from "./Checksum.js";
  6. /**
  7. * Hashing operations.
  8. *
  9. * @author n1474335 [n1474335@gmail.com]
  10. * @copyright Crown Copyright 2016
  11. * @license Apache-2.0
  12. *
  13. * @namespace
  14. */
  15. const Hash = {
  16. /**
  17. * MD2 operation.
  18. *
  19. * @param {string} input
  20. * @param {Object[]} args
  21. * @returns {string}
  22. */
  23. runMD2: function (input, args) {
  24. return CryptoApi.hash("md2", input, {}).stringify("hex");
  25. },
  26. /**
  27. * MD4 operation.
  28. *
  29. * @param {string} input
  30. * @param {Object[]} args
  31. * @returns {string}
  32. */
  33. runMD4: function (input, args) {
  34. return CryptoApi.hash("md4", input, {}).stringify("hex");
  35. },
  36. /**
  37. * MD5 operation.
  38. *
  39. * @param {string} input
  40. * @param {Object[]} args
  41. * @returns {string}
  42. */
  43. runMD5: function (input, args) {
  44. return CryptoApi.hash("md5", input, {}).stringify("hex");
  45. },
  46. /**
  47. * @constant
  48. * @default
  49. */
  50. MD6_SIZE: 256,
  51. /**
  52. * @constant
  53. * @default
  54. */
  55. MD6_LEVELS: 64,
  56. /**
  57. * MD6 operation.
  58. *
  59. * @param {string} input
  60. * @param {Object[]} args
  61. * @returns {string}
  62. */
  63. runMD6: function (input, args) {
  64. const size = args[0],
  65. levels = args[1],
  66. key = args[2];
  67. if (size < 0 || size > 512)
  68. return "Size must be between 0 and 512";
  69. if (levels < 0)
  70. return "Levels must be greater than 0";
  71. return MD6.getHashOfText(input, size, key, levels);
  72. },
  73. /**
  74. * SHA0 operation.
  75. *
  76. * @param {string} input
  77. * @param {Object[]} args
  78. * @returns {string}
  79. */
  80. runSHA0: function (input, args) {
  81. return CryptoApi.hash("sha0", input, {}).stringify("hex");
  82. },
  83. /**
  84. * SHA1 operation.
  85. *
  86. * @param {string} input
  87. * @param {Object[]} args
  88. * @returns {string}
  89. */
  90. runSHA1: function (input, args) {
  91. return CryptoApi.hash("sha1", input, {}).stringify("hex");
  92. },
  93. /**
  94. * @constant
  95. * @default
  96. */
  97. SHA2_SIZE: ["512", "256", "384", "224", "512/256", "512/224"],
  98. /**
  99. * SHA2 operation.
  100. *
  101. * @param {string} input
  102. * @param {Object[]} args
  103. * @returns {string}
  104. */
  105. runSHA2: function (input, args) {
  106. const size = args[0];
  107. return CryptoApi.hash("sha" + size, input, {}).stringify("hex");
  108. },
  109. /**
  110. * @constant
  111. * @default
  112. */
  113. SHA3_SIZE: ["512", "384", "256", "224"],
  114. /**
  115. * SHA3 operation.
  116. *
  117. * @param {string} input
  118. * @param {Object[]} args
  119. * @returns {string}
  120. */
  121. runSHA3: function (input, args) {
  122. const size = parseInt(args[0], 10);
  123. let algo;
  124. switch (size) {
  125. case 224:
  126. algo = SHA3.sha3_224;
  127. break;
  128. case 384:
  129. algo = SHA3.sha3_384;
  130. break;
  131. case 256:
  132. algo = SHA3.sha3_256;
  133. break;
  134. case 512:
  135. algo = SHA3.sha3_512;
  136. break;
  137. default:
  138. return "Invalid size";
  139. }
  140. return algo(input);
  141. },
  142. /**
  143. * @constant
  144. * @default
  145. */
  146. KECCAK_SIZE: ["512", "384", "256", "224"],
  147. /**
  148. * Keccak operation.
  149. *
  150. * @param {string} input
  151. * @param {Object[]} args
  152. * @returns {string}
  153. */
  154. runKeccak: function (input, args) {
  155. const size = parseInt(args[0], 10);
  156. let algo;
  157. switch (size) {
  158. case 224:
  159. algo = SHA3.keccak224;
  160. break;
  161. case 384:
  162. algo = SHA3.keccak384;
  163. break;
  164. case 256:
  165. algo = SHA3.keccak256;
  166. break;
  167. case 512:
  168. algo = SHA3.keccak512;
  169. break;
  170. default:
  171. return "Invalid size";
  172. }
  173. return algo(input);
  174. },
  175. /**
  176. * @constant
  177. * @default
  178. */
  179. SHAKE_CAPACITY: ["256", "128"],
  180. /**
  181. * @constant
  182. * @default
  183. */
  184. SHAKE_SIZE: 512,
  185. /**
  186. * Shake operation.
  187. *
  188. * @param {string} input
  189. * @param {Object[]} args
  190. * @returns {string}
  191. */
  192. runShake: function (input, args) {
  193. const capacity = parseInt(args[0], 10),
  194. size = args[1];
  195. let algo;
  196. if (size < 0)
  197. return "Size must be greater than 0";
  198. switch (capacity) {
  199. case 128:
  200. algo = SHA3.shake128;
  201. break;
  202. case 256:
  203. algo = SHA3.shake256;
  204. break;
  205. default:
  206. return "Invalid size";
  207. }
  208. return algo(input, size);
  209. },
  210. /**
  211. * @constant
  212. * @default
  213. */
  214. RIPEMD_SIZE: ["320", "256", "160", "128"],
  215. /**
  216. * RIPEMD operation.
  217. *
  218. * @param {string} input
  219. * @param {Object[]} args
  220. * @returns {string}
  221. */
  222. runRIPEMD: function (input, args) {
  223. const size = args[0];
  224. return CryptoApi.hash("ripemd" + size, input, {}).stringify("hex");
  225. },
  226. /**
  227. * HAS-160 operation.
  228. *
  229. * @param {string} input
  230. * @param {Object[]} args
  231. * @returns {string}
  232. */
  233. runHAS: function (input, args) {
  234. return CryptoApi.hash("has160", input, {}).stringify("hex");
  235. },
  236. /**
  237. * @constant
  238. * @default
  239. */
  240. WHIRLPOOL_VARIANT: ["Whirlpool", "Whirlpool-T", "Whirlpool-0"],
  241. /**
  242. * Whirlpool operation.
  243. *
  244. * @param {string} input
  245. * @param {Object[]} args
  246. * @returns {string}
  247. */
  248. runWhirlpool: function (input, args) {
  249. const variant = args[0].toLowerCase();
  250. return CryptoApi.hash(variant, input, {}).stringify("hex");
  251. },
  252. /**
  253. * @constant
  254. * @default
  255. */
  256. HMAC_FUNCTIONS: [
  257. "MD2",
  258. "MD4",
  259. "MD5",
  260. "SHA0",
  261. "SHA1",
  262. "SHA224",
  263. "SHA256",
  264. "SHA384",
  265. "SHA512",
  266. "SHA512/224",
  267. "SHA512/256",
  268. "RIPEMD128",
  269. "RIPEMD160",
  270. "RIPEMD256",
  271. "RIPEMD320",
  272. "HAS160",
  273. "Whirlpool",
  274. "Whirlpool-0",
  275. "Whirlpool-T"
  276. ],
  277. /**
  278. * HMAC operation.
  279. *
  280. * @param {string} input
  281. * @param {Object[]} args
  282. * @returns {string}
  283. */
  284. runHMAC: function (input, args) {
  285. const password = args[0],
  286. hashFunc = args[1].toLowerCase(),
  287. hmac = CryptoApi.mac("hmac", password, hashFunc, {});
  288. hmac.update(input);
  289. return hmac.finalize().stringify("hex");
  290. },
  291. /**
  292. * Generate all hashes operation.
  293. *
  294. * @param {string} input
  295. * @param {Object[]} args
  296. * @returns {string}
  297. */
  298. runAll: function (input, args) {
  299. let byteArray = Utils.strToByteArray(input),
  300. output = "MD2: " + Hash.runMD2(input, []) +
  301. "\nMD4: " + Hash.runMD4(input, []) +
  302. "\nMD5: " + Hash.runMD5(input, []) +
  303. "\nMD6: " + Hash.runMD6(input, []) +
  304. "\nSHA0: " + Hash.runSHA0(input, []) +
  305. "\nSHA1: " + Hash.runSHA1(input, []) +
  306. "\nSHA2 224: " + Hash.runSHA2(input, ["224"]) +
  307. "\nSHA2 256: " + Hash.runSHA2(input, ["256"]) +
  308. "\nSHA2 384: " + Hash.runSHA2(input, ["384"]) +
  309. "\nSHA2 512: " + Hash.runSHA2(input, ["512"]) +
  310. "\nSHA3 224: " + Hash.runSHA3(input, ["224"]) +
  311. "\nSHA3 256: " + Hash.runSHA3(input, ["256"]) +
  312. "\nSHA3 384: " + Hash.runSHA3(input, ["384"]) +
  313. "\nSHA3 512: " + Hash.runSHA3(input, ["512"]) +
  314. "\nKeccak 224: " + Hash.runKeccak(input, ["224"]) +
  315. "\nKeccak 256: " + Hash.runKeccak(input, ["256"]) +
  316. "\nKeccak 384: " + Hash.runKeccak(input, ["384"]) +
  317. "\nKeccak 512: " + Hash.runKeccak(input, ["512"]) +
  318. "\nShake 128: " + Hash.runShake(input, ["128", 256]) +
  319. "\nShake 256: " + Hash.runShake(input, ["256", 512]) +
  320. "\nRIPEMD-128: " + Hash.runRIPEMD(input, ["128"]) +
  321. "\nRIPEMD-160: " + Hash.runRIPEMD(input, ["160"]) +
  322. "\nRIPEMD-256: " + Hash.runRIPEMD(input, ["256"]) +
  323. "\nRIPEMD-320: " + Hash.runRIPEMD(input, ["320"]) +
  324. "\nHAS-160: " + Hash.runHAS(input, []) +
  325. "\nWhirlpool-0: " + Hash.runWhirlpool(input, ["Whirlpool-0"]) +
  326. "\nWhirlpool-T: " + Hash.runWhirlpool(input, ["Whirlpool-T"]) +
  327. "\nWhirlpool: " + Hash.runWhirlpool(input, ["Whirlpool"]) +
  328. "\n\nChecksums:" +
  329. "\nFletcher-8: " + Checksum.runFletcher8(byteArray, []) +
  330. "\nFletcher-16: " + Checksum.runFletcher16(byteArray, []) +
  331. "\nFletcher-32: " + Checksum.runFletcher32(byteArray, []) +
  332. "\nFletcher-64: " + Checksum.runFletcher64(byteArray, []) +
  333. "\nAdler-32: " + Checksum.runAdler32(byteArray, []) +
  334. "\nCRC-16: " + Checksum.runCRC16(input, []) +
  335. "\nCRC-32: " + Checksum.runCRC32(input, []);
  336. return output;
  337. },
  338. /**
  339. * Analyse hash operation.
  340. *
  341. * @param {string} input
  342. * @param {Object[]} args
  343. * @returns {string}
  344. */
  345. runAnalyse: function(input, args) {
  346. input = input.replace(/\s/g, "");
  347. let output = "",
  348. byteLength = input.length / 2,
  349. bitLength = byteLength * 8,
  350. possibleHashFunctions = [];
  351. if (!/^[a-f0-9]+$/i.test(input)) {
  352. return "Invalid hash";
  353. }
  354. output += "Hash length: " + input.length + "\n" +
  355. "Byte length: " + byteLength + "\n" +
  356. "Bit length: " + bitLength + "\n\n" +
  357. "Based on the length, this hash could have been generated by one of the following hashing functions:\n";
  358. switch (bitLength) {
  359. case 4:
  360. possibleHashFunctions = [
  361. "Fletcher-4",
  362. "Luhn algorithm",
  363. "Verhoeff algorithm",
  364. ];
  365. break;
  366. case 8:
  367. possibleHashFunctions = [
  368. "Fletcher-8",
  369. ];
  370. break;
  371. case 16:
  372. possibleHashFunctions = [
  373. "BSD checksum",
  374. "CRC-16",
  375. "SYSV checksum",
  376. "Fletcher-16"
  377. ];
  378. break;
  379. case 32:
  380. possibleHashFunctions = [
  381. "CRC-32",
  382. "Fletcher-32",
  383. "Adler-32",
  384. ];
  385. break;
  386. case 64:
  387. possibleHashFunctions = [
  388. "CRC-64",
  389. "RIPEMD-64",
  390. "SipHash",
  391. ];
  392. break;
  393. case 128:
  394. possibleHashFunctions = [
  395. "MD5",
  396. "MD4",
  397. "MD2",
  398. "HAVAL-128",
  399. "RIPEMD-128",
  400. "Snefru",
  401. "Tiger-128",
  402. ];
  403. break;
  404. case 160:
  405. possibleHashFunctions = [
  406. "SHA-1",
  407. "SHA-0",
  408. "FSB-160",
  409. "HAS-160",
  410. "HAVAL-160",
  411. "RIPEMD-160",
  412. "Tiger-160",
  413. ];
  414. break;
  415. case 192:
  416. possibleHashFunctions = [
  417. "Tiger",
  418. "HAVAL-192",
  419. ];
  420. break;
  421. case 224:
  422. possibleHashFunctions = [
  423. "SHA-224",
  424. "SHA3-224",
  425. "ECOH-224",
  426. "FSB-224",
  427. "HAVAL-224",
  428. ];
  429. break;
  430. case 256:
  431. possibleHashFunctions = [
  432. "SHA-256",
  433. "SHA3-256",
  434. "BLAKE-256",
  435. "ECOH-256",
  436. "FSB-256",
  437. "GOST",
  438. "Grøstl-256",
  439. "HAVAL-256",
  440. "PANAMA",
  441. "RIPEMD-256",
  442. "Snefru",
  443. ];
  444. break;
  445. case 320:
  446. possibleHashFunctions = [
  447. "RIPEMD-320",
  448. ];
  449. break;
  450. case 384:
  451. possibleHashFunctions = [
  452. "SHA-384",
  453. "SHA3-384",
  454. "ECOH-384",
  455. "FSB-384",
  456. ];
  457. break;
  458. case 512:
  459. possibleHashFunctions = [
  460. "SHA-512",
  461. "SHA3-512",
  462. "BLAKE-512",
  463. "ECOH-512",
  464. "FSB-512",
  465. "Grøstl-512",
  466. "JH",
  467. "MD6",
  468. "Spectral Hash",
  469. "SWIFFT",
  470. "Whirlpool",
  471. ];
  472. break;
  473. case 1024:
  474. possibleHashFunctions = [
  475. "Fowler-Noll-Vo",
  476. ];
  477. break;
  478. default:
  479. possibleHashFunctions = [
  480. "Unknown"
  481. ];
  482. break;
  483. }
  484. return output + possibleHashFunctions.join("\n");
  485. },
  486. };
  487. export default Hash;