implementazione MD5 più veloce in JavaScript

Ci sono molte implementazioni di MD5 JavaScript là fuori. Qualcuno sa qual è il più avanzato, il più bugfixed e il più veloce?

Ne ho bisogno per questo strumento.

Ho sentito che l’implementazione di Joseph’s Myers è abbastanza veloce. Inoltre, ha un lungo articolo sull’ottimizzazione Javascript che descrive ciò che ha imparato durante la scrittura della sua implementazione. È una buona lettura per chiunque sia interessato a javascript performante.

http://www.webreference.com/programming/javascript/jkm3/

La sua implementazione MD5 può essere trovata qui

Ti suggerirei di utilizzare CryptoJS in questo caso.

Fondamentalmente CryptoJS è una raccolta crescente di algoritmi crittografici standard e sicuri implementati in JavaScript utilizzando le migliori pratiche e modelli. Sono veloci e hanno un’interfaccia coerente e semplice.

Quindi, se si desidera calcolare l’hash MD5 della stringa della password, procedere come segue:

   

Quindi questo script pubblicherà l’hash della stringa della password sul server.

Per ulteriori informazioni e supporto su altri algoritmi di calcolo hash puoi visitare:

http://code.google.com/p/crypto-js/

Mentre si seleziona la libreria è anche importante vedere se supporta i moderni framework come Bower, passa jslint, supporta il modello di plugin per JQuery o i sistemi di moduli come AMD / RequireJS oltre ad essere in sviluppo attivo e avere più di 1 contributori. Esistono un paio di opzioni che soddisfano alcuni o tutti questi criteri aggiuntivi:

  • CryptoJS : questa è forse la libreria più estesa in cui ogni algoritmo può essere usato separatamente senza aggiungere grasso al tuo codice JS. In più come encoder / decodificatore per UTF8, UTF16 e Base64. Gestisco il repository github registrato come pacchetto Bower e le istruzioni su come utilizzarlo con RequireJS.
  • Spark MD5 : questo è basato sul codice JKM che altre risposte menzionano, che è anche l’implementazione più rapida. Tuttavia, l’implementazione Spark aggiunge il supporto AMD, passa jslint plus ha una modalità incrementale. Non ha Base64 o / p ma ha raw o / p (cioè array di 32-bit int insead di stringa).
  • Plugin JQuery MD5 : molto semplice, ma non sembra avere la modalità raw.
  • JavaScript-MD5 : non elegante o veloce come Spark ma più semplice.

Esempio da CryptoJS:

 //just include md5.js from the CryptoJS rollups folder var hash = CryptoJS.MD5("Message"); console.log(hash.toString()); 

Esiste un confronto delle prestazioni tra le librerie sopra a http://jsperf.com/md5-shootout/7 . Sulla mia macchina i test attuali (che sono certamente vecchi) mostrano che se stai cercando la velocità, Spark MD5 è la soluzione migliore (e quindi è un semplice codice JKM). Tuttavia, se stai cercando una libreria più completa, CryptoJS è la soluzione migliore, sebbene sia il 79% più lento di Spark MD5. Comunque immagino che CryptoJS alla fine raggiungerà la stessa velocità in quanto è un po ‘più attivo del progetto.

Ho trovato una serie di articoli su questo argomento. Tutti hanno suggerito l’implementazione di Joseph Meyers.

vedi: http://jsperf.com/md5-shootout su alcuni test

Nella mia ricerca della massima velocità ho guardato questo codice, ho visto che poteva essere migliorato. Così ho creato un nuovo script JS basato sul codice Joseph Meyers.

vedere il codice di Jospeh Meyers migliorato

Devo solo supportare i browser HTML5 che supportano gli array digitati (DataView, ArrayBuffer, ecc.) Penso di aver preso il codice Joseph Myers e di averlo modificato per supportare il passaggio in un Uint8Array. Non ho preso tutti i miglioramenti, e ci sono ancora probabilmente alcuni artefatti di array char () che possono essere migliorati. Ne avevo bisogno per l’aggiunta al progetto PouchDB.

 var PouchUtils = {}; PouchUtils.Crypto = {}; (function () { PouchUtils.Crypto.MD5 = function (uint8Array) { function md5cycle(x, k) { var a = x[0], b = x[1], c = x[2], d = x[3]; a = ff(a, b, c, d, k[0], 7, -680876936); d = ff(d, a, b, c, k[1], 12, -389564586); c = ff(c, d, a, b, k[2], 17, 606105819); b = ff(b, c, d, a, k[3], 22, -1044525330); a = ff(a, b, c, d, k[4], 7, -176418897); d = ff(d, a, b, c, k[5], 12, 1200080426); c = ff(c, d, a, b, k[6], 17, -1473231341); b = ff(b, c, d, a, k[7], 22, -45705983); a = ff(a, b, c, d, k[8], 7, 1770035416); d = ff(d, a, b, c, k[9], 12, -1958414417); c = ff(c, d, a, b, k[10], 17, -42063); b = ff(b, c, d, a, k[11], 22, -1990404162); a = ff(a, b, c, d, k[12], 7, 1804603682); d = ff(d, a, b, c, k[13], 12, -40341101); c = ff(c, d, a, b, k[14], 17, -1502002290); b = ff(b, c, d, a, k[15], 22, 1236535329); a = gg(a, b, c, d, k[1], 5, -165796510); d = gg(d, a, b, c, k[6], 9, -1069501632); c = gg(c, d, a, b, k[11], 14, 643717713); b = gg(b, c, d, a, k[0], 20, -373897302); a = gg(a, b, c, d, k[5], 5, -701558691); d = gg(d, a, b, c, k[10], 9, 38016083); c = gg(c, d, a, b, k[15], 14, -660478335); b = gg(b, c, d, a, k[4], 20, -405537848); a = gg(a, b, c, d, k[9], 5, 568446438); d = gg(d, a, b, c, k[14], 9, -1019803690); c = gg(c, d, a, b, k[3], 14, -187363961); b = gg(b, c, d, a, k[8], 20, 1163531501); a = gg(a, b, c, d, k[13], 5, -1444681467); d = gg(d, a, b, c, k[2], 9, -51403784); c = gg(c, d, a, b, k[7], 14, 1735328473); b = gg(b, c, d, a, k[12], 20, -1926607734); a = hh(a, b, c, d, k[5], 4, -378558); d = hh(d, a, b, c, k[8], 11, -2022574463); c = hh(c, d, a, b, k[11], 16, 1839030562); b = hh(b, c, d, a, k[14], 23, -35309556); a = hh(a, b, c, d, k[1], 4, -1530992060); d = hh(d, a, b, c, k[4], 11, 1272893353); c = hh(c, d, a, b, k[7], 16, -155497632); b = hh(b, c, d, a, k[10], 23, -1094730640); a = hh(a, b, c, d, k[13], 4, 681279174); d = hh(d, a, b, c, k[0], 11, -358537222); c = hh(c, d, a, b, k[3], 16, -722521979); b = hh(b, c, d, a, k[6], 23, 76029189); a = hh(a, b, c, d, k[9], 4, -640364487); d = hh(d, a, b, c, k[12], 11, -421815835); c = hh(c, d, a, b, k[15], 16, 530742520); b = hh(b, c, d, a, k[2], 23, -995338651); a = ii(a, b, c, d, k[0], 6, -198630844); d = ii(d, a, b, c, k[7], 10, 1126891415); c = ii(c, d, a, b, k[14], 15, -1416354905); b = ii(b, c, d, a, k[5], 21, -57434055); a = ii(a, b, c, d, k[12], 6, 1700485571); d = ii(d, a, b, c, k[3], 10, -1894986606); c = ii(c, d, a, b, k[10], 15, -1051523); b = ii(b, c, d, a, k[1], 21, -2054922799); a = ii(a, b, c, d, k[8], 6, 1873313359); d = ii(d, a, b, c, k[15], 10, -30611744); c = ii(c, d, a, b, k[6], 15, -1560198380); b = ii(b, c, d, a, k[13], 21, 1309151649); a = ii(a, b, c, d, k[4], 6, -145523070); d = ii(d, a, b, c, k[11], 10, -1120210379); c = ii(c, d, a, b, k[2], 15, 718787259); b = ii(b, c, d, a, k[9], 21, -343485551); x[0] = add32(a, x[0]); x[1] = add32(b, x[1]); x[2] = add32(c, x[2]); x[3] = add32(d, x[3]); } function cmn(q, a, b, x, s, t) { a = add32(add32(a, q), add32(x, t)); return add32((a < < s) | (a >>> (32 - s)), b); } function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); } function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); } function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); } function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); } function md51(s) { txt = ''; var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i; for (i = 64; i < = s.length; i += 64) { md5cycle(state, md5blk(s.subarray(i - 64, i))); } s = s.subarray(i - 64); var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < s.length; i++) tail[i >> 2] |= s[i] < < ((i % 4) << 3); tail[i >> 2] |= 0x80 < < ((i % 4) << 3); if (i > 55) { md5cycle(state, tail); for (i = 0; i < 16; i++) tail[i] = 0; } tail[14] = n * 8; md5cycle(state, tail); return state; } /* there needs to be support for Unicode here, * unless we pretend that we can redefine the MD-5 * algorithm for multi-byte characters (perhaps * by adding every four 16-bit characters and * shortening the sum to 32 bits). Otherwise * I suggest performing MD-5 as if every character * was two bytes--eg, 0040 0025 = @%--but then * how will an ordinary MD-5 sum be matched? * There is no way to standardize text to something * like UTF-8 before transformation; speed cost is * utterly prohibitive. The JavaScript standard * itself needs to look at this: it should start * providing access to strings as preformed UTF-8 * 8-bit unsigned value arrays. */ function md5blk(s) { /* I figured global was faster. */ var md5blks = [], i; /* Andy King said do it this way. */ for (i = 0; i < 64; i += 4) { md5blks[i >> 2] = s[i] + (s[i + 1] < < 8) + (s[i + 2] << 16) + (s[i + 3] << 24); } return md5blks; } var hex_chr = '0123456789abcdef'.split(''); function rhex(n) { var s = '', j = 0; for (; j < 4; j++) s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]; return s; } function hex(x) { for (var i = 0; i < x.length; i++) x[i] = rhex(x[i]); return x.join(''); } function md5(s) { return hex(md51(s)); } function add32(a, b) { return (a + b) & 0xFFFFFFFF; } return md5(uint8Array); }; })(); 

Attualmente l’implementazione più veloce di md5 (basata sul codice di Joseph Myers):

https://github.com/iReal/FastMD5

comparaison jsPerf: http://jsperf.com/md5-shootout/63

Ho scritto test per confrontare diverse implementazioni di hash JavaScript, inclusa la maggior parte delle implementazioni MD5 menzionate qui. Per eseguire i test, vai su http://brillout.github.io/test-javascript-hash-implementations/ e aspetta un po ‘.

Sembra che l’implementazione YaMD5 della risposta di R. Hill sia la più veloce.

 MD5 = function(e) { function h(a, b) { var c, d, e, f, g; e = a & 2147483648; f = b & 2147483648; c = a & 1073741824; d = b & 1073741824; g = (a & 1073741823) + (b & 1073741823); return c & d ? g ^ 2147483648 ^ e ^ f : c | d ? g & 1073741824 ? g ^ 3221225472 ^ e ^ f : g ^ 1073741824 ^ e ^ f : g ^ e ^ f } function k(a, b, c, d, e, f, g) { a = h(a, h(h(b & c | ~b & d, e), g)); return h(a < < f | a >>> 32 - f, b) } function l(a, b, c, d, e, f, g) { a = h(a, h(h(b & d | c & ~d, e), g)); return h(a < < f | a >>> 32 - f, b) } function m(a, b, d, c, e, f, g) { a = h(a, h(h(b ^ d ^ c, e), g)); return h(a < < f | a >>> 32 - f, b) } function n(a, b, d, c, e, f, g) { a = h(a, h(h(d ^ (b | ~c), e), g)); return h(a < < f | a >>> 32 - f, b) } function p(a) { var b = "", d = "", c; for (c = 0; 3 >= c; c++) d = a >>> 8 * c & 255, d = "0" + d.toString(16), b += d.substr(d.length - 2, 2); return b } var f = [], q, r, s, t, a, b, c, d; e = function(a) { a = a.replace(/\r\n/g, "\n"); for (var b = "", d = 0; d < a.length; d++) { var c = a.charCodeAt(d); 128 > c ? b += String.fromCharCode(c) : (127 < c && 2048 > c ? b += String.fromCharCode(c >> 6 | 192) : (b += String.fromCharCode(c >> 12 | 224), b += String.fromCharCode(c >> 6 & 63 | 128)), b += String.fromCharCode(c & 63 | 128)) } return b }(e); f = function(b) { var a, c = b.length; a = c + 8; for (var d = 16 * ((a - a % 64) / 64 + 1), e = Array(d - 1), f = 0, g = 0; g < c;) a = (g - g % 4) / 4, f = g % 4 * 8, e[a] |= b.charCodeAt(g) << f, g++; a = (g - g % 4) / 4; e[a] |= 128 << g % 4 * 8; e[d - 2] = c << 3; e[d - 1] = c >>> 29; return e }(e); a = 1732584193; b = 4023233417; c = 2562383102; d = 271733878; for (e = 0; e < f.length; e += 16) q = a, r = b, s = c, t = d, a = k(a, b, c, d, f[e + 0], 7, 3614090360), d = k(d, a, b, c, f[e + 1], 12, 3905402710), c = k(c, d, a, b, f[e + 2], 17, 606105819), b = k(b, c, d, a, f[e + 3], 22, 3250441966), a = k(a, b, c, d, f[e + 4], 7, 4118548399), d = k(d, a, b, c, f[e + 5], 12, 1200080426), c = k(c, d, a, b, f[e + 6], 17, 2821735955), b = k(b, c, d, a, f[e + 7], 22, 4249261313), a = k(a, b, c, d, f[e + 8], 7, 1770035416), d = k(d, a, b, c, f[e + 9], 12, 2336552879), c = k(c, d, a, b, f[e + 10], 17, 4294925233), b = k(b, c, d, a, f[e + 11], 22, 2304563134), a = k(a, b, c, d, f[e + 12], 7, 1804603682), d = k(d, a, b, c, f[e + 13], 12, 4254626195), c = k(c, d, a, b, f[e + 14], 17, 2792965006), b = k(b, c, d, a, f[e + 15], 22, 1236535329), a = l(a, b, c, d, f[e + 1], 5, 4129170786), d = l(d, a, b, c, f[e + 6], 9, 3225465664), c = l(c, d, a, b, f[e + 11], 14, 643717713), b = l(b, c, d, a, f[e + 0], 20, 3921069994), a = l(a, b, c, d, f[e + 5], 5, 3593408605), d = l(d, a, b, c, f[e + 10], 9, 38016083), c = l(c, d, a, b, f[e + 15], 14, 3634488961), b = l(b, c, d, a, f[e + 4], 20, 3889429448), a = l(a, b, c, d, f[e + 9], 5, 568446438), d = l(d, a, b, c, f[e + 14], 9, 3275163606), c = l(c, d, a, b, f[e + 3], 14, 4107603335), b = l(b, c, d, a, f[e + 8], 20, 1163531501), a = l(a, b, c, d, f[e + 13], 5, 2850285829), d = l(d, a, b, c, f[e + 2], 9, 4243563512), c = l(c, d, a, b, f[e + 7], 14, 1735328473), b = l(b, c, d, a, f[e + 12], 20, 2368359562), a = m(a, b, c, d, f[e + 5], 4, 4294588738), d = m(d, a, b, c, f[e + 8], 11, 2272392833), c = m(c, d, a, b, f[e + 11], 16, 1839030562), b = m(b, c, d, a, f[e + 14], 23, 4259657740), a = m(a, b, c, d, f[e + 1], 4, 2763975236), d = m(d, a, b, c, f[e + 4], 11, 1272893353), c = m(c, d, a, b, f[e + 7], 16, 4139469664), b = m(b, c, d, a, f[e + 10], 23, 3200236656), a = m(a, b, c, d, f[e + 13], 4, 681279174), d = m(d, a, b, c, f[e + 0], 11, 3936430074), c = m(c, d, a, b, f[e + 3], 16, 3572445317), b = m(b, c, d, a, f[e + 6], 23, 76029189), a = m(a, b, c, d, f[e + 9], 4, 3654602809), d = m(d, a, b, c, f[e + 12], 11, 3873151461), c = m(c, d, a, b, f[e + 15], 16, 530742520), b = m(b, c, d, a, f[e + 2], 23, 3299628645), a = n(a, b, c, d, f[e + 0], 6, 4096336452), d = n(d, a, b, c, f[e + 7], 10, 1126891415), c = n(c, d, a, b, f[e + 14], 15, 2878612391), b = n(b, c, d, a, f[e + 5], 21, 4237533241), a = n(a, b, c, d, f[e + 12], 6, 1700485571), d = n(d, a, b, c, f[e + 3], 10, 2399980690), c = n(c, d, a, b, f[e + 10], 15, 4293915773), b = n(b, c, d, a, f[e + 1], 21, 2240044497), a = n(a, b, c, d, f[e + 8], 6, 1873313359), d = n(d, a, b, c, f[e + 15], 10, 4264355552), c = n(c, d, a, b, f[e + 6], 15, 2734768916), b = n(b, c, d, a, f[e + 13], 21, 1309151649), a = n(a, b, c, d, f[e + 4], 6, 4149444226), d = n(d, a, b, c, f[e + 11], 10, 3174756917), c = n(c, d, a, b, f[e + 2], 15, 718787259), b = n(b, c, d, a, f[e + 9], 21, 3951481745), a = h(a, q), b = h(b, r), c = h(c, s), d = h(d, t); return (p(a) + p(b) + p(c) + p(d)).toLowerCase() }; 

Mi ha infastidito il fatto che non sono riuscito a trovare un’implementazione che sia veloce e supporta le stringhe Unicode.

Ne ho creato uno che supporta le stringhe Unicode e mostra ancora più velocemente (al momento della scrittura) rispetto alle implementazioni di stringhe ascii attualmente più veloci:

https://github.com/gorhill/yamd5.js

Basato sul codice di Joseph Myers, ma utilizza TypedArrays, oltre ad altri miglioramenti.

L’hash molto più veloce dovrebbe essere ansible calcolando sulla scheda grafica (implementare l’algoritmo di hash in WebGL), come discusso in merito a SHA256: è ansible calcolare gli hash sha256 nel browser utilizzando la scheda video dell’utente, ad es. usando WebGL o Flash?

js-md5 supporta stringa UTF-8, array, ArrayBuffer, AMD ….

e veloce. jsperf

Perché non provare http://phpjs.org/functions/md5/ ?

Sfortunatamente le prestazioni sono limitate con qualsiasi script emulato, tuttavia questo può rendere reale l’hash MD5. Anche se consiglierei di usare md5 per le password, visto che si tratta di un hash veloce reso.

Puoi anche controllare la mia implementazione md5 . Dovrebbe essere ca. lo stesso dell’altro pubblicato sopra. Sfortunatamente, le prestazioni sono limitate dal ciclo interno che è imansible ottimizzare di più.

Se le prestazioni della tua applicazione sono limitate da un’implementazione Javascript di MD5, allora stai davvero facendo qualcosa di sbagliato. Considerare un cambiamento architettonico (suggerimento: usare MD5 meno spesso)