/*** "RSA Data Security, Inc. MD5 Message-Digest Algorithm" ***/

 function md5_decode(s) {
  result=new Array();
  for (var i=0; i<=((s.length>>>6)<<4)+15; i++) result[i]=0;
  for (var i=0; i<s.length; i++) {
   result[i>>>2]|=(s.Win1250CodeAt(i)) << ((8*i)%32);
  }
  return(result);
 }

 function md5_encode(b) {
  result="";
  var t="0123456789abcdef";
  for (var i=0; i<b.length; i++)
   for (var j=0; j<4; j++) {
    result+=t.charAt( (b[i] >> (8*j+4) ) & 0xF);
    result+=t.charAt( (b[i] >> (8*j) ) & 0xF);
   }
  return(result);
 }

 function md5_padding(b,l) {
  b[l>>>2]|=128 << ((l*8)%32);
  b[((l>>>6)<<4)+14]=l*8;
  return(b);
 }

 function md5_add(x,y) {
  return (((x&0xffffffff) + (y&0xffffffff)) & 0xffffffff);
 }

 function md5_XX(a,b,func,Xk,Ti,s) {
  a=md5_add(md5_add(a+func), md5_add(Xk+Ti));
  return(md5_add(b, ((a << s) | (a >>> (32-s))) ));
 }

 function md5_FF(a,b,c,d,Xk,s,Ti) {
  var func=(b & c) | ((~b) & d);
  return(md5_XX(a,b,func,Xk,Ti,s));
 }
 function md5_GG(a,b,c,d,Xk,s,Ti) {
  var func=(b & d) | (c & (~d));
  return(md5_XX(a,b,func,Xk,Ti,s));
 }
 function md5_HH(a,b,c,d,Xk,s,Ti) {
  var func=b^c^d;
  return(md5_XX(a,b,func,Xk,Ti,s));
 }
 function md5_II(a,b,c,d,Xk,s,Ti) {
  var func=c ^ (b | (~d));
  return(md5_XX(a,b,func,Xk,Ti,s));
 }

 function md5_hash(m) {
  var a = 0x67452301;
  var b = 0xefcdab89;
  var c = 0x98badcfe;
  var d = 0x10325476;

  var aa,bb,cc,dd;

  x=new Array(16);

  for (var i=0; i<m.length/16; i++) {

   for (var j=0; j<=15; j++) x[j]=m[i*16+j];

   aa=a; bb=b; cc=c; dd=d;

   a=md5_FF(a, b, c, d, x[ 0],  7, 0xd76aa478);
   d=md5_FF(d, a, b, c, x[ 1], 12, 0xe8c7b756);
   c=md5_FF(c, d, a, b, x[ 2], 17, 0x242070db);
   b=md5_FF(b, c, d, a, x[ 3], 22, 0xc1bdceee);
   a=md5_FF(a, b, c, d, x[ 4],  7, 0xf57c0faf);
   d=md5_FF(d, a, b, c, x[ 5], 12, 0x4787c62a);
   c=md5_FF(c, d, a, b, x[ 6], 17, 0xa8304613);
   b=md5_FF(b, c, d, a, x[ 7], 22, 0xfd469501);
   a=md5_FF(a, b, c, d, x[ 8],  7, 0x698098d8);
   d=md5_FF(d, a, b, c, x[ 9], 12, 0x8b44f7af);
   c=md5_FF(c, d, a, b, x[10], 17, 0xffff5bb1);
   b=md5_FF(b, c, d, a, x[11], 22, 0x895cd7be);
   a=md5_FF(a, b, c, d, x[12],  7, 0x6b901122);
   d=md5_FF(d, a, b, c, x[13], 12, 0xfd987193);
   c=md5_FF(c, d, a, b, x[14], 17, 0xa679438e);
   b=md5_FF(b, c, d, a, x[15], 22, 0x49b40821);

   a=md5_GG(a, b, c, d, x[ 1],  5, 0xf61e2562);
   d=md5_GG(d, a, b, c, x[ 6],  9, 0xc040b340);
   c=md5_GG(c, d, a, b, x[11], 14, 0x265e5a51);
   b=md5_GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa);
   a=md5_GG(a, b, c, d, x[ 5],  5, 0xd62f105d);
   d=md5_GG(d, a, b, c, x[10],  9,  0x2441453);
   c=md5_GG(c, d, a, b, x[15], 14, 0xd8a1e681);
   b=md5_GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8);
   a=md5_GG(a, b, c, d, x[ 9],  5, 0x21e1cde6);
   d=md5_GG(d, a, b, c, x[14],  9, 0xc33707d6);
   c=md5_GG(c, d, a, b, x[ 3], 14, 0xf4d50d87);
   b=md5_GG(b, c, d, a, x[ 8], 20, 0x455a14ed);
   a=md5_GG(a, b, c, d, x[13],  5, 0xa9e3e905);
   d=md5_GG(d, a, b, c, x[ 2],  9, 0xfcefa3f8);
   c=md5_GG(c, d, a, b, x[ 7], 14, 0x676f02d9);
   b=md5_GG(b, c, d, a, x[12], 20, 0x8d2a4c8a);

   a=md5_HH(a, b, c, d, x[ 5],  4, 0xfffa3942);
   d=md5_HH(d, a, b, c, x[ 8], 11, 0x8771f681);
   c=md5_HH(c, d, a, b, x[11], 16, 0x6d9d6122);
   b=md5_HH(b, c, d, a, x[14], 23, 0xfde5380c);
   a=md5_HH(a, b, c, d, x[ 1],  4, 0xa4beea44);
   d=md5_HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9);
   c=md5_HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60);
   b=md5_HH(b, c, d, a, x[10], 23, 0xbebfbc70);
   a=md5_HH(a, b, c, d, x[13],  4, 0x289b7ec6);
   d=md5_HH(d, a, b, c, x[ 0], 11, 0xeaa127fa);
   c=md5_HH(c, d, a, b, x[ 3], 16, 0xd4ef3085);
   b=md5_HH(b, c, d, a, x[ 6], 23,  0x4881d05);
   a=md5_HH(a, b, c, d, x[ 9],  4, 0xd9d4d039);
   d=md5_HH(d, a, b, c, x[12], 11, 0xe6db99e5);
   c=md5_HH(c, d, a, b, x[15], 16, 0x1fa27cf8);
   b=md5_HH(b, c, d, a, x[ 2], 23, 0xc4ac5665);

   a=md5_II(a, b, c, d, x[ 0],  6, 0xf4292244);
   d=md5_II(d, a, b, c, x[ 7], 10, 0x432aff97);
   c=md5_II(c, d, a, b, x[14], 15, 0xab9423a7);
   b=md5_II(b, c, d, a, x[ 5], 21, 0xfc93a039);
   a=md5_II(a, b, c, d, x[12],  6, 0x655b59c3);
   d=md5_II(d, a, b, c, x[ 3], 10, 0x8f0ccc92);
   c=md5_II(c, d, a, b, x[10], 15, 0xffeff47d);
   b=md5_II(b, c, d, a, x[ 1], 21, 0x85845dd1);
   a=md5_II(a, b, c, d, x[ 8],  6, 0x6fa87e4f);
   d=md5_II(d, a, b, c, x[15], 10, 0xfe2ce6e0);
   c=md5_II(c, d, a, b, x[ 6], 15, 0xa3014314);
   b=md5_II(b, c, d, a, x[13], 21, 0x4e0811a1);
   a=md5_II(a, b, c, d, x[ 4],  6, 0xf7537e82);
   d=md5_II(d, a, b, c, x[11], 10, 0xbd3af235);
   c=md5_II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb);
   b=md5_II(b, c, d, a, x[ 9], 21, 0xeb86d391);

   a=md5_add(a,aa);
   b=md5_add(b,bb);
   c=md5_add(c,cc);
   d=md5_add(d,dd);
  }
  return Array(a,b,c,d);
 }

 function md5(s) {
  return(md5_encode( md5_hash( md5_padding(md5_decode(s),s.length) ) ) );
 }


/*** US Secure Hash Algorithm 1 (SHA1) ***/

 function sha1_Sn(X,n) {
  return((X<<n)|(X>>>(32-n)));
 }
 function sha1_add() {
  var result=arguments[0];
  for (var i=1; i<arguments.length; i++)
   result=((result & 0xffffffff) + (arguments[i] & 0xffffffff)) & 0xffffffff;
  return(result);
 }
 function sha1(s) {
  /*padding*/
  s+=String.fromCharCode(128);
  var l=((s.length+8)>>>6)*64+64;

  var M=new Array(l/4);
  for (var i=0; i<M.length; i++) M[i]=0;
  for (i=0; i<s.length; i++) M[i>>>2]|=s.charCodeAt(i)<<((3-i%4)*8);
  M[M.length-1]=(s.length-1)*8;

  /*hashing*/
  var H0,H1,H2,H3,H4;
  H0=0x67452301;
  H1=0xEFCDAB89;
  H2=0x98BADCFE;
  H3=0x10325476;
  H4=0xC3D2E1F0;

  var W=new Array(80);
  var A,B,C,D,E,TEMP;
  for (var j=0; j<(M.length>>>4); j++) {
   for (i=0; i<16; i++) W[i]=M[i+j*16];
   for (i=16; i<W.length; i++) W[i]=sha1_Sn(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<20; i++) {
    TEMP = sha1_add( sha1_Sn(A,5) , (B & C) | ((~B) & D) , E , W[i], 0x5A827999);
    E = D;
    D = C;
    C = sha1_Sn(B,30);
    B = A;
    A = TEMP;
   }

   for (i=20; i<40; i++) {
    TEMP = sha1_add( sha1_Sn(A,5) , B ^ C ^ D , E , W[i], 0x6ED9EBA1);
    E = D;
    D = C;
    C = sha1_Sn(B,30);
    B = A;
    A = TEMP;
   }

   for (i=40; i<60; i++) {
    TEMP = sha1_add( sha1_Sn(A,5) , (B & C) | (B & D) | (C & D) , E , W[i], 0x8F1BBCDC);
    E = D;
    D = C;
    C = sha1_Sn(B,30);
    B = A;
    A = TEMP;
   }

   for (i=60; i<80; i++) {
    TEMP = sha1_add( sha1_Sn(A,5) , B ^ C ^ D , E , W[i], 0xCA62C1D6);
    E = D;
    D = C;
    C = sha1_Sn(B,30);
    B = A;
    A = TEMP;
   }

   H0=sha1_add(H0,A);
   H1=sha1_add(H1,B);
   H2=sha1_add(H2,C);
   H3=sha1_add(H3,D);
   H4=sha1_add(H4,E);
  }

  /* bin to hex*/
  var result="";
  var hex="0123456789abcdef";
  var H=new Array(H0,H1,H2,H3,H4);
  for (var i=0; i<H.length; i++)
   for (var j=0; j<8; j++)
    result+=hex.charAt( (H[i] >>> (28-4*j)) & 0xF);
  return(result);
 }

/*** HMAC ***/
 function hmac(text,K) {
  function str_xor(s1,s2) {
   var result="";
   var m=Math.min(s1.length,s2.length);
   for (var i=0; i<m; i++) result+=String.fromCharCode( s1.charCodeAt(i)^s2.charCodeAt(i) );
   result+=s1.substr(m)+s2.substr(m);
   return(result);
  }
  var ipad=""; for (var i=0; i<64; i++) ipad+=String.fromCharCode(0x36);
  var opad=""; for (var i=0; i<64; i++) opad+=String.fromCharCode(0x5C);
  return (sha1(str_xor(K,opad)+sha1(str_xor(K,ipad)+text)));
 }

 function hash(challenge,login,realm,password) {
  return(hmac(challenge,md5(login+":"+realm+":"+password)));
 }