/*******************************************/
/* Program Arc4. Version 1.0. August 2012. */
/*******************************************/

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main(int argc, char* argv[])					// Takes arguments
{
	unsigned int s[256];							// int array for ...
	string keystring = "";							// string for the key
	unsigned int keylength;							// int for the length of the key
	string FileNameIn = "";							// Name of file for input
	string FileNameOut = "";						// Name of file for output
	unsigned int filesize;							// int for the size of the input file
	int temp = 0;									// int for use in 
	
	/* Check that the number of arguments is correct, i.e. equal to 2 */
		if (argc < 3 || argc >3){cout << "Error 1: Wrong syntax." << endl << "Syntax: arc4 filein fileout" << endl; return 1;}
	
	/* Set up array s[] = 0, 1, 2, ... , 256. This array is used in the ...*/
		for (int i = 0; i < 256; i++)
		{
				s[i] = i;	
		}
	
	/* Set up the key key[] as an int array*/
		cout << "Enter key..: " ;					// Asks for the key/password
		getline (cin,keystring);					// Reads the key from the input
		keylength = keystring.size();				// Computes the length of the key
	
	/* Check that the length of the key is not zero*/
		if (keylength == 0) {cout << "Error 2: Key length is zero." << endl; return 1;}

	int key[keylength] ;							// Declares the int array used for the key

	/* Stores the key in the int array key. Each entry is an unsigned integer */
		for (int i = 0; i < keylength ; i++) 
		{
			key[i] = (int)((char)keystring.at(i));	
		} 
	
	/* Set up the array s[] */
		int j = 0;									// Temporary variable 
		for (int i = 0 ; i < 256; i++)
		{
			j = (j + s[i] + key[ i % keylength] ) % 256;
			temp = s[i];
			s[i] = s[j];
			s[j] = temp;
		}
	
	/* Encryption / decryption routine */	
		FileNameIn = argv[1];
		FileNameOut = argv[2];
		ifstream myFileIn (FileNameIn, ios::out | ios::binary);					// Opens input file		
		ofstream myFileOut (FileNameOut, ios::in | ios::binary | ios::trunc);	// Opens output file
	
	/* Continue if the input file is open */
		if (myFileIn.is_open())
		{
			myFileIn.seekg(0, ios::end ); 										// Move to end of file
			filesize = myFileIn.tellg(); 										// Compute file size
			unsigned char r; 													// char to be read
			unsigned char w; 													// char to be written
			unsigned int i = 0;
			unsigned int j = 0;
			int keys = 0;
			int keystream = 0;
			
			for (int n = 0; n <= filesize - 1; n++)
			{
				i = (i + 1) % 256;
				j = (j + s[i]) % 256;
				temp = s[i];
				s[i] = s[j];
				s[j] = temp;
				myFileIn.seekg (n, ios::beg); 									// Move to the beginning of the file
				myFileIn >> noskipws >> r;										// Read one byte from file
				keys = (s[i] + s[j]) % 256;										
				keystream = s[keys];											 
				w = r ^ (char)keystream;										// Compute the character to be written
				myFileOut << w;													// Write to the output file
			}
	
	}
	
	/* Close files */
	myFileIn.close();			
	myFileOut.close();	
	cout << "Sucess!"<< endl;
	return 0;
}



