dojo.require("dojo.crypto");
dojo.provide("dojo.crypto.SHA1");
dojo.require("dojo.experimental");

/*
 *	A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
 *	in FIPS PUB 180-1
 *
 * 	Version 2.1a Copyright Paul Johnston 2000 - 2002.
 * 	Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * 	Distributed under the BSD License
 * 	See http://pajhome.org.uk/crypt/md5 for details.
 *
 *	Dojo port by Tom Trenka
 */
dojo.experimental("dojo.crypto.SHA1");

dojo.crypto.SHA1 = new function(){
	var chrsz=8;
	var mask=(1<<chrsz)-1;
	function toWord(s) {
	  var wa=[];
	  for(var i=0; i<s.length*chrsz; i+=chrsz)
		wa[i>>5]|=(s.charCodeAt(i/chrsz)&mask)<<(i%32);
	  return wa;
	}
	function toString(wa){
		var s=[];
		for(var i=0; i<wa.length*32; i+=chrsz)
			s.push(String.fromCharCode((wa[i>>5]>>>(i%32))&mask));
		return s.join("");
	}
	function toHex(wa) {
		var h="0123456789abcdef";
		var s=[];
		for(var i=0; i<wa.length*4; i++){
			s.push(h.charAt((wa[i>>2]>>((i%4)*8+4))&0xF)+h.charAt((wa[i>>2]>>((i%4)*8))&0xF));
		}
		return s.join("");
	}
	function toBase64(wa){
		var p="=";
		var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
		var s=[];
		for(var i=0; i<wa.length*4; i+=3){
			var t=(((wa[i>>2]>>8*(i%4))&0xFF)<<16)|(((wa[i+1>>2]>>8*((i+1)%4))&0xFF)<<8)|((wa[i+2>>2]>>8*((i+2)%4))&0xFF);
			for(var j=0; j<4; j++){
				if(i*8+j*6>wa.length*32) s.push(p);
				else s.push(tab.charAt((t>>6*(3-j))&0x3F));
			}
		}
		return s.join("");
	}

	//	math
	function add(x,y){
		var l=(x&0xffff)+(y&0xffff);
		var m=(x>>16)+(y>>16)+(l>>16);
		return (m<<16)|(l&0xffff);
	}
	function r(x,n){  return (x<<n)|(x>>>(32-n)); }

	//	SHA rounds
	function f(u,v,w){ return ((u&v)|(~u&w)); }
	function g(u,v,w){ return ((u&v)|(u&w)|(v&w)); }
	function h(u,v,w){ return (u^v^w); }

	function fn(i,u,v,w){
		if(i<20) return f(u,v,w);
		if(i<40) return h(u,v,w);
		if(i<60) return g(u,v,w);
		return h(u,v,w);
	}
	function cnst(i){
		if(i<20) return 1518500249;
		if(i<40) return 1859775393;
		if(i<60) return -1894007588;
		return -899497514;
	}

	function core(x,len){
		x[len>>5]|=0x80<<(24-len%32);
		x[((len+64>>9)<<4)+15]=len;

		var w=[];
		var a= 1732584193;		//	0x67452301
		var b=-271733879;		//	0xefcdab89
		var c=-1732584194;		//	0x98badcfe
		var d= 271733878;		//	0x10325476
		var e=-1009589776;		//	0xc3d2e1f0

		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]=r(w[j-3]^w[j-8]^w[j-14]^w[j-16],1);
				var t=add(add(r(a,5),fn(j,b,c,d)),add(add(e,w[j]),cnst(j)));
				e=d; d=c; c=r(b,30); b=a; a=t;
			}

			a=add(a,olda);
			b=add(b,oldb);
			c=add(c,oldc);
			d=add(d,oldd);
			e=add(e,olde);
		}
		return [a,b,c,d,e];
	}
	function hmac(data,key){
		var wa=toWord(key);
		if(wa.length>16) wa=core(wa,key.length*chrsz);
		var l=[], r=[];
		for(var i=0; i<16; i++){
			l[i]=wa[i]^0x36363636;
			r[i]=wa[i]^0x5c5c5c5c;
		}
		var h=core(l.concat(toWord(data)),512+data.length*chrsz);
		return core(r.concat(h),640);
	}

	this.compute=function(data,outputType){
		var out=outputType||dojo.crypto.outputTypes.Base64;
		switch(out){
			case dojo.crypto.outputTypes.Hex:{
				return toHex(core(toWord(data),data.length*chrsz));
			}
			case dojo.crypto.outputTypes.String:{
				return toString(core(toWord(data),data.length*chrsz));
			}
			default:{
				return toBase64(core(toWord(data),data.length*chrsz));
			}
		}
	};
	this.getHMAC=function(data,key,outputType){
		var out=outputType||dojo.crypto.outputTypes.Base64;
		switch(out){
			case dojo.crypto.outputTypes.Hex:{
				return toHex(hmac(data,key));
			}
			case dojo.crypto.outputTypes.String:{
				return toString(hmac(data,key));
			}
			default:{
				return toBase64(hmac(data,key));
			}
		}
	};
}();
