/*
* A JavaScript implementation of the ARCFour stream cipher
*
* FILE:	arcfour.js
* VERSION:	1.0
* AUTHOR:	Christoph Bichlmeier <informatik@zombiearena.de>
*
* NOTE: This version is not tested thoroughly!
*
* Copyright (c) 2004, Christoph Bichlmeier
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of contributors
*    may be used to endorse or promote products derived from this software
*    without specific prior written permission.
*
* ======================================================================
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


/* the arcfour encryption / decryption */
function arcfour_crypt(data, key)
{
	var STATE_LENGTH = 256;
	var i, i1, i2, x, y, temp;
	var secretKey = new Array(STATE_LENGTH);
	var keyLen = key.length;
	var dataLen = data.length;
	var output = new Array(dataLen);

	i1 = 0; i2 = 0; x = 0; y = 0;
	for(i = 0; i < STATE_LENGTH; i++)
		secretKey[i] = i;


	for(i = 0; i < STATE_LENGTH; i++)
	{
		i2 = ((key.charCodeAt(i1) & 255) + secretKey[i] + i2) & 255;
		// swap
		temp = secretKey[i]; secretKey[i] = secretKey[i2]; secretKey[i2] = temp;
		i1 = (i1 + 1) % keyLen;
	}

	for(i = 0; i < dataLen ; i++)
	{
		x = (x + 1) & 255;
		y = (secretKey[x] + y) & 255;
		// swap
		temp = secretKey[x]; secretKey[x] = secretKey[y]; secretKey[y] = temp;
		// xor
		output[i] = data.charCodeAt(i) ^ secretKey[(secretKey[x] + secretKey[y]) & 255];
    }
	return arcfour_byte_string(output);
}

/* convert byte array into string */
function arcfour_byte_string(input)
{
	var output = new String();
	for(var i = 0; i < input.length; i++)
	{
		output += String.fromCharCode(input[i]);
	}
	return output;
}

/* get the hex representation of an array of bytes */
function arcfour_hex_encode(input)
{
	var hex_digits = "0123456789abcdef";
	var output = new String();
	for(var i = 0; i < input.length; i++)
	{
		output += hex_digits.charAt((input.charCodeAt(i) >>> 4) & 15);
		output += hex_digits.charAt( input.charCodeAt(i)        & 15);
	}
	return output;
}

/* decode hex string */
function arcfour_hex_decode(input)
{
	var left, right, index;
	var output = new Array(input.length/2);
	for (var i = 0; i < input.length; i += 2)
	{
		left  = input.charCodeAt(i);
		right = input.charCodeAt(i+1);
		index = i / 2;
		if (left < 97)  // left < 'a'
			output[index] = ((left - 48)      << 4);  // left - '0'
		else
			output[index] = ((left - 97 + 10) << 4);
		if (right < 97)
			output[index] += (right - 48);
		else
			output[index] += (right - 97 + 10);
	}
	return arcfour_byte_string(output);
}
