/*
name: workspace.security.coltrans
extends: workspace.security
*/
workspace.security.coltrans = {}
workspace.security.coltrans._construct = function()
{

	function PermutationGenerator(nNumElements)
	{
		this.nNumElements     = nNumElements;
		this.antranspositions = new Array;
		var k = 0;

		for (i = 0; i < nNumElements - 1; i++)
			for (j = i + 1; j < nNumElements; j++)
				this.antranspositions[ k++ ] = ( i << 8 ) | j;

		// keep two positions as lo and hi byte!
		this.nNumtranspositions = k;

	}
	PermutationGenerator.prototype.fromCycle = function(anCycle)
	{
		var anpermutation = new Array(this.nNumElements);

		for (var i = 0; i < this.nNumElements; i++) anpermutation[i] = i;
		
		for (var i = 0; i < anCycle.length; i++)
		{
			var nT = this.antranspositions[anCycle[i]];
			var n1 = nT & 255;
			var n2 = (nT >> 8) & 255;
			nT = anpermutation[n1];
			anpermutation[n1] = anpermutation[n2];
			anpermutation[n2] = nT;
		}

		return anpermutation;
	}

	function Password(strpasswd)
	{
		this.strpasswd = strpasswd;
	}
	Password.prototype.getHashValue = function()
	{
		var m = 2096597;
		var a = 971;

		var h = 0;

		for (var i = 0; i < this.strpasswd.length; i++) 
			h = (h * a + this.strpasswd.charCodeAt(i)) % m;

		return h;
	}
	Password.prototype.getpermutation = function()
	{
		var nNUMELEMENTS = 13;
		var nCYCLELENGTH = 21;
		
		pg = new PermutationGenerator(nNUMELEMENTS);
		
		var anCycle = new Array(nCYCLELENGTH);
		var npred   = this.getHashValue();

		for (var i = 0; i < nCYCLELENGTH; i++)
		{
			npred = 839 * npred % 2096597;
			anCycle[i] = npred % pg.nNumtranspositions;
		}

		return pg.fromCycle(anCycle);
	}

	function SecureContext(strText)
	{
		this.strText = strText;
	}
	SecureContext.prototype.transliterate = function(btransliterate)
	{
		str = this.strText

		var strDest = '';

		var nTextIter  = 0;
		var nTexttrail = 0;

		while (nTextIter < str.length)
		{
			var strRun = '';
			var cSkipped   = 0;

			while (cSkipped < 7 && nTextIter < str.length)
			{
				var chT = str.charAt(nTextIter++);
				if (-1 == strRun.indexOf(chT))
				{
					strRun += chT;
					cSkipped = 0;
				}
				else cSkipped++;
			}

			while (nTexttrail < nTextIter)
			{
				var nRunIdx = strRun.indexOf(str.charAt(nTexttrail++));
				if (btransliterate)
				{
					nRunIdx++
					if (nRunIdx == strRun.length) nRunIdx = 0;
				}
				else
				{
					nRunIdx--;
					if (nRunIdx == -1) nRunIdx += strRun.length;
				}
				strDest += strRun.charAt(nRunIdx);
			}
		}
		return strDest;
	}
	SecureContext.prototype.encypher = function(anperm)
	{	
		var strEncyph = '';
		var nCols     = anperm.length;
		var nRows     = this.strText.length / nCols;
		
		for (var i = 0; i < nCols; i++)
		{
			var k = anperm[ i ];
			for (var j = 0; j < nRows; j++)
			{
				strEncyph += this.strText.charAt(k);
				k         += nCols;
			}
		}
		
		this.strText = strEncyph;
	}
	SecureContext.prototype.decypher = function(anperm)
	{
		var nRows    = anperm.length;
		var nCols    = this.strText.length / nRows;
		var anRowOfs = new Array;
		
		for (var i = 0 ; i < nRows; i++) anRowOfs[ anperm[ i ] ] = i * nCols;

		var strplain = '';
		for (var i = 0; i < nCols; i++)
		{
			for (var j = 0; j < nRows; j++)
				strplain += this.strText.charAt(anRowOfs[ j ] + i);
		}

		this.strText = strplain;
	}
	SecureContext.prototype.pad = function (nCols, rsPad)
	{

		if (typeof(rsPad) == "undefined") rsPad = ' ';
		var nTextLen     = this.strText.length;
		var nMissingCols = nCols - (nTextLen % nCols);
		var strpadding   = '';  

		if (nMissingCols < nCols)
			for (var i = 0; i < nMissingCols; i++) strpadding += rsPad;

		this.strText +=  strpadding;
	}
	SecureContext.prototype.secure = function (strpasswd, rsPad)
	{
		var passwd = new Password(strpasswd);
		var anperm   = passwd.getpermutation()
		this.sign(anperm.length, rsPad);
		this.transliterate(true);
		this.encypher(anperm);
	}
	SecureContext.prototype.unsecure = function (strpasswd)
	{
		var passwd = new Password(strpasswd);
		var anperm = passwd.getpermutation();
		this.decypher(anperm);
		this.transliterate(false);
		return true;
	}

	function getCryptText(rsPlain, rsPassword, rsPad)
	{
		var sc = new SecureContext(rsPlain);

		sc.secure(rsPassword, rsPad);

		return sc.strText;	
	}

	function getPlainText(rsCrypt, rsPassword)
	{
		var sc = new SecureContext(rsCrypt);
		
		sc.unsecure(rsPassword);
		
		return sc.strText;
	}
	
	this.getCryptText = getCryptText
	this.getPlainText = getPlainText
}
workspace.security.coltrans._construct()