Click here to Skip to main content
15,867,453 members
Articles / Programming Languages / C

Two Efficient Classes for RC4 and Base64 Stream Cipher Algorithms

Rate me:
Please Sign up or sign in to vote.
4.81/5 (18 votes)
15 Apr 2009CPOL3 min read 77.4K   2.8K   36   17
Two fast and efficient classes of RC4 and Base64 stream cipher algorithms
Image 1

Introduction

This article provides two efficient and handy wrapping C++ classes of Base64 and RC4 stream cipher algorithms.

Background

I programmed the classes after I searched the internet and found very few implementations are neat and efficient enough for practical use as lower cipher classes in the project.

Introduction of Algorithms 

What is RC4

RC4 was created by Ron Rivest of RSA Security in 1987. It is one of the most widely-used software stream cipher and is used in popular protocols such as Secure Sockets Layer (SSL) (to protect Internet traffic) and WEP (to secure wireless networks). RC4 is used in many commercial software packages such as Lotus Notes and Oracle Secure SQL.

There are two parts in RC4 algorithm, a 'key scheduling algorithm' (KSA) which turns a random key (typically between 40 and 256 bits) into an initial permutation of S-box of N(power of 2). The other part is 'pseudorandom number generator(' PRNG), PRNG uses the permutation to generate a pseudo-random number sequence which is XORed with the plaintext to give the cipher text.

RC4 is a fast cipher algorithm and about 10 times faster than DES(Data Encryption Standard).

This wrapping class CRC4 is a handy version for using by avoiding string terminator ¡®\0¡¯ in the middle of the encoded text data. It is annoying and bug-hidden if you want to handle the encoded text data as a string without knowing that the '\0' character could truncate your cipher text to be incomplete.

The Code of Class CRC4

C++
#define SWAP(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
class CRC4 
{
public:

	  CRC4 () 
	  {
		memset(sbox,0,256);
		memset(key,0,256);
	  }
	  virtual ~CRC4 ()
	  {							
		memset(sbox,0,256);  /* remove Key traces in memory  */
		memset(key,0,256);   
	  }

	  char *Encrypt(char *pszText,const char *pszKey) 
	  {
		i=0, j=0,n = 0;
		ilen = (int)strlen(pszKey);

		for (m = 0;  m < 256; m++)  /* Initialize the key sequence */
		{
			*(key + m)= *(pszKey + (m % ilen));
			*(sbox + m) = m;
		}
		for (m=0; m < 256; m++)
		{
			n = (n + *(sbox+m) + *(key + m)) &0xff;
			SWAP(*(sbox + m),*(sbox + n));
		}

		ilen = (int)strlen(pszText);
		for (m = 0; m < ilen; m++)
		{
			i = (i + 1) &0xff;
			j = (j + *(sbox + i)) &0xff;
			SWAP(*(sbox+i),*(sbox + j));  /* randomly Initialize 
							the key sequence */
			k = *(sbox + ((*(sbox + i) + *(sbox + j)) &0xff ));
			if(k == *(pszText + m))       /* avoid '\0' among the 
							encoded text; */
			       k = 0;
			*(pszText + m) ^=  k;
		}

		return pszText;
	  }

	  char *Decrypt(char *pszText,const char *pszKey)
	  {
	        return Encrypt(pszText,pszKey) ;  /* using the same function 
							as encoding */
	  }

private:
          unsigned char sbox[256];      /* Encryption array             */
          unsigned char key[256],k;     /* Numeric key values           */
	 int  m, n, i, j, ilen;        /* Ambiguously named counters   */
};
;

What is BASE64

Base64 is a different way of interpreting bits of data in order to transmit that data over a text-only medium, such as the body of an e-mail.

The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable. It is widely used in e-mail encoding and also .NET View state encoding for its efficiency.

Base64 algorithm processes input in 24bit chunks by converting each chunk into 4 bytes of output. It does so by splitting input into four 6 bit groups and using these as indexes in the following substitution table:

C++
const char base64_map[] =
	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

If an input is not a multiple of 3 bytes, it's padded with zeros. In this case, the output bytes that consist entirely of the pad data are replaced with '='.

Example of Base64

An input of 0x00 0x45 0xF2 is equivalent to 00000000 01000101 11110010 bit sequence, which is then split into 000000 000100 010111 110010 and these are substituted to produce the following base64 encoding 'A' 'E' 'X' 'y'.

The code of class CBase64

C++
class CBase64
{
public:
	CBase64(){}

	char *Encrypt(const char * srcp, int len, char * dstp)
	{
		register int i = 0;
		char *dst = dstp;

		for (i = 0; i < len - 2; i += 3)
		{
			*dstp++ = *(base64_map + ((*(srcp+i)>>2)&0x3f));
			*dstp++ = *(base64_map + ((*(srcp+i)<< 4)&0x30 | (
                                *(srcp+i+1)>>4)&0x0f ));
			*dstp++ = *(base64_map + ((*(srcp+i+1)<<2)&0x3C | (
                                *(srcp+i+2)>>6)&0x03));
			*dstp++ = *(base64_map + (*(srcp+i+2)&0x3f));
		}
		srcp += i;
		len -= i;

		if(len & 0x02 ) /* (i==2) 2 bytes left,pad one byte of '=' */
		{      
			*dstp++ = *(base64_map + ((*srcp>>2)&0x3f));
			*dstp++ = *(base64_map + ((*srcp<< 4)&0x30 | (
                                *(srcp+1)>>4)&0x0f ));
			*dstp++ = *(base64_map + ((*(srcp+1)<<2)&0x3C) );
			*dstp++ = '=';
		}
		else if(len & 0x01 )  /* (i==1) 1 byte left,pad two bytes of '='  */
		{ 
			*dstp++ = *(base64_map + ((*srcp>>2)&0x3f));
			*dstp++ = *(base64_map + ((*srcp<< 4)&0x30));
			*dstp++ = '=';
			*dstp++ = '=';
		}

		*dstp = '\0';

		return dst;
	}

	void *Decrypt(const char * srcp, int len, char * dstp)
	{
		register int i = 0;
		void *dst = dstp;

		while(i < len)
		{
			*dstp++ = (B64_offset[*(srcp+i)] <<2 | 
                                B64_offset[*(srcp+i+1)] >>4);
			*dstp++ = (B64_offset[*(srcp+i+1)]<<4 | 
                                B64_offset[*(srcp+i+2)]>>2);
			*dstp++ = (B64_offset[*(srcp+i+2)]<<6 |
                                B64_offset[*(srcp+i+3)] );
			i += 4;
		}
		srcp += i;
		
		if(*(srcp-2) == '=')  /* remove 2 bytes of '='  padded while encoding */
		{	 
			*(dstp--) = '\0';
			*(dstp--) = '\0';
		}
		else if(*(srcp-1) == '=') /* remove 1 byte of '='  padded while encoding */
			*(dstp--) = '\0';

		*dstp = '\0';

		return dst;
	};

	size_t B64_length(size_t len)
	{
		size_t  npad = len%3;
                // padded for multiple of 3 bytes
		size_t  size = (npad > 0)? (len +3-npad ) : len;
         return  (size*8)/6;
	}

	size_t Ascii_length(size_t len)
	{
		return  (len*6)/8;
	}

};

Using the Code

If you want to use the code in your project, just copy the code directly from this page and paste into your source file or copy Base64_RC4.h into your project folder and insert a header line.

C++
#include "Base64_RC4.h" 

A Demo of Using the Classes

C++
#include "Base64_RC4.h"
void main()
{
	char str[64] = "This is a test for RC4 cypher";
/* Test rc4 encoding and decoding here */
	CRC4 rc4;
	printf("Demo for RC4 \n\n");
	printf("Plain text: %s \n",str);
	rc4.Encrypt(str,"Key");
	printf("Encoded string: %s \n",str);
	rc4.Decrypt(str,"Key");
	printf("Decoded string: %s \n",str);
/* Test Base64  encoding and decoding here */
	strcpy(str, "This is a test for Base64 cypher");
	CBase64  base64;
	char *dst;
	dst = (char*)malloc( base64.B64_length(strlen(str))+1);
	if(dst == NULL)
		return;
	printf("\n\nDemo for Base64 \n\n");
	printf("Plain text: %s \n",str);
	base64.Encrypt(str,strlen(str),dst);
	printf("Encoded string: %s\n",dst);
	memset(str,0,sizeof(str));
	base64.Decrypt(dst,strlen(dst),str);
	printf("Decoded string: %s\n",str);
	free(dst);
	getchar();
}

Points of Interest

Encoding/decoding is a lot of fun and critical for security, try to use it and feel its magic.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder SmartTick Software Inc.
Canada Canada
Jerry Jiang(BOLIANG JIANG)

A passionate software developer since 1992

Education:Master of Computer Science.

jerry@smarttick.com

Comments and Discussions

 
NewsYour RC4 Decript function maybe incorrect. Pin
NullMiracle4-May-14 21:44
NullMiracle4-May-14 21:44 
QuestionSwap Problem Pin
See_Sharp4-Sep-12 8:04
See_Sharp4-Sep-12 8:04 
AnswerRe: Swap Problem Pin
Jerry Jiang17-Sep-12 20:07
Jerry Jiang17-Sep-12 20:07 
QuestionSeems to mess up on a NULL Pin
Member 96487181-Jul-12 9:32
Member 96487181-Jul-12 9:32 
AnswerRe: Seems to mess up on a NULL Pin
Member 96487181-Jul-12 9:38
Member 96487181-Jul-12 9:38 
GeneralRe: Seems to mess up on a NULL Pin
Jerry Jiang17-Sep-12 20:19
Jerry Jiang17-Sep-12 20:19 
QuestionQuery on the key. Pin
Snehamoy Banerjee21-Aug-11 2:05
Snehamoy Banerjee21-Aug-11 2:05 
AnswerRe: Query on the key. Pin
Jerry Jiang24-Sep-11 22:19
Jerry Jiang24-Sep-11 22:19 
GeneralNew code snippet for char *Encrypt(char *pszText,const char *pszKey) in class CRC4 Pin
Jerry Jiang10-Jul-09 8:22
Jerry Jiang10-Jul-09 8:22 
Generalneeds a lot more. Pin
madicursar13-Apr-09 22:56
madicursar13-Apr-09 22:56 
GeneralRe: needs a lot more. [modified] Pin
Jerry Jiang14-Apr-09 9:52
Jerry Jiang14-Apr-09 9:52 
GeneralMy vote of 2 Pin
Nick Kulikovsky13-Apr-09 14:41
Nick Kulikovsky13-Apr-09 14:41 
GeneralRe: My vote of 2 [modified] Pin
Jerry Jiang13-Apr-09 16:50
Jerry Jiang13-Apr-09 16:50 
GeneralRe: My vote of 2 Pin
yafan15-Apr-09 11:42
yafan15-Apr-09 11:42 
GeneralRe: My vote of 2 [modified] Pin
Jerry Jiang15-Apr-09 17:05
Jerry Jiang15-Apr-09 17:05 
GeneralMy vote of 2 Pin
surajfrommumbai12-Apr-09 18:16
surajfrommumbai12-Apr-09 18:16 
GeneralRe: My vote of 2 [modified] Pin
Jerry Jiang12-Apr-09 19:08
Jerry Jiang12-Apr-09 19:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.