From 2427c4cd2449307925150ec121ba8984182db7af Mon Sep 17 00:00:00 2001 From: Waldir Pimenta Date: Mon, 23 Feb 2015 19:48:29 +0000 Subject: [PATCH 1/2] first version of sha256 --- bookmarklet.js | 125 ++++++++++--------------------------------------- 1 file changed, 26 insertions(+), 99 deletions(-) diff --git a/bookmarklet.js b/bookmarklet.js index 2b2620a..8089bcc 100644 --- a/bookmarklet.js +++ b/bookmarklet.js @@ -1,101 +1,28 @@ -var chrsz = 8; // size of password in chars -var b64pad = ""; // See http://en.wikipedia.org/wiki/Base64#Padding - -// main function -function b64_sha1(s) { - return binb2b64(core_sha1(str2binb(s), s.length * chrsz)); -} - -function core_sha1(x, len) { - x[len >> 5] |= 0x80 << (24 - len % 32); - x[((len + 64 >> 9) << 4) + 15] = len; - - var w = Array(80); - var a = 1732584193; - var b = -271733879; - var c = -1732584194; - var d = 271733878; - var e = -1009589776; - - for (var i = 0; i < x.length; i += 16) { - var olda = a; - var oldb = b; - var oldc = c; - var oldd = d; - var olde = e; - - for (var j = 0; j < 80; j++) { - if (j < 16) { - w[j] = x[i + j]; - } else { - w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); - } - var t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)), - safe_add(safe_add(e, w[j]), sha1_kt(j))); - e = d; - d = c; - c = bit_rol(b, 30); - b = a; - a = t; - } - - a = safe_add(a, olda); - b = safe_add(b, oldb); - c = safe_add(c, oldc); - d = safe_add(d, oldd); - e = safe_add(e, olde); - } - return Array(a, b, c, d, e); -} - -function sha1_ft(t, b, c, d) { - if (t < 20) { return (b & c) | ((~b) & d); } - if (t < 40) { return b ^ c ^ d; } - if (t < 60) { return (b & c) | (b & d) | (c & d); } - return b ^ c ^ d; -} - -function sha1_kt(t) { - return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : - (t < 60) ? -1894007588 : -899497514; -} - -// ROL = ROtate bits Left, aka Left circular shift -function bit_rol(num, cnt) { - return (num << cnt) | (num >>> (32 - cnt)); -} - -function str2binb(str) { - var bin = Array(); - var mask = (1 << chrsz) - 1; - for (var i = 0; i < str.length * chrsz; i += chrsz) { - bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32); - } - return bin; -} - -function safe_add(x, y) { - var lsw = (x & 0xFFFF) + (y & 0xFFFF); - var msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return (msw << 16) | (lsw & 0xFFFF); -} - -// Convert binary(?) to base64 -function binb2b64(binarray) { - // Base64 alphabet - var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - var str = ""; - for (var i = 0; i < binarray.length * 4; i += 3) { - var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16) - | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) - | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF); - for (var j = 0; j < 4; j++) { - if (i * 8 + j * 6 > binarray.length * 32) { str += b64pad; } - else { str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); } // 0x3F = 63 = '?' - } - } - return str; -} +// Slighly uncompressed version of https://github.com/geraintluff/sha256's minimized code +var base64_sha256 = function a(b) { + function c(a, b) { return a >>> b | a << 32 - b } + for (var d, e, f = Math.pow, g = f(2, 32), h = "length", i = "", j = [], k = 8 * b[h], l = a.h = a.h || [], m = a.k = a.k || [], n = m[h], o = {}, p = 2; 64 > n; p++) + if (!o[p]) { + for (d = 0; 313 > d; d += p) o[d] = p; + l[n] = f(p, .5) * g | 0, m[n++] = f(p, 1 / 3) * g | 0 } + for (b += "\x80"; b[h] % 64 - 56;) b += "\x00"; + for (d = 0; d < b[h]; d++) { + if (e = b.charCodeAt(d), e >> 8) return; + j[d >> 2] |= e << (3 - d) % 4 * 8 } + for (j[j[h]] = k / g | 0, j[j[h]] = k, e = 0; e < j[h];) { + var q = j.slice(e, e += 16), r = l; + for (l = l.slice(0, 8), d = 0; 64 > d; d++) { + var s = q[d - 15], t = q[d - 2], u = l[0], v = l[4], + w = l[7] + (c(v, 6) ^ c(v, 11) ^ c(v, 25)) + (v & l[5] ^ ~v & l[6]) + m[d] + (q[d] = 16 > d ? q[d] : q[d - 16] + (c(s, 7) ^ c(s, 18) ^ s >>> 3) + q[d - 7] + (c(t, 17) ^ c(t, 19) ^ t >>> 10) | 0), + x = (c(u, 2) ^ c(u, 13) ^ c(u, 22)) + (u & l[1] ^ u & l[2] ^ l[1] & l[2]); + l = [w + x | 0].concat(l), l[4] = l[4] + w | 0 } + for (d = 0; 8 > d; d++) l[d] = l[d] + r[d] | 0 } + for (d = 0; 8 > d; d++) + for (e = 3; e + 1; e--) { + var y = l[d] >> 8 * e & 255; + i += (16 > y ? 0 : "") + y.toString(16) } + return btoa(i); +}; function pressHashMyPass() { @@ -173,7 +100,7 @@ function hmp(master) { } // Generate a password that should be fairly secure and work on most websites: // 8 chars, upper and lowercase letters and numbers - var p = b64_sha1(master+':'+domain).substr(0,8); + var p = base64_sha256(master+':'+domain).substr(0,8); // Make sure it includes at least one number String.prototype.replaceAt = function(index, repStr) { return this.substr(0, index) + repStr + this.substr(index+repStr.toString().length); From 129f97107a5fd848f87442221aabdd3abdc6ef16 Mon Sep 17 00:00:00 2001 From: Waldir Pimenta Date: Mon, 23 Mar 2015 22:17:01 +0000 Subject: [PATCH 2/2] properly convert hex to base64 based on a snippet found at http://stackoverflow.com/q/23190056/ I am not actually sure this is better/more cryptographically sound, but it feels less of a hack than interpreting the base64 result as a string. --- bookmarklet.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bookmarklet.js b/bookmarklet.js index 8089bcc..cd7d27b 100644 --- a/bookmarklet.js +++ b/bookmarklet.js @@ -21,7 +21,8 @@ var base64_sha256 = function a(b) { for (e = 3; e + 1; e--) { var y = l[d] >> 8 * e & 255; i += (16 > y ? 0 : "") + y.toString(16) } - return btoa(i); + // convert hex to base64 (see dandavis's comment here: http://stackoverflow.com/q/23190056) + return btoa(i.match(/\w{2}/g).map(function(a){return String.fromCharCode(parseInt(a, 16));} ).join("")) }; function pressHashMyPass() {