65.9K
CodeProject 正在变化。 阅读更多。
Home

RC4 和 Base64 流密码算法的两个高效类

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.81/5 (15投票s)

2009年4月11日

CPOL

3分钟阅读

viewsIcon

80849

downloadIcon

2775

两个快速高效的 RC4 和 Base64 流密码算法类

引言

本文提供了两个高效且方便的 Base64 和 RC4 流密码算法的 C++ 封装类。

背景

我编程实现这些类是在我搜索互联网之后,发现很少有实现既简洁又高效,足以在项目中作为较低级别的密码类实际使用。

算法介绍 

什么是 RC4

RC4 由 RSA Security 的 Ron Rivest 于 1987 年创建。它是最广泛使用的软件流密码之一,并用于流行的协议中,例如安全套接字层 (SSL)(用于保护互联网流量)和WEP(用于保护无线网络)。RC4 用于许多商业软件包,例如 Lotus Notes 和 Oracle Secure SQL。

RC4 算法分为两部分,一个“密钥调度算法”(KSA),它将一个随机密钥(通常在 40 到 256 位之间)转换为 N(2 的幂)S-box的初始排列。另一部分是“伪随机数生成器”(PRNG),PRNG 使用排列来生成一个伪随机数序列,该序列与明文进行异或运算以产生密文。

RC4 是一种快速的密码算法,比 DES(数据加密标准)快大约 10 倍。

这个封装类 CRC4 是一个方便的版本,可以通过避免编码文本数据中间的字符串终止符 ¡®\0¡¯ 来使用。 如果您想将编码的文本数据作为string处理,而不知道 '\0' 字符可能会截断您的密文使其不完整,这会很烦人并且会隐藏错误。

CRC4 类的代码

#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   */
};
;

什么是 BASE64

Base64 是一种解释数据位的方式,以便通过纯文本媒介(例如电子邮件的正文)传输该数据。

Base64 Content-Transfer-Encoding 旨在以一种无需人工可读的形式来表示任意的八位字节序列。它因其效率而被广泛用于电子邮件编码和 .NET View 状态编码。

Base64 算法以 24 位块处理输入,方法是将每个块转换为 4 个字节的输出。 它是通过将输入分成四个 6 位组,并将其用作以下替换表中的索引来实现的

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

如果输入不是 3 字节的倍数,则用零填充。 在这种情况下,完全由填充数据组成的输出字节将替换为 '='。

Base64 示例

0x00 0x45 0xF2的输入等同于00000000 01000101 11110010位序列,然后将其拆分为000000 000100 010111 110010,并将这些替换为生成以下 base64 编码 'A' 'E' 'X' 'y'。

CBase64 类的代码

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

如果您想在您的项目中使用该代码,只需直接从该页面复制代码并粘贴到您的源文件中,或者将Base64_RC4.h复制到您的项目文件夹中并插入一个头文件行。

#include "Base64_RC4.h" 

使用这些类的演示

#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();
}

关注点

编码/解码非常有趣且对于安全性至关重要,尝试使用它并感受它的魔力。

© . All rights reserved.