/*
 * FIPS PUB 180-1: Secure Hash Standard, SHA-1 - see Schneier pp442-5
 *
 * Copyright (c) 2002 d@vidwest.net - USE THIS FREE SOURCE AT YOUR OWN RISK.
 */

function SHA1 (s) { return s2h(SHA1s(s)); } // [API] standard 40 char hexstring

function SHA1s(s) { return bi2s(SHA1Transforms(s2bi(SHA1pad(s)))); } // 8bit str

function SHA1test(warn) { // best called at startup
 if (SHA1('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq') ==
     '84983e441c3bd26ebaae4aa1f95129e5e54670f1') return true; // more or less
 if (warn)
  alert('SHA1 ERROR:\nScripts on this page might not run properly in this\n' +
        'web browser. Maybe you should try a newer version?.');
 return false;
}

function SHA1Transforms(m) {
 var h = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
 for (var i = 0, n = m.length, x=0xffffffff, w = []; i < n; i += 16) {
  var a = h[0], b = h[1], c = h[2], d = h[3], e = h[4];
  for (var t = 0; t < 80; t++) {
   w[t] = t < 16 ? m[i+t] : rotl(w[t-3]^w[t-8]^w[t-14]^w[t-16], 1);
   var temp = rotl(a, 5) + e + w[t] +
   (t<20 ? ((b&c)|(~b&d))      + 0x5a827999 : t<40 ? (b^c^d) + 0x6ed9eba1 :
    t<60 ? ((b&c)|(b&d)|(c&d)) + 0x8f1bbcdc :        (b^c^d) + 0xca62c1d6);
   e = d; d = c; c = rotl(b, 30); b = a; a = temp;
  }
  h[0] = (h[0] + a) & x; h[1] = (h[1] + b) & x; h[2] = (h[2] + c) & x;
  h[3] = (h[3] + d) & x; h[4] = (h[4] + e) & x;
 }
 return h; // ('& 0xffffffff' above to prevent int overflow)
}

function SHA1pad(s) { // pad and append string length in bits, max 2**32-1
 var n = s.length;
 return s + bi2s([0x80000000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]).substring(0,
  64-((n+8)&63)) + bi2s([0,n<<3]);
} // note md5 is the same, but with little-endian ints...

/*
 * SHA-1 encryption functions - slow! - CFB mode - see Schneier pp351,209
 */

// version 0.2

function SHA1encrypt(key, msg) { // [API]
 var iv = s = sxor(SHA1s(key), SHA1s(msg));
 for (var i = 0, n = msg.length; i < n; i +=20) {
  iv = sxor(SHA1s(key + '' + iv), msg.substring(i, i + 20)); s += '' + iv;
 }
 return stob64(s);
}

function SHA1decrypt(key, msg) { // [API]
 var m = b64tos(msg), iv = mac = m.substring(0,20), s = '', m = m.substring(20);
 for (var i = 0, n = m.length; i < n; i +=20) {
  var b = m.substring(i, i + 20); s += sxor(SHA1s(key + '' + iv), b); iv = b;
 }
 if (SHA1s(s) != sxor(SHA1s(key), mac))
  alert('Warning: decrypted/original message mis-match.');
 return s;
}

// Pick-and-Mix Conversions and Common Functions...

function stob64(s) { // [binary mode: no lf->crlf's - see rfc2045]
 var B = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 for (var i = c = 0, n = s.length, b = ''; ; ) {
  var x = s.charCodeAt(i++), y = s.charCodeAt(i++), z = s.charCodeAt(i++);
  if (i > n) break;
  b += B.charAt(63&(x>>2)) + B.charAt(63&((x<<4)+(y>>4)))+
       B.charAt(63&((y<<2)+(z>>6))) + B.charAt(63&z);
  if (++c > 18) { b += '\n'; c = 0; }
 }
 if      (i - n == 1)
  b += B.charAt(63&(x>>2))+B.charAt(63&((x<<4)+(y>>4)))+B.charAt(63&(y<<2))+'=';
 else if (i - n == 2)
  b += B.charAt(63&(x>>2))+B.charAt(63&(x<<4))+'==';
 return b;
} // used by all en/decrypt functions

function b64tos(b) {
 var B = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 for (var i = 0, n = b.length, s = '', a = []; i < n; ) {
  for (var j = 0; j < 4 && i < n; i++) {
   var c = B.indexOf(b.charAt(i));
   if (c != -1) a[j++] = c;
  }
  if (j < 4) break;
  s += String.fromCharCode(
   255&((a[0]<<2)+(a[1]>>4)), 255&((a[1]<<4)+(a[2]>>2)), 255&(a[2]<<6)+(a[3]));
 }
 if (j % 4 > 1) s += String.fromCharCode(255&((a[0]<<2)+(a[1]>>4)));
 if (j % 4 > 2) s += String.fromCharCode(255&((a[1]<<4)+(a[2]>>2)));
 return s;
} // used by all en/decrypt functions

function sxor(a,b,v) { // xor strings a^b, repeating the shorter if v(igenere)
 var l = a.length, m = b.length, n = (l>m&&v)||(l<m&&!v) ? l : m;
 for (var i = 0, s = ''; i < n; i++)
  s += String.fromCharCode(a.charCodeAt(i%l) ^ b.charCodeAt(i%m));
 return s; // 8bit
} // used by all en/decrypt functions, except RC4()

function rotl(x,n) { return (x<<n)|(x>>>(32-n)); } // used by MD5/SHA-1

function s2h(s) { // 8bit string to hexstring
 for (var i = 0, n = s.length, x = '0123456789abcdef', h = ''; i < n; i++) {
  var c = s.charCodeAt(i); h += x.charAt((c & 255) >> 4) + x.charAt(c & 15);
 }
 return h;
} // used by MD5/SHA-1

function h2s(h) { // hexstring to 8bit string
 for (var i = 0, n = h.length, x = '0123456789abcdef', s = ''; i < n; i+=2) {
  s+=String.fromCharCode((x.indexOf(h.charAt(i))<<4)+x.indexOf(h.charAt(i+1)));
 }
 return s;
} // unused

function li2s(a) { // little-endian 32bit int array to 8bit string
 for(var i = 0, n = a.length, m = 255, s = ''; i < n; i++)
  s+=String.fromCharCode(a[i]&m, (a[i]>>>8)&m, (a[i]>>>16)&m, (a[i]>>>24)&m);
//s+=String.fromCharCode((a[i]>>>24)&m, (a[i]>>>16)&m, (a[i]>>>8)&m, a[i]&m);
 return s;
} // used by MD5

function s2li(s) { // 8bit string to little-endian 32bit int array
 for (var i = 0, n = s.length, a = []; i < n; i++)
  a[i >>> 2] |= (s.charCodeAt(i) & 255) << ((i & 3) << 3);
//a[i >>> 2] |= (s.charCodeAt(i) & 255) << ((3 - (i & 3)) << 3);
 return a;
} // used by MD5

function bi2s(a) { // array of big-endian 32bit ints to 8bit string
 for(var i = 0, n = a.length, m = 255, s = ''; i < n; i++)
  s+=String.fromCharCode((a[i]>>>24)&m, (a[i]>>>16)&m, (a[i]>>>8)&m, a[i]&m);
 return s;
} // used by SHA-1

function s2bi(s) { // 8bit string to big-endian 32bit int array
 for (var i = 0, n = s.length, a = []; i < n; i++)
  a[i >>> 2] |= (s.charCodeAt(i) & 255) << ((3 - (i & 3)) << 3);
 return a;
} // used by SHA-1

//-->



