// RSA, a suite of routines for performing RSA public-key computations in
// JavaScript.
//
// Requires BigInt.js and Barrett.js.
//
// Copyright 1998-2005 David Shapiro.
//
// You may use, re-use, abuse, copy, and modify this code to your liking, but
// please keep this header.
//
// Thanks!
// 
// Dave Shapiro
// dave@ohdave.com 
var charMap = Array();
charMap[8364] = 128;
charMap[65533] = 129;
charMap[8218] = 130;
charMap[402] = 131;
charMap[8222] = 132;
charMap[8230] = 133;
charMap[8224] = 134;
charMap[8225] = 135;
charMap[710] = 136;
charMap[8240] = 137;
charMap[352] = 138;
charMap[8249] = 139;
charMap[338] = 140;
charMap[65533] = 141;
charMap[381] = 142;
charMap[65533] = 143;
charMap[65533] = 144;
charMap[8216] = 145;
charMap[8217] = 146;
charMap[8220] = 147;
charMap[8221] = 148;
charMap[8226] = 149;
charMap[8211] = 150;
charMap[8212] = 151;
charMap[732] = 152;
charMap[8482] = 153;
charMap[353] = 154;
charMap[8250] = 155;
charMap[339] = 156;
charMap[65533] = 157;
charMap[382] = 158;
charMap[376] = 159;

String.prototype.chunk = function(n) {
if (typeof n=='undefined') n=2;
return this.match(RegExp('.{1,'+n+'}','g'));
};

function txt2num(sourceString) {

	workingLength = sourceString.length;
	intResult = biFromString("0",10);
	while (true) {

		workingLength = workingLength - 1;
		x2 = biFromString("256",10);
		currentNumber = biMultiply(x2, intResult);
		
		intResult = biAdd(currentNumber, biFromString(sourceString[workingLength].charCodeAt(0) + '', 10));
		if (workingLength == 0) {
			break;
		}
		
	}	
	return biToString(intResult, 10);
}		
	
function longBaseConvert(numString, fromBase, toBase) {

	stringChars = numString.chunk(1);
	
	chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+=!@#$%^*(){[}]|:,.?/`~•¤¶§ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥ƒáíóúñÑªº¿¬½¼¡«»¯ßµ±÷;<>";
	fromString = chars.substring(0, fromBase);
	targetString = chars.substring(0, toBase);
	targetStringChars = targetString.chunk(1);
	workingLength = numString.length;
	workingNumbers = new Array();
	for (i = 0; i<workingLength; i++) {
		workingNumbers[i] = fromString.indexOf(stringChars[i]);
	}
	
	newLen = 0;
	divide = 0;
	result = "";
 	while (true)
  {

    newLen = 0;
    divide = 0;
    for (i = 0; i < workingLength; i++)
    {
        divide = divide * fromBase + parseInt(workingNumbers[i]);

        
        if (divide >= toBase)
        {
            workingNumbers[newLen++] = divide / toBase;

            divide = divide % toBase;

        }
        else if (newLen > 0) 
        {
            workingNumbers[newLen++] = 0;
            //newLen++;
        }
    }
    workingLength = newLen;
    
    result = targetStringChars[divide] + result;

    if (newLen == 0)
    {
        break;
    }
    
	}

	return result;
}
var keyStr = "ABCDEFGHIJKLMNOP" +
                "QRSTUVWXYZabcdef" +
                "ghijklmnopqrstuv" +
                "wxyz0123456789+/" +
                "=";
function encode64(text) {


    var digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
        i = 0,
        cur, prev, byteNum,
        result=[];      

    while(i < text.length){

        cur = text.charCodeAt(i);
        if (cur > 256) {
        	cur = charMap[cur];
        }
        //alert(i + "," + cur);

        byteNum = i % 3;

        switch(byteNum){
            case 0: //first byte
                result.push(digits.charAt(cur >> 2));
                break;

            case 1: //second byte
                result.push(digits.charAt((prev & 3) << 4 | (cur >> 4)));
                break;

            case 2: //third byte
                result.push(digits.charAt((prev & 0x0f) << 2 | (cur >> 6)));
                result.push(digits.charAt(cur & 0x3f));
                break;
        }

        prev = cur;
        i++;
    }

    //more code here

    return result.join("");

   }
   
function runx() {
	virginEncrypt = "abw0=9uwk;lj aslkjdAS)(";
	chunkArray = virginEncrypt.chunk(12);
	convertedLong = "";
	for (var chunkIndex in chunkArray) {
				if (chunkArray.hasOwnProperty(chunkIndex)) {
		chunk = chunkArray[chunkIndex];
		if (chunk) {
			
			working = txt2num(chunk);
			workingInt = biFromString(working, 10);
			expInt = biFromString("74051",10);
			mod = biFromString("34223006313802362857834907976974026712808558900922983467528973296961378716888622280051418794301754187795380362049897", 10);

			result = biPowMod(workingInt, expInt, mod);

			convertedLong = convertedLong + longBaseConvert(biToString(result, 10) + "", 10, 145) + " ";
			
}
		}
	}
	
	//alert(convertedLong);
	
	changeInput = Base64.encode(convertedLong);
	


	
	//longBaseConvert("29973776345311410133302122122356795694616272744762153538118682439673375863634450958007914791006552503411922746740110", 10, 145);
	/**
	input = "XTAC18660319582020202020202020594e36303754323553373334";
	var breaker = input.chunk(48);
	intResult = new BigInt();
	intResult = biFromDecimal("0",10);
	setMaxDigits(128);
	alert('x');
	i = 0;
		alert(breaker[i]);
		sourceString = breaker[i];
		workingLength = sourceString.length;
		while (true) {
			workingLength = workingLength - 1;
			
			x2 = biFromString("256",10);

			currentNumber = biMultiply(x2, intResult);
			
			intResult = biAdd(currentNumber, biFromString(sourceString[workingLength].charCodeAt(0) + '', 10));
		alert(biToString(intResult, 10));	
			// + sourceString[workingLength].charCodeAt(0);
//			alert(biToString(currentNumber, 10));
			
			//workingInt = biToString(currentNumber, 10);
			
			


			if (workingLength == 0) {
				alert('breaker');
				break;
			}
		}	
		alert('broken');
		alert(biToString(intResult, 10));

	
	/**
	//1754187795380362049897
	setMaxDigits(128);
	mod = biFromString("34223006313802362857834907976974026712808558900922983467528973296961378716888622280051418794301754187795380362049897", 10);
	exponent = biFromString("74051",10);
	working = biFromString("7881608390130606227978128028779202807929733981193549942411873534204262698971990803477520718295257215279337102726232", 10);
	result = biPowMod(working, mod, exponent);
	alert(biToString(result, 10));
	**/
	
}

function encryptString(virginEncrypt) {


//	mod = biFromString("34223006313802362857834907976974026712808558900922983467528973296961378716888622280051418794301754187795380362049897", 10);
//	expInt = biFromString("74051",10);
	
	var expInt = biFromString("113",10);
	var mod = biFromString("50825623218265140459277716391", 10);
			
	chunkArray = virginEncrypt.chunk(12);
	
	convertedLong = "";
	
	for (var y=0; y<chunkArray.length; y++) {
		
		var chunk = chunkArray[y];
		
		
		if (chunk) {
			var working = txt2num(chunk);			
			var workingInt = biFromString(working, 10);
			var result = biPowMod(workingInt, expInt, mod);
			convertedLong = convertedLong  + longBaseConvert(biToString(result, 10) + "", 10, 145) + " ";

		}
		
	}

	changeInput = Base64.encode(convertedLong);

return changeInput;
	
}

function forwardDecryption(decryptString) {

	localHttp= createRequestObject();

	localHttp.open('get', 'http://gygan.com/remoteHandler.php?action=decryption&decryptString=' + encodeURIComponent(decryptString));
	localHttp.onreadystatechange = function(foo) {
		if (localHttp.readyState == 4) {	
				rez = localHttp.responseText;				
				alert(rez);
		}
	}
	localHttp.send(null);
}

function RSAKeyPair(encryptionExponent, decryptionExponent, modulus)
{
	this.e = biFromHex(encryptionExponent);
	this.d = biFromHex(decryptionExponent);
	this.m = biFromHex(modulus);
	// We can do two bytes per digit, so
	// chunkSize = 2 * (number of digits in modulus - 1).
	// Since biHighIndex returns the high index, not the number of digits, 1 has
	// already been subtracted.
	this.chunkSize = 2 * biHighIndex(this.m);
	this.radix = 16;
	this.barrett = new BarrettMu(this.m);
}

function twoDigit(n)
{
	return (n < 10 ? "0" : "") + String(n);
}

function encryptedString(key, s)
	// Altered by Rob Saunders (rob@robsaunders.net). New routine pads the
	// string after it has been converted to an array. This fixes an
	// incompatibility with Flash MX's ActionScript.
{
	var a = new Array();
	var sl = s.length;
	var i = 0;
	while (i < sl) {
		a[i] = s.charCodeAt(i);
		i++;
	}

	while (a.length % key.chunkSize != 0) {
		a[i++] = 0;
	}

	var al = a.length;
	var result = "";
	var j, k, block;
	for (i = 0; i < al; i += key.chunkSize) {
		block = new BigInt();
		j = 0;
		for (k = i; k < i + key.chunkSize; ++j) {
			block.digits[j] = a[k++];
			block.digits[j] += a[k++] << 8;
		}
		var crypt = key.barrett.powMod(block, key.e);
		var text = key.radix == 16 ? biToHex(crypt) : biToString(crypt, key.radix);
		result += text + " ";
	}
	return result.substring(0, result.length - 1); // Remove last space.
}

function decryptedString(key, s)
{
	var blocks = s.split(" ");
	var result = "";
	var i, j, block;
	for (i = 0; i < blocks.length; ++i) {
		var bi;
		if (key.radix == 16) {
			bi = biFromHex(blocks[i]);
		}
		else {
			bi = biFromString(blocks[i], key.radix);
		}
		block = key.barrett.powMod(bi, key.d);
		for (j = 0; j <= biHighIndex(block); ++j) {
			result += String.fromCharCode(block.digits[j] & 255,
			                              block.digits[j] >> 8);
		}
	}
	// Remove trailing null, if any.
	if (result.charCodeAt(result.length - 1) == 0) {
		result = result.substring(0, result.length - 1);
	}
	return result;
}


var Base64 = {
 
	// private property
	_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
 
	// public method for encoding
	encode : function (input) {
		var output = "";
		var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
		var i = 0;
 
		//input = Base64._utf8_encode(input);
 
		while (i < input.length) {
 
			chr1 = input.charCodeAt(i++);
			chr2 = input.charCodeAt(i++);
			chr3 = input.charCodeAt(i++);

 			if (chr1 > 256) {
 				chr1 = charMap[chr1];
 			}
 			if (chr2 > 256) {
 				chr2 = charMap[chr2];
 			}
 			if (chr3 > 256) {
 				chr3 = charMap[chr3];
 			}
			 			
			enc1 = chr1 >> 2;
			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
			enc4 = chr3 & 63;
 
			if (isNaN(chr2)) {
				enc3 = enc4 = 64;
			} else if (isNaN(chr3)) {
				enc4 = 64;
			}
 
			output = output +
			this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
			this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
 
		}
 
		return output;
	},
 
	// public method for decoding
	decode : function (input) {
		var output = "";
		var chr1, chr2, chr3;
		var enc1, enc2, enc3, enc4;
		var i = 0;
 
		input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
 
		while (i < input.length) {
 
			enc1 = this._keyStr.indexOf(input.charAt(i++));
			enc2 = this._keyStr.indexOf(input.charAt(i++));
			enc3 = this._keyStr.indexOf(input.charAt(i++));
			enc4 = this._keyStr.indexOf(input.charAt(i++));
 
			chr1 = (enc1 << 2) | (enc2 >> 4);
			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
			chr3 = ((enc3 & 3) << 6) | enc4;
 
			output = output + String.fromCharCode(chr1);
 
			if (enc3 != 64) {
				output = output + String.fromCharCode(chr2);
			}
			if (enc4 != 64) {
				output = output + String.fromCharCode(chr3);
			}
 
		}
 
		output = Base64._utf8_decode(output);
 
		return output;
 
	},
 
	// private method for UTF-8 encoding
	_utf8_encode : function (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;
	},
 
	// private method for UTF-8 decoding
	_utf8_decode : function (utftext) {
		var string = "";
		var i = 0;
		var c = c1 = c2 = 0;
 
		while ( i < utftext.length ) {
 
			c = utftext.charCodeAt(i);
 
			if (c < 128) {
				string += String.fromCharCode(c);
				i++;
			}
			else if((c > 191) && (c < 224)) {
				c2 = utftext.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			}
			else {
				c2 = utftext.charCodeAt(i+1);
				c3 = utftext.charCodeAt(i+2);
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}
 
		}
 
		return string;
	}
 
}