// --------------------------------------------------------------------
// XOR Encryption functions
//
// Author
// Christian Mueller <pille@hbr1.com>
//
// Copyright
// This module is free software. You may distribute under the terms of
// either the GNU General Public License or the Artistic License.
//
// Have a nice time
// --------------------------------------------------------------------

var HBT = new Array(
	'00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0A', '0B',
	'0C', '0D', '0E', '0F', '10', '11', '12', '13', '14', '15', '16', '17',
	'18', '19', '1A', '1B', '1C', '1D', '1E', '1F', '20', '21', '22', '23',
	'24', '25', '26', '27', '28', '29', '2A', '2B', '2C', '2D', '2E', '2F',
	'30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3A', '3B',
	'3C', '3D', '3E', '3F', '40', '41', '42', '43', '44', '45', '46', '47',
	'48', '49', '4A', '4B', '4C', '4D', '4E', '4F', '50', '51', '52', '53',
	'54', '55', '56', '57', '58', '59', '5A', '5B', '5C', '5D', '5E', '5F',
	'60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6A', '6B',
	'6C', '6D', '6E', '6F', '70', '71', '72', '73', '74', '75', '76', '77',
	'78', '79', '7A', '7B', '7C', '7D', '7E', '7F', '80', '81', '82', '83',
	'84', '85', '86', '87', '88', '89', '8A', '8B', '8C', '8D', '8E', '8F',
	'90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '9A', '9B',
	'9C', '9D', '9E', '9F', 'A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7',
	'A8', 'A9', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'B0', 'B1', 'B2', 'B3',
	'B4', 'B5', 'B6', 'B7', 'B8', 'B9', 'BA', 'BB', 'BC', 'BD', 'BE', 'BF',
	'C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', 'CA', 'CB',
	'CC', 'CD', 'CE', 'CF', 'D0', 'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7',
	'D8', 'D9', 'DA', 'DB', 'DC', 'DD', 'DE', 'DF', 'E0', 'E1', 'E2', 'E3',
	'E4', 'E5', 'E6', 'E7', 'E8', 'E9', 'EA', 'EB', 'EC', 'ED', 'EE', 'EF',
	'F0', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'FA', 'FB',
	'FC', 'FD', 'FE', 'FF'
);

function xor_encrypt( orig, key ) {
	var index, key_tab, key_index, crypt;
	key_tab = new Array( key.length );
	for( key_index = 0; key_index < key.length; key_index ++ ) {
		key_tab[ key_index ] = key.charCodeAt( key_index );
	}
	key_index = 0;
	crypt = "";
	for( index = 0; index < orig.length; index ++ ) {
		crypt += String.fromCharCode( ( orig.charCodeAt( index ) +
			key_tab[ key_index ] ) % 256 );
		key_index = ( key_index + 1 ) % key_tab.length;
	}
	return crypt;
}

function xor_decrypt( crypt, key ) {
	var index, key_tab, key_index, orig;
	key_tab = new Array( key.length );
	for( key_index = 0; key_index < key.length; key_index ++ ) {
		key_tab[ key_index ] = key.charCodeAt( key_index );
	}
	key_index = 0;
	orig = "";
	for( index = 0; index < crypt.length; index ++ ) {
		orig += String.fromCharCode( ( crypt.charCodeAt( index ) -
			key_tab[ key_index ] + 256 ) % 256 );
		key_index = ( key_index + 1 ) % key_tab.length;
	}
	return orig;
}

function xor_encrypt_hex( orig, key ) {
	var index, key_tab, key_index, crypt;
	key_tab = new Array( key.length );
	for( key_index = 0; key_index < key.length; key_index ++ ) {
		key_tab[ key_index ] = key.charCodeAt( key_index );
	}
	key_index = 0;
	crypt = "";
	for( index = 0; index < orig.length; index ++ ) {
		crypt +=
			HBT[ ( orig.charCodeAt( index ) + key_tab[ key_index ] ) % 256 ];
		key_index = ( key_index + 1 ) % key_tab.length;
	}
	return crypt;
}

function xor_decrypt_hex( crypt, key ) {
	var index, key_tab, key_index, orig;
	key_tab = new Array( key.length );
	for( key_index = 0; key_index < key.length; key_index ++ ) {
		key_tab[ key_index ] = key.charCodeAt( key_index );
	}
	key_index = 0;
	orig = "";
	for( index = 0; index < crypt.length; index += 2 ) {
		orig += String.fromCharCode(
			( parseInt( '0x' + crypt.substr( index, 2 ) )
			- key_tab[ key_index ] + 256 ) % 256
		);
		key_index = ( key_index + 1 ) % key_tab.length;
	}
	return orig;
}

/******************************************************************************
 * original by BrowseX XOR Encryption
 *
 * The BrowseX  XOR encryption varies by generating a start seed based
 * upon the XORing of all characters in the password. Modulo arithmetic is
 * used with the seed to determine the offset within the password to start.
 * Modulo is again used to determine when to recalculate the seed based upon
 * the currently selected password character. And finally, the password
 * character itself is XORed with the current seed before it is itself used
 * to XOR the data. 
 ******************************************************************************/

function xor_aperiodic( pass, msg ) {
	var seed = pass.charCodeAt( 0 );
	for( var i = 1; i < pass.length; seed ^= pass.charCodeAt( i ++ ) );
	var p = (seed % pass.length);
	var res = "";
	for( var i = 0; i < msg.length; i ++ ) {
		if( ++ p >= pass.length )
			p = 0;
		var rval = pass.charCodeAt( p );
		if( p == (seed % pass.length) )
			seed = (rval ^ seed);
		res += String.fromCharCode( msg.charCodeAt( i ) ^ (rval ^ seed) );
	}
	return res;
}

function xor_ap_encrypt_hex( pass, msg ) {
	var seed = pass.charCodeAt( 0 );
	for( var i = 1; i < pass.length; seed ^= pass.charCodeAt( i ++ ) );
	var p = (seed % pass.length);
	var res = "";
	for( var i = 0; i < msg.length; i ++ ) {
		if( ++ p >= pass.length )
			p = 0;
		var rval = pass.charCodeAt( p );
		if( p == (seed % pass.length) )
			seed = (rval ^ seed);
		res += HBT[msg.charCodeAt( i ) ^ (rval ^ seed)];
	}
	return res;
}

function xor_ap_decrypt_hex( pass, msg ) {
	var seed = pass.charCodeAt( 0 );
	for( var i = 1; i < pass.length; seed ^= pass.charCodeAt( i ++ ) );
	var p = (seed % pass.length);
	var res = "";
	for( var i = 0; i < msg.length - 2; i += 2 ) {
		if( ++ p >= pass.length )
			p = 0;
		var rval = pass.charCodeAt( p );
		if( p == (seed % pass.length) )
			seed = (rval ^ seed);
		var c = parseInt( '0x' + msg.substr( i, 2 ) );
		res += String.fromCharCode( c ^ (rval ^ seed) );
	}
	return res;
}
