//                                     rsa_js.js 
// extends the biginteger.js class plus some utilities function for RSA string passing
// Bn stands for bignumber
// Copyright (C) 2008 Marius Chincisan @ zalsoft.com. This filr is not under GPL
// Version: 1.0.0.0
// Licence: Private zalsoft inc
//

//---------------------------------------------------------------------------------------
// from php code over internet from several implemntations
function Encrypt(cntntz, exp, modulus, keylen)
{
	cntntz += "\xF0";
    var cntnt = Str2Bn(cntntz);
	var biexp = (exp);
	var bimod = (modulus);
	keylen -= 4;
	var bnl = BnLength(cntnt);
	var blk = Math.ceil(keylen / 8);
	var pw = 0;
	var outs = '';
	var tmp;
	var pmd;
	var i2b;
   	while (pw < bnl) 
	{
		tmp = GetSubBn(cntnt, pw, keylen);
		pmd = BnPowMod(tmp,biexp,bimod);
		i2b = Bn2Str(pmd);
        outs += UtilStrPad(i2b, blk,"\0");
        pw += keylen;
	}
	return Str2Hex(outs);
}

//---------------------------------------------------------------------------------------
function Str2Bn(str)
{
    var result = 0;
    var n = str.length;
    do {
        result = bigint_plus(bigint_mul(result, 256), str.charCodeAt(--n));
    } while (n > 0);
    return result;
}

//---------------------------------------------------------------------------------------
function BnLength(num)
{
    var tmp     = Bn2Str(num);
    var bit_len = tmp.length * 8;
    tmp  = tmp.charCodeAt(tmp.length-1);
    if (tmp==0) 
    {
        bit_len -= 8;
    }
    else 
    {
        while ((tmp & 0x80) == 0) 
        {
            bit_len--;
            tmp <<= 1;
        }
    }
    return bit_len;
}

//---------------------------------------------------------------------------------------
function UtilStrPad(s,l,c)
{
    while(s.length < l)
        s += c;
    return s;
}

//---------------------------------------------------------------------------------------
// inspired from php code over internet from several implemntations
function GetSubBn(num, start, length)
{
    var start_byte  = start / 8;
    var start_bit   = start % 8;
    var byte_length = length / 8;
    var bit_length  = length % 8;
    
    if (bit_length) 
    {
        byte_length++;
    }
    num     = bigint_div(num, (1 << start_bit));
    var tmp = Bn2Str(num).substring(start_byte, start_byte + byte_length);
    tmp     = UtilStrPad(tmp, byte_length, "\0");
    var      codechr = (tmp.charCodeAt(byte_length - 1)) & ((0xff >> (8 - bit_length)));
    codechr = String.fromCharCode(codechr);
    
    var newtmp ='';
    for(var c=0; c < tmp.length; c++)
    {
        if(c == (byte_length - 1))
            newtmp += codechr;
        else
            newtmp += tmp.charAt(c);
    }
    newtmp =  newtmp.substring(0, byte_length);
    retval =  Str2Bn(newtmp);
    return retval;
}

//---------------------------------------------------------------------------------------
function Bn2Str(num)
{
    var result = '';
    do {
        result += String.fromCharCode(bigint_mod(num, 256) & 0xFF);
        num    = bigint_div(num, 256);
    } while (bigint_cmp(num, 0));
    return result;
}

//---------------------------------------------------------------------------------------
// to se a bignumber use Str2Hex(Bn2Str(num))
function Str2Hex(str)
{
    var string = '';
    for(var c=0; c<str.length; c++)
    {
        string += c2h(str.charCodeAt(c & 0xFF));
    }
    return string;
}

//---------------------------------------------------------------------------------------
function Hex2Str(str)
{
    var string = '';
    for(var c=0;c < str.length; )
    {
        var grp =  str.charAt(c++);
        grp     += str.charAt(c++);
        string  += h2c(grp);
    }
    return string;
}

//---------------------------------------------------------------------------------------
function h2c(str) 
{
    var sHex = '0123456789ABCDEF';
    var hb = str.charAt(0); // Note: Netscape 2.0 bug workaround
    var lb  = str.charAt(1);
    return  String.fromCharCode((16 * sHex.indexOf(hb)) +sHex.indexOf(lb));
}

//---------------------------------------------------------------------------------------
function c2h (n) 
{
    var sHex = '0123456789ABCDEF';
    return sHex.charAt(n / 16) + sHex.charAt(n & 0x0F);
}

//---------------------------------------------------------------------------------------
// inspired from php code over internet from several implemntations
function BnPowMod(anum, apow, amod)
{
    var num = bigint_from_any(anum);
    var pow = bigint_from_any(apow);
    var mod = bigint_from_any(amod);
    var result = bigint_from_any('1');
    var tmp    = bigint_from_any('0');
    do {
        if (0 == bigint_cmp(bigint_mod(pow, 2), 1)) 
        {
            result = bigint_mod(bigint_mul(result, num), mod);
        }
        num = bigint_mod(BnPow(num, 2), mod);
	    pow = bigint_div(pow, 2);
	    if(pow==null) break;
    } while (bigint_cmp(pow, 0));
    return result;
}

//---------------------------------------------------------------------------------------
function BnPow(x, y)
{
    var init = x;
	y--;
    while(y--)
    {
        x = bigint_mul(x , init);
    }
    return x;
}

