xor (en/de)cryption using a key file source code

This snippet submitted by yzb3 on 2012-02-02. It has been viewed 23270 times.
Rating of 5.4 with 151 votes

/*
	The function (en/de)crypts an input data file with an input key
	file using the XOR method.

	The use of a key file instead of a plain text key makes it much
	more flexible and secure. If the key is longer than the encrypted data,
	truly random (btw, compressed files like mp3 or jpg provide pretty
	good "almost-like-random" characters) and used only once, even though
	the metod is so simple, it is unbreakable even in theory.
*/

//libraries to include
#include <stdio.h> //for file handling and other IO
#include <stdlib.h> //for the exit function

//macros
#define BUF 512 //input filename buffer size
#define CNK 256 //IO buffer size
#define FILCHK(x) if(!x){printf("Cannot open file %s\n", x); exit(EXIT_FAILURE);} //file pointer checker

//xor (en/de)coding function
void xorenc(char *inname, char *outname, char *keyname)
{
	FILE *infile, *outfile, *keyfile; //file pointers
	char datachunk[CNK], keychunk[CNK]; //input data & key buffers
	long datapos, keypos, datalen, keylen, keymax; //data lengths
	
	//open files
	infile = fopen(inname, "rb"); //binary mode (b) is crucial
	FILCHK(infile); //check the file pointer
	outfile = fopen(outname, "wb");
	FILCHK(outfile);
	keyfile = fopen(keyname, "rb");
	FILCHK(keyfile);
	
	//get key length
	fseek(keyfile, 0L, SEEK_END); //seek the end of file
	keymax = ftell(keyfile); //tell what its position is
	rewind(keyfile); //go back to the beginning of the key file
	
	//get the first key chunk
	keypos = 0; //initialize the key buffer position
	keylen = fread(keychunk, 1, CNK, keyfile); //binary read a chunk of the key
	
	//an infinite loop
	while(1)
	{
		//binary read a chunk of data
		datalen = fread(datachunk, 1, CNK, infile);
		
		//for every char in the input buffer
		for(datapos = 0; datapos < datalen; ++datapos)
		{
			datachunk[datapos] ^= keychunk[keypos++]; //xor a data char with a key char
			
			//if the whole key chunk was used
			if(keypos == CNK)
			{
				keylen += fread(keychunk, 1, CNK, keyfile); //read a new key chunk
				keypos = 0; //set the key buffer position to 0
			}
			
			//otherwise, if the whole key file was used
			else if(keypos == keymax || keypos == keylen)
			{
				rewind(keyfile); //rewind it
				keylen = fread(keychunk, 1, CNK, keyfile); //read a key chunk
				keypos = 0; //set the key buffer position to 0
			}
		}
		
		//binary write the (en/de)crypted data
		fwrite(datachunk, 1, datalen, outfile);
		
		//if the whole data file was processed
		if(datalen < CNK)
			break; //end the loop
		
		//otherwise, if the whole key file was processed
		else if(keylen == keymax)
		{
			rewind(keyfile); //rewind it
			keylen = fread(keychunk, 1, CNK, keyfile); //read a key chunk
			keypos = 0; //set the key buffer position to 0
		}
	}
	
	//close the files
	fclose(infile);
	fclose(outfile);
	fclose(keyfile);
}




More C and C++ source code snippets