Last active
January 2, 2016 15:19
-
-
Save hswolff/8322978 to your computer and use it in GitHub Desktop.
sha_fun
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://www.movable-type.co.uk/scripts/sha1.html | |
// based off http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf | |
// minified size: 1320 bytes | |
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
/* SHA-1 implementation in JavaScript | (c) Chris Veness 2002-2013 | www.movable-type.co.uk */ | |
/* - see http://csrc.nist.gov/groups/ST/toolkit/secure_hashing.html */ | |
/* http://csrc.nist.gov/groups/ST/toolkit/examples.html */ | |
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
var Sha1 = {}; // Sha1 namespace | |
/** | |
* Generates SHA-1 hash of string | |
* | |
* @param {String} msg String to be hashed | |
* @param {Boolean} [utf8encode=true] Encode msg as UTF-8 before generating hash | |
* @returns {String} Hash of msg as hex character string | |
*/ | |
Sha1.hash = function(msg, utf8encode) { | |
utf8encode = (typeof utf8encode == 'undefined') ? true : utf8encode; | |
// convert string to UTF-8, as SHA only deals with byte-streams | |
if (utf8encode) msg = Utf8.encode(msg); | |
// constants [§4.2.1] | |
var K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6]; | |
// PREPROCESSING | |
msg += String.fromCharCode(0x80); // add trailing '1' bit (+ 0's padding) to string [§5.1.1] | |
// convert string msg into 512-bit/16-integer blocks arrays of ints [§5.2.1] | |
var l = msg.length/4 + 2; // length (in 32-bit integers) of msg + ‘1’ + appended length | |
var N = Math.ceil(l/16); // number of 16-integer-blocks required to hold 'l' ints | |
var M = new Array(N); | |
for (var i=0; i<N; i++) { | |
M[i] = new Array(16); | |
for (var j=0; j<16; j++) { // encode 4 chars per integer, big-endian encoding | |
M[i][j] = (msg.charCodeAt(i*64+j*4)<<24) | (msg.charCodeAt(i*64+j*4+1)<<16) | | |
(msg.charCodeAt(i*64+j*4+2)<<8) | (msg.charCodeAt(i*64+j*4+3)); | |
} // note running off the end of msg is ok 'cos bitwise ops on NaN return 0 | |
} | |
// add length (in bits) into final pair of 32-bit integers (big-endian) [§5.1.1] | |
// note: most significant word would be (len-1)*8 >>> 32, but since JS converts | |
// bitwise-op args to 32 bits, we need to simulate this by arithmetic operators | |
M[N-1][14] = ((msg.length-1)*8) / Math.pow(2, 32); M[N-1][14] = Math.floor(M[N-1][14]) | |
M[N-1][15] = ((msg.length-1)*8) & 0xffffffff; | |
// set initial hash value [§5.3.1] | |
var H0 = 0x67452301; | |
var H1 = 0xefcdab89; | |
var H2 = 0x98badcfe; | |
var H3 = 0x10325476; | |
var H4 = 0xc3d2e1f0; | |
// HASH COMPUTATION [§6.1.2] | |
var W = new Array(80); var a, b, c, d, e; | |
for (var i=0; i<N; i++) { | |
// 1 - prepare message schedule 'W' | |
for (var t=0; t<16; t++) W[t] = M[i][t]; | |
for (var t=16; t<80; t++) W[t] = Sha1.ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1); | |
// 2 - initialise five working variables a, b, c, d, e with previous hash value | |
a = H0; b = H1; c = H2; d = H3; e = H4; | |
// 3 - main loop | |
for (var t=0; t<80; t++) { | |
var s = Math.floor(t/20); // seq for blocks of 'f' functions and 'K' constants | |
var T = (Sha1.ROTL(a,5) + Sha1.f(s,b,c,d) + e + K[s] + W[t]) & 0xffffffff; | |
e = d; | |
d = c; | |
c = Sha1.ROTL(b, 30); | |
b = a; | |
a = T; | |
} | |
// 4 - compute the new intermediate hash value | |
H0 = (H0+a) & 0xffffffff; // note 'addition modulo 2^32' | |
H1 = (H1+b) & 0xffffffff; | |
H2 = (H2+c) & 0xffffffff; | |
H3 = (H3+d) & 0xffffffff; | |
H4 = (H4+e) & 0xffffffff; | |
} | |
return Sha1.toHexStr(H0) + Sha1.toHexStr(H1) + | |
Sha1.toHexStr(H2) + Sha1.toHexStr(H3) + Sha1.toHexStr(H4); | |
} | |
// | |
// function 'f' [§4.1.1] | |
// | |
Sha1.f = function(s, x, y, z) { | |
switch (s) { | |
case 0: return (x & y) ^ (~x & z); // Ch() | |
case 1: return x ^ y ^ z; // Parity() | |
case 2: return (x & y) ^ (x & z) ^ (y & z); // Maj() | |
case 3: return x ^ y ^ z; // Parity() | |
} | |
} | |
// | |
// rotate left (circular left shift) value x by n positions [§3.2.5] | |
// | |
Sha1.ROTL = function(x, n) { | |
return (x<<n) | (x>>>(32-n)); | |
} | |
// | |
// hexadecimal representation of a number | |
// (note toString(16) is implementation-dependant, and | |
// in IE returns signed numbers when used on full words) | |
// | |
Sha1.toHexStr = function(n) { | |
var s="", v; | |
for (var i=7; i>=0; i--) { v = (n>>>(i*4)) & 0xf; s += v.toString(16); } | |
return s; | |
} | |
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
/* Utf8 class: encode / decode between multi-byte Unicode characters and UTF-8 multiple */ | |
/* single-byte character encoding (c) Chris Veness 2002-2013 */ | |
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
var Utf8 = {}; // Utf8 namespace | |
/** | |
* Encode multi-byte Unicode string into utf-8 multiple single-byte characters | |
* (BMP / basic multilingual plane only) | |
* | |
* Chars in range U+0080 - U+07FF are encoded in 2 chars, U+0800 - U+FFFF in 3 chars | |
* | |
* @param {String} strUni Unicode string to be encoded as UTF-8 | |
* @returns {String} encoded string | |
*/ | |
Utf8.encode = function(strUni) { | |
// use regular expressions & String.replace callback function for better efficiency | |
// than procedural approaches | |
var strUtf = strUni.replace( | |
/[\u0080-\u07ff]/g, // U+0080 - U+07FF => 2 bytes 110yyyyy, 10zzzzzz | |
function(c) { | |
var cc = c.charCodeAt(0); | |
return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); } | |
); | |
strUtf = strUtf.replace( | |
/[\u0800-\uffff]/g, // U+0800 - U+FFFF => 3 bytes 1110xxxx, 10yyyyyy, 10zzzzzz | |
function(c) { | |
var cc = c.charCodeAt(0); | |
return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); } | |
); | |
return strUtf; | |
} | |
/** | |
* Decode utf-8 encoded string back into multi-byte Unicode characters | |
* | |
* @param {String} strUtf UTF-8 string to be decoded back to Unicode | |
* @returns {String} decoded string | |
*/ | |
Utf8.decode = function(strUtf) { | |
// note: decode 3-byte chars first as decoded 2-byte strings could appear to be 3-byte char! | |
var strUni = strUtf.replace( | |
/[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars | |
function(c) { // (note parentheses for precence) | |
var cc = ((c.charCodeAt(0)&0x0f)<<12) | ((c.charCodeAt(1)&0x3f)<<6) | ( c.charCodeAt(2)&0x3f); | |
return String.fromCharCode(cc); } | |
); | |
strUni = strUni.replace( | |
/[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars | |
function(c) { // (note parentheses for precence) | |
var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f; | |
return String.fromCharCode(cc); } | |
); | |
return strUni; | |
} | |
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
module.exports = Sha1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var crypto = require('crypto'), | |
shasum = crypto.createHash('sha1'); | |
var shaInput = "The quick brown fox jumps over the lazy dog"; | |
var expectedHash = '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'; | |
function testHash(input) { | |
console.log('hash',input); | |
console.log('equal?', input === expectedHash); | |
console.log(''); | |
} | |
shasum.update(shaInput); | |
testHash(shasum.digest('hex')); | |
// http://www.webtoolkit.info/javascript-sha1.html#.UssA72RDtGc | |
/** | |
* | |
* Secure Hash Algorithm (SHA1) | |
* http://www.webtoolkit.info/ | |
* | |
**/ | |
function SHA1 (msg) { | |
function rotate_left(n,s) { | |
var t4 = ( n<<s ) | (n>>>(32-s)); | |
return t4; | |
} | |
function lsb_hex(val) { | |
var str=""; | |
var i; | |
var vh; | |
var vl; | |
for( i=0; i<=6; i+=2 ) { | |
vh = (val>>>(i*4+4))&0x0f; | |
vl = (val>>>(i*4))&0x0f; | |
str += vh.toString(16) + vl.toString(16); | |
} | |
return str; | |
} | |
function cvt_hex(val) { | |
var str=""; | |
var i; | |
var v; | |
for( i=7; i>=0; i-- ) { | |
v = (val>>>(i*4))&0x0f; | |
str += v.toString(16); | |
} | |
return str; | |
} | |
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; | |
} | |
var blockstart; | |
var i, j; | |
var W = new Array(80); | |
var H0 = 0x67452301; | |
var H1 = 0xEFCDAB89; | |
var H2 = 0x98BADCFE; | |
var H3 = 0x10325476; | |
var H4 = 0xC3D2E1F0; | |
var A, B, C, D, E; | |
var temp; | |
msg = Utf8Encode(msg); | |
var msg_len = msg.length; | |
var word_array = new Array(); | |
for( i=0; i<msg_len-3; i+=4 ) { | |
j = msg.charCodeAt(i)<<24 | msg.charCodeAt(i+1)<<16 | | |
msg.charCodeAt(i+2)<<8 | msg.charCodeAt(i+3); | |
word_array.push( j ); | |
} | |
switch( msg_len % 4 ) { | |
case 0: | |
i = 0x080000000; | |
break; | |
case 1: | |
i = msg.charCodeAt(msg_len-1)<<24 | 0x0800000; | |
break; | |
case 2: | |
i = msg.charCodeAt(msg_len-2)<<24 | msg.charCodeAt(msg_len-1)<<16 | 0x08000; | |
break; | |
case 3: | |
i = msg.charCodeAt(msg_len-3)<<24 | msg.charCodeAt(msg_len-2)<<16 | msg.charCodeAt(msg_len-1)<<8 | 0x80; | |
break; | |
} | |
word_array.push( i ); | |
while( (word_array.length % 16) != 14 ) word_array.push( 0 ); | |
word_array.push( msg_len>>>29 ); | |
word_array.push( (msg_len<<3)&0x0ffffffff ); | |
for ( blockstart=0; blockstart<word_array.length; blockstart+=16 ) { | |
for( i=0; i<16; i++ ) W[i] = word_array[blockstart+i]; | |
for( i=16; i<=79; i++ ) W[i] = rotate_left(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); | |
A = H0; | |
B = H1; | |
C = H2; | |
D = H3; | |
E = H4; | |
for( i= 0; i<=19; i++ ) { | |
temp = (rotate_left(A,5) + ((B&C) | (~B&D)) + E + W[i] + 0x5A827999) & 0x0ffffffff; | |
E = D; | |
D = C; | |
C = rotate_left(B,30); | |
B = A; | |
A = temp; | |
} | |
for( i=20; i<=39; i++ ) { | |
temp = (rotate_left(A,5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff; | |
E = D; | |
D = C; | |
C = rotate_left(B,30); | |
B = A; | |
A = temp; | |
} | |
for( i=40; i<=59; i++ ) { | |
temp = (rotate_left(A,5) + ((B&C) | (B&D) | (C&D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff; | |
E = D; | |
D = C; | |
C = rotate_left(B,30); | |
B = A; | |
A = temp; | |
} | |
for( i=60; i<=79; i++ ) { | |
temp = (rotate_left(A,5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff; | |
E = D; | |
D = C; | |
C = rotate_left(B,30); | |
B = A; | |
A = temp; | |
} | |
H0 = (H0 + A) & 0x0ffffffff; | |
H1 = (H1 + B) & 0x0ffffffff; | |
H2 = (H2 + C) & 0x0ffffffff; | |
H3 = (H3 + D) & 0x0ffffffff; | |
H4 = (H4 + E) & 0x0ffffffff; | |
} | |
var temp = cvt_hex(H0) + cvt_hex(H1) + cvt_hex(H2) + cvt_hex(H3) + cvt_hex(H4); | |
return temp.toLowerCase(); | |
} | |
testHash(SHA1(shaInput)); | |
// 1677 bytes | |
function SHA1small(a){function b(a,b){var c=a<<b|a>>>32-b;return c}function d(a){var c,d,b="";for(c=7;c>=0;c--)d=15&a>>>4*c,b+=d.toString(16);return b}function e(a){a=a.replace(/\r\n/g,"\n");for(var b="",c=0;c<a.length;c++){var d=a.charCodeAt(c);128>d?b+=String.fromCharCode(d):d>127&&2048>d?(b+=String.fromCharCode(192|d>>6),b+=String.fromCharCode(128|63&d)):(b+=String.fromCharCode(224|d>>12),b+=String.fromCharCode(128|63&d>>6),b+=String.fromCharCode(128|63&d))}return b}var f,g,h,o,p,q,r,s,t,i=new Array(80),j=1732584193,k=4023233417,l=2562383102,m=271733878,n=3285377520;a=e(a);var u=a.length,v=new Array;for(g=0;u-3>g;g+=4)h=a.charCodeAt(g)<<24|a.charCodeAt(g+1)<<16|a.charCodeAt(g+2)<<8|a.charCodeAt(g+3),v.push(h);switch(u%4){case 0:g=2147483648;break;case 1:g=8388608|a.charCodeAt(u-1)<<24;break;case 2:g=32768|(a.charCodeAt(u-2)<<24|a.charCodeAt(u-1)<<16);break;case 3:g=128|(a.charCodeAt(u-3)<<24|a.charCodeAt(u-2)<<16|a.charCodeAt(u-1)<<8)}for(v.push(g);14!=v.length%16;)v.push(0);for(v.push(u>>>29),v.push(4294967295&u<<3),f=0;f<v.length;f+=16){for(g=0;16>g;g++)i[g]=v[f+g];for(g=16;79>=g;g++)i[g]=b(i[g-3]^i[g-8]^i[g-14]^i[g-16],1);for(o=j,p=k,q=l,r=m,s=n,g=0;19>=g;g++)t=4294967295&b(o,5)+(p&q|~p&r)+s+i[g]+1518500249,s=r,r=q,q=b(p,30),p=o,o=t;for(g=20;39>=g;g++)t=4294967295&b(o,5)+(p^q^r)+s+i[g]+1859775393,s=r,r=q,q=b(p,30),p=o,o=t;for(g=40;59>=g;g++)t=4294967295&b(o,5)+(p&q|p&r|q&r)+s+i[g]+2400959708,s=r,r=q,q=b(p,30),p=o,o=t;for(g=60;79>=g;g++)t=4294967295&b(o,5)+(p^q^r)+s+i[g]+3395469782,s=r,r=q,q=b(p,30),p=o,o=t;j=4294967295&j+o,k=4294967295&k+p,l=4294967295&l+q,m=4294967295&m+r,n=4294967295&n+s}var t=d(j)+d(k)+d(l)+d(m)+d(n);return t.toLowerCase()} | |
testHash(SHA1small(shaInput)); | |
// 1337 bytes | |
// uglified goes down to: 1264 bytes | |
// https://code.google.com/p/tiny-sha1/ | |
function SHA1_2(s){function U(a,b,c){while(0<c--)a.push(b)}function L(a,b){return(a<<b)|(a>>>(32-b))}function P(a,b,c){return a^b^c}function A(a,b){var c=(b&0xFFFF)+(a&0xFFFF),d=(b>>>16)+(a>>>16)+(c>>>16);return((d&0xFFFF)<<16)|(c&0xFFFF)}var B="0123456789abcdef";return(function(a){var c=[],d=a.length*4,e;for(var i=0;i<d;i++){e=a[i>>2]>>((3-(i%4))*8);c.push(B.charAt((e>>4)&0xF)+B.charAt(e&0xF))}return c.join('')}((function(a,b){var c,d,e,f,g,h=a.length,v=0x67452301,w=0xefcdab89,x=0x98badcfe,y=0x10325476,z=0xc3d2e1f0,M=[];U(M,0x5a827999,20);U(M,0x6ed9eba1,20);U(M,0x8f1bbcdc,20);U(M,0xca62c1d6,20);a[b>>5]|=0x80<<(24-(b%32));a[(((b+65)>>9)<<4)+15]=b;for(var i=0;i<h;i+=16){c=v;d=w;e=x;f=y;g=z;for(var j=0,O=[];j<80;j++){O[j]=j<16?a[j+i]:L(O[j-3]^O[j-8]^O[j-14]^O[j-16],1);var k=(function(a,b,c,d,e){var f=(e&0xFFFF)+(a&0xFFFF)+(b&0xFFFF)+(c&0xFFFF)+(d&0xFFFF),g=(e>>>16)+(a>>>16)+(b>>>16)+(c>>>16)+(d>>>16)+(f>>>16);return((g&0xFFFF)<<16)|(f&0xFFFF)})(j<20?(function(t,a,b){return(t&a)^(~t&b)}(d,e,f)):j<40?P(d,e,f):j<60?(function(t,a,b){return(t&a)^(t&b)^(a&b)}(d,e,f)):P(d,e,f),g,M[j],O[j],L(c,5));g=f;f=e;e=L(d,30);d=c;c=k}v=A(v,c);w=A(w,d);x=A(x,e);y=A(y,f);z=A(z,g)}return[v,w,x,y,z]}((function(t){var a=[],b=255,c=t.length*8;for(var i=0;i<c;i+=8){a[i>>5]|=(t.charCodeAt(i/8)&b)<<(24-(i%32))}return a}(s)).slice(),s.length*8))))} | |
testHash(SHA1_2(shaInput)); | |
// 1255 bytes | |
testHash(require('./sha_3').hash(shaInput, false)); | |
(function() { | |
// bytes 1321 | |
// http://phpjs.org/functions/sha1/ | |
function sha1(r){var t,a,o,e,h,n,f,c,u,S=function(r,t){var a=r<<t|r>>>32-t | |
return a},i=function(r){var t,a,o="" | |
for(t=7;t>=0;t--)a=r>>>4*t&15,o+=a.toString(16) | |
return o},v=Array(80),A=1732584193,s=4023233417,C=2562383102,d=271733878,l=3285377520,g=r.length,H=[] | |
for(a=0;g-3>a;a+=4)o=r.charCodeAt(a)<<24|r.charCodeAt(a+1)<<16|r.charCodeAt(a+2)<<8|r.charCodeAt(a+3),H.push(o) | |
switch(g%4){case 0:a=2147483648 | |
break | |
case 1:a=r.charCodeAt(g-1)<<24|8388608 | |
break | |
case 2:a=r.charCodeAt(g-2)<<24|r.charCodeAt(g-1)<<16|32768 | |
break | |
case 3:a=r.charCodeAt(g-3)<<24|r.charCodeAt(g-2)<<16|r.charCodeAt(g-1)<<8|128}for(H.push(a);H.length%16!=14;)H.push(0) | |
for(H.push(g>>>29),H.push(g<<3&4294967295),t=0;t<H.length;t+=16){for(a=0;16>a;a++)v[a]=H[t+a] | |
for(a=16;79>=a;a++)v[a]=S(v[a-3]^v[a-8]^v[a-14]^v[a-16],1) | |
for(e=A,h=s,n=C,f=d,c=l,a=0;19>=a;a++)u=S(e,5)+(h&n|~h&f)+c+v[a]+1518500249&4294967295,c=f,f=n,n=S(h,30),h=e,e=u | |
for(a=20;39>=a;a++)u=S(e,5)+(h^n^f)+c+v[a]+1859775393&4294967295,c=f,f=n,n=S(h,30),h=e,e=u | |
for(a=40;59>=a;a++)u=S(e,5)+(h&n|h&f|n&f)+c+v[a]+2400959708&4294967295,c=f,f=n,n=S(h,30),h=e,e=u | |
for(a=60;79>=a;a++)u=S(e,5)+(h^n^f)+c+v[a]+3395469782&4294967295,c=f,f=n,n=S(h,30),h=e,e=u | |
A=A+e&4294967295,s=s+h&4294967295,C=C+n&4294967295,d=d+f&4294967295,l=l+c&4294967295}return u=i(A)+i(s)+i(C)+i(d)+i(l),u.toLowerCase()} | |
testHash(sha1(shaInput)); | |
})(); | |
// another option, seems too big | |
// 4746 bytes | |
// https://github.com/Caligatio/jsSHA | |
console.log('mine'); | |
testHash(require('./sha_3_mine').hash(shaInput)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment