// 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 

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 = 10;
	this.barrett = new BarrettMu(this.m);
}

function twoDigit(n)
{
	return (n < 10 ? "0" : "") + String(n);
}

function encryptedString(public_key, message, modulus)
	// 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 public_key = biFromString(public_key, 10);
	var m = biFromString(modulus, 10);
	var chunkSize = 2 * biHighIndex(m);
	var barrett = new BarrettMu(m);
	
	var a = new Array();
	var sl = message.length;
	var i = 0;
	while (i < sl) {
		a[i] = message.charCodeAt(i);
		i++;
	}

	while (a.length % chunkSize != 0) {
		a[i++] = ' ';	//pad with spaces andrew masri
	}
	
	a = a.reverse();	//andrew masri reverse the string for compatibility with the server-side php rsa function

	var al = a.length;
	var result = "";
	var j, k, block;
	for (i = 0; i < al; i += chunkSize) {
		block = new BigInt();
		j = 0;
		for (k = i; k < i + chunkSize; ++j) {
			block.digits[j] = a[k++];
			block.digits[j] += a[k++] << 8;
		}
		var crypt = barrett.powMod(block, public_key);
		var text = biToString(crypt, 10);		//andrew masri - use decimal for compatibility with server-side
		result += text + " ";
	}
	return result.substring(0, result.length - 1); // Remove last space.
}

function decryptedString(private_key, message, modulus)
{
	var private_key = biFromString(private_key, 10);
	var m = biFromString(modulus, 10);
	var barrett = new BarrettMu(m);

	var blocks = message.split(" ");
	var result = "";
	var i, j, block;
	for (i = 0; i < blocks.length; ++i) {
		var bi = biFromString(blocks[i], 10);		//andrew masri - use decimal for compatibility with server-side
		block = barrett.powMod(bi, private_key);
		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);
	}
	
	result = result.reverse();	//andrew masri reverse the string for compatibility with the server-side php rsa function

	return result;
}


String.prototype.reverse = function(){
	splitext = this.split("");
	revertext = splitext.reverse();
	reversed = revertext.join("");
	return reversed;
}
