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






4.81/5 (15投票s)
两个快速高效的 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();
}
关注点
编码/解码非常有趣且对于安全性至关重要,尝试使用它并感受它的魔力。