function f(t, x, y, z)
{
   if ((0<=t) && (t<=19))
   {
      return ch(x, y, z);
   }
   else if ((20<=t) && (t<=39))
   {
      return parity(x, y, z);
   }
   else if ((40<=t) && (t<=59))
   {
      return maj(x, y, z);
   }
   else if ((60<=t) && (t<=79))
   {
      return parity(x, y, z);
   }
}

function ch(x, y, z)
{
   return xor(and(x,y),and(not(x),z)); 
}

function parity(x, y, z)
{
   return xor(xor(x,y),z);
}

function maj(x, y, z)
{
   return xor(xor(and(x,y),and(x,z)),and(y,z));
}

function k(t)
{
   if ((0<=t) && (t<=19))
   {
      return 0x5a827999;
   }
   else if ((20<=t) && (t<=39))
   {
      return 0x6ed9eba1;
   }
   else if ((40<=t) && (t<=59))
   {
      return 0x8f1bbcdc;
   }
   else if ((60<=t) && (t<=79))
   {
      return 0xca62c1d6;
   }
}

function stringCode(n,s)
{
	var i;
	for (i=0; i<s.length; i++)
	{
		var bin = s.charCodeAt(i).toString(2);
		var j;
		var npos = i*8 + 7;
		for (j=bin.length-1; j>=0; j--)
		{
			n[npos]=parseInt(bin.charAt(j));
			npos--;
		}
	}
}

function nToString(n,b)
{
	var i;
	var s="";
	for (i=0; i<n.length; i++)
	{
		s = s + n[i].toString(b);
	}
	return s;
}

function addLength(n, len)
{
	var binlen = len.toString(2);
	var i;
	var npos = n.length-1;
	for (i=binlen.length-1; i>=0; i--)
	{
		n[npos]=parseInt(binlen.charAt(i));
		npos--;
	}
}

function pad(n,s)
{
	stringCode(n,s);
	var len = s.length * 8;
	n[len]=1;
	addLength(n,len);
	return n;
}

function sha1parse(n, bits)
{
    var a = new Array();
    var blockSize = Math.pow(2,bits);
    var blockValue;
    while (n!=0)
    {
       blockValue = n%blockSize;
       a.unshift(blockValue);
       n -= blockValue;
       n /= blockSize;
    }
    return a;
}

function rotl(x, n)      //32-Bit-Worte
{
   return or(shl(x, n), shr(x, 32-n));
}

function parseIt(n, nps)
{
	var a = nps;
	var b = new Array();//512-Bit-lang, enthält 32-Bit-Worte
	
	var i;
	var bit=0;
	var x=0;
	for(i=0; i<n.length; i++)
	{
		x *= 2;
		x += n[i];
		bit++;
		if (bit==32)
		{
			b.push(x);
			x=0;
			bit=0;
		}
		if(b.length==16)
		{
			a.push(b);
			b = new Array();
		}
	}
}

function sha1(s)
{
	var len=0;
	len = s.length*8;
	len -= 448;
	var mblocks = Math.ceil(1 + (len+1)/512);
	var n = new Array(512*mblocks);
	var i;
	for (i=0; i<512*mblocks; i++)
	{
		n[i]=0;
	}
	pad(n,s);
   var nps = new Array();
   parseIt(n, nps);
   var h0 = 0x67452301;
   var h1 = 0xefcdab89;
   var h2 = 0x98badcfe;
   var h3 = 0x10325476;
   var h4 = 0xc3d2e1f0;
   
   var a,b,c,d,e;
   
   var i;
   
   var exp2_32 = Math.pow(2,32);
   
   for (i=0; i<nps.length; i++)
   {
      var m = nps[i];
      var j;
      var t;
      for (t=16; t<=79; t++)
      {
      	m[t]=(rotl(xor(xor(xor(m[t-14], m[t-16]), m[t-8]), m[t-3]), 1));
      }
      a = h0;
      b = h1;
      c = h2;
      d = h3;
      e = h4;
      
      var temp;
      
      for (t=0; t<=79; t++)
      {
      	temp = (rotl(a,5) + f(t,b,c,d) + e + k(t) + m[t]) % exp2_32;
      	e = d;
      	d = c;
      	c = rotl(b,30);
      	b = a;
      	a = temp;
      }
      
      h0 = (a + h0) % exp2_32;
      h1 = (b + h1) % exp2_32;
      h2 = (c + h2) % exp2_32;
      h3 = (d + h3) % exp2_32;
      h4 = (e + h4) % exp2_32;
   }
   h0 = h0.toString(16);
   h1 = h1.toString(16);
   h2 = h2.toString(16);
   h3 = h3.toString(16);
   h4 = h4.toString(16);
   
   h0 = zeroUp(h0, 8);
   h1 = zeroUp(h1, 8);
   h2 = zeroUp(h2, 8);
   h3 = zeroUp(h3, 8);
   h4 = zeroUp(h4, 8);
   
   return h0 + h1 + h2 + h3 + h4;
}

function zeroUp(s, n)
{
   while(s.length<n)
   {
	   s = "0" + s;
   }
   return s;
}

/*
 * extract of md5.js 1.0b 27/06/96
 *
 * Javascript implementation of the RSA Data Security, Inc. MD5
 * Message-Digest Algorithm.
 *
 * Copyright (c) 1996 Henri Torgemane. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for any purposes and without
 * fee is hereby granted provided that this copyright notice
 * appears in all copies.
 *
 * Of course, this soft is provided "as is" without express or implied
 * warranty of any kind.
 *
 *
 * Modified with german comments and some information about collisions.
 * (Ralf Mieke, ralf@miekenet.de, http://mieke.home.pages.de)
 */



function array(n) {
  for(i=0;i<n;i++) this[i]=0;
  this.length=n;
}



/* Einige grundlegenden Funktionen m&uuml;ssen wegen
 * Javascript Fehlern umgeschrieben werden.
 * Man versuche z.B. 0xffffffff >> 4 zu berechnen..
 * Die nun verwendeten Funktionen sind zwar langsamer als die Originale,
 * aber sie funktionieren.
 */

function integer(n) { return n%(0xffffffff+1); }

function shr(a,b) {
  a=integer(a);
  b=integer(b);
  if (a-0x80000000>=0) {
    a=a%0x80000000;
    a>>=b;
    a+=0x40000000>>(b-1);
  } else
    a>>=b;
  return a;
}

function shl1(a) {
  a=a%0x80000000;
  if (a&0x40000000==0x40000000)
  {
    a-=0x40000000;
    a*=2;
    a+=0x80000000;
  } else
    a*=2;
  return a;
}

function shl(a,b) {
  a=integer(a);
  b=integer(b);
  for (var i=0;i<b;i++) a=shl1(a);
  return a;
}

function and(a,b) {
  a=integer(a);
  b=integer(b);
  var t1=(a-0x80000000);
  var t2=(b-0x80000000);
  if (t1>=0)
    if (t2>=0)
      return ((t1&t2)+0x80000000);
    else
      return (t1&b);
  else
    if (t2>=0)
      return (a&t2);
    else
      return (a&b);
}

function or(a,b) {
  a=integer(a);
  b=integer(b);
  var t1=(a-0x80000000);
  var t2=(b-0x80000000);
  if (t1>=0)
    if (t2>=0)
      return ((t1|t2)+0x80000000);
    else
      return ((t1|b)+0x80000000);
  else
    if (t2>=0)
      return ((a|t2)+0x80000000);
    else
      return (a|b);
}

function xor(a,b) {
  a=integer(a);
  b=integer(b);
  var t1=(a-0x80000000);
  var t2=(b-0x80000000);
  if (t1>=0)
    if (t2>=0)
      return (t1^t2);
    else
      return ((t1^b)+0x80000000);
  else
    if (t2>=0)
      return ((a^t2)+0x80000000);
    else
      return (a^b);
}

function not(a) {
  a=integer(a);
  return (0xffffffff-a);
}

