码迷,mamicode.com
首页 > 编程语言 > 详细

RC5分组密码算法

时间:2015-07-11 15:10:26      阅读:392      评论:0      收藏:0      [点我收藏+]

标签:

RC5分组密码算法是1994由麻萨诸塞技术研究所的Ronald L. Rivest教授发明的,并由RSA实验室分析。它是参数可变的分组密码算法,三个可变的参数是:分组大小、密钥大小和加密轮数。在此算法中使用了三种运算:异或、加和循环。
RC5是种比较新的算法,Rivest设计了RC5的一种特殊的实现方式,因此RC5算法有一个面向字的结构:RC5-w/r/b,这里w是字长其值可以是16、32或64对于不同的字长明文和密文块的分组长度为2w位,r是加密轮数,b是密钥字节长度。RC5是一个分组长度可变的密码算法.
加密解密
1、创建密钥组
RC5算法加密时使用了2r+2个密钥相关的的32位字: 这里r表示加密的轮数。
2、加密处理
在创建完密钥组后开始进行对明文的加密。
3、解密处理
RSA试验室花费了相当的时间来分析64位分组的RC5算法,在5轮后统计特性看起来非常好,在6轮后线性分析就是安全的了。在8轮后,每一个明文位至少影响一个循环。Rivest推荐至少12轮,甚至可能是16轮。轮数可以进行选择,一般是8轮、12轮或16轮。

代码如下(在实际项目中经过大量测试过):

RC5加密算法头文件

#ifndef _MY_RC5_H
#define _MY_RC5_H
#include <stdlib.h>

#define RC5_ENCRYPT	1
#define RC5_DECRYPT	0


/* 32 bit.  For Alpha, things may get weird */
#define RC5_32_INT unsigned int


#define RC5_32_BLOCK		8
#define RC5_32_KEY_LENGTH	16 /* This is a default, max is 255 */


/* This are the only values supported.  Tweak the code if you want more
 * * The most supported modes will be
 * * RC5-32/12/16
 * * RC5-32/16/8
 * */
#define RC5_8_ROUNDS	8
#define RC5_12_ROUNDS	12
#define RC5_16_ROUNDS	16


typedef struct rc5_key_st
{
	/* Number of rounds */
	int rounds;
	RC5_32_INT data[2*(RC5_16_ROUNDS+1)];
} RC5_32_KEY;


#define c2ln(c,l1,l2,n)	{ 	c+=n; 		l1=l2=0; 		switch (n) { 			case 8: l2 =((RC5_32_INT )(*(--(c))))<<24L; 			case 7: l2|=((RC5_32_INT )(*(--(c))))<<16L; 			case 6: l2|=((RC5_32_INT )(*(--(c))))<< 8L; 			case 5: l2|=((RC5_32_INT )(*(--(c))));     			case 4: l1 =((RC5_32_INT )(*(--(c))))<<24L; 			case 3: l1|=((RC5_32_INT )(*(--(c))))<<16L; 			case 2: l1|=((RC5_32_INT )(*(--(c))))<< 8L; 			case 1: l1|=((RC5_32_INT )(*(--(c))));     		} }
#undef c2l
#define c2l(c,l)	(l =((RC5_32_INT )(*((c)++)))    , 		l|=((RC5_32_INT )(*((c)++)))<< 8L, 		l|=((RC5_32_INT )(*((c)++)))<<16L, 		l|=((RC5_32_INT )(*((c)++)))<<24L)


#define RC5_32_MASK	0xffffffffL


#define RC5_16_P	0xB7E1
#define RC5_16_Q	0x9E37
#define RC5_32_P	0xB7E15163L
#define RC5_32_Q	0x9E3779B9L
#define RC5_64_P	0xB7E151628AED2A6BLL
#define RC5_64_Q	0x9E3779B97F4A7C15LL


#define ROTATE_l32(a,n)     (((a)<<(int)(n))|((a)>>(32-(int)(n))))
#define ROTATE_r32(a,n)     (((a)>>(int)(n))|((a)<<(32-(int)(n))))
	/*
	 * #define ROTATE_l32(a,n)     _lrotl(a,n)
	 * #define ROTATE_r32(a,n)     _lrotr(a,n)
	 * */


#define E_RC5_32(a,b,s,n) 	a^=b; 	a=ROTATE_l32(a,b); 	a+=s[n]; 	a&=RC5_32_MASK; 	b^=a; 	b=ROTATE_l32(b,a); 	b+=s[n+1]; 	b&=RC5_32_MASK;


#define D_RC5_32(a,b,s,n) b-=s[n+1]; 	b&=RC5_32_MASK; 	b=ROTATE_r32(b,a); 	b^=a; 	a-=s[n]; 	a&=RC5_32_MASK; 	a=ROTATE_r32(a,b); 	a^=b;


typedef void (* f_RC5_32_decrypt)(RC5_32_INT *d, RC5_32_KEY *key);
typedef void (* f_RC5_32_encrypt)(RC5_32_INT *d, RC5_32_KEY *key);
typedef void (* f_RC5_32_set_key)(RC5_32_KEY *key, int len, const unsigned char *data,
		int rounds);
#endif

RC5 加密算法源文件

//设置密钥

void RC5_32_set_key(RC5_32_KEY *key, int len, const unsigned char *data,
		    int rounds)
	{
	RC5_32_INT L[64],l,ll,A,B,*S,k;
	int i,j,m,c,t,ii,jj;


	if (	(rounds != RC5_16_ROUNDS) &&
		(rounds != RC5_12_ROUNDS) &&
		(rounds != RC5_8_ROUNDS))
		rounds=RC5_16_ROUNDS;


	key->rounds=rounds;
	S= &(key->data[0]);
	j=0;
	for (i=0; i<=(len-8); i+=8)
		{
		c2l(data,l);
		L[j++]=l;
		c2l(data,l);
		L[j++]=l;
		}
	ii=len-i;
	if (ii)
		{
		k=len&0x07;
		c2ln(data,l,ll,k);
		L[j+0]=l;
		L[j+1]=ll;
		}


	c=(len+3)/4;
	t=(rounds+1)*2;
	S[0]=RC5_32_P;
	for (i=1; i<t; i++)
		S[i]=(S[i-1]+RC5_32_Q)&RC5_32_MASK;


	j=(t>c)?t:c;
	j*=3;
	ii=jj=0;
	A=B=0;
	for (i=0; i<j; i++)
		{
		k=(S[ii]+A+B)&RC5_32_MASK;
		A=S[ii]=ROTATE_l32(k,3);
		m=(int)(A+B);
		k=(L[jj]+A+B)&RC5_32_MASK;
		B=L[jj]=ROTATE_l32(k,m);
		if (++ii >= t) ii=0;
		if (++jj >= c) jj=0;
		}
	}

//加密函数
void RC5_32_encrypt(RC5_32_INT *d, RC5_32_KEY *key)
	{
		RC5_32_INT a,b,*s;

		s=key->data;

		a=d[0]+s[0];
		b=d[1]+s[1];
		E_RC5_32(a,b,s, 2);
		E_RC5_32(a,b,s, 4);
		E_RC5_32(a,b,s, 6);
		E_RC5_32(a,b,s, 8);
		E_RC5_32(a,b,s,10);
		E_RC5_32(a,b,s,12);
		E_RC5_32(a,b,s,14);
		E_RC5_32(a,b,s,16);
		if (key->rounds == 12)
		{
			E_RC5_32(a,b,s,18);
			E_RC5_32(a,b,s,20);
			E_RC5_32(a,b,s,22);
			E_RC5_32(a,b,s,24);
		}
		else if (key->rounds == 16)
		{
			/* Do a full expansion to avoid a jump */
			E_RC5_32(a,b,s,18);
			E_RC5_32(a,b,s,20);
			E_RC5_32(a,b,s,22);
			E_RC5_32(a,b,s,24);
			E_RC5_32(a,b,s,26);
			E_RC5_32(a,b,s,28);
			E_RC5_32(a,b,s,30);
			E_RC5_32(a,b,s,32);
		}
		d[0]=a;
		d[1]=b;
	}

//解密函数
void RC5_32_decrypt(RC5_32_INT *d, RC5_32_KEY *key)
	{
		RC5_32_INT a,b,*s;

		s=key->data;

		a=d[0];
		b=d[1];
		if (key->rounds == 16) 
		{
			D_RC5_32(a,b,s,32);
			D_RC5_32(a,b,s,30);
			D_RC5_32(a,b,s,28);
			D_RC5_32(a,b,s,26);
			/* Do a full expansion to avoid a jump */
			D_RC5_32(a,b,s,24);
			D_RC5_32(a,b,s,22);
			D_RC5_32(a,b,s,20);
			D_RC5_32(a,b,s,18);
		}
		else if (key->rounds == 12)
		{
			D_RC5_32(a,b,s,24);
			D_RC5_32(a,b,s,22);
			D_RC5_32(a,b,s,20);
			D_RC5_32(a,b,s,18);
		}
		D_RC5_32(a,b,s,16);
		D_RC5_32(a,b,s,14);
		D_RC5_32(a,b,s,12);
		D_RC5_32(a,b,s,10);
		D_RC5_32(a,b,s, 8);
		D_RC5_32(a,b,s, 6);
		D_RC5_32(a,b,s, 4);
		D_RC5_32(a,b,s, 2);
		d[0]=a-s[0];
		d[1]=b-s[1];
	}

加密解密封装头文件

//声明加密函数
extern void RC5_32_set_key(RC5_32_KEY *key, int len, const unsigned char *data,int rounds);
extern void RC5_32_encrypt(RC5_32_INT *d, RC5_32_KEY *key);
extern void RC5_32_decrypt(RC5_32_INT *d, RC5_32_KEY *key);

class CEncrypt
{
public:
	CEncrypt();
	enum encMethod
	{
		ENCDEC_NONE,
		ENCDEC_RC5
	};
	void setEncMethod(encMethod method);
	void set_key_rc5(const unsigned char *data, int nLen, int rounds);
	int encdec(void *data, unsigned int nLen, bool enc);
private:
	RC5_32_KEY key_rc5;
	bool haveKey_rc5;
	encMethod method;
	unsigned int enc_mask;//需要加密的位置(默认都所有位置需要加密和解密,每比特标示需要加密8字节,依次循环)
	unsigned int dec_mask;//需要解密的位置(跟加密位置一致)
};


//加密解密封装源文件
CEncrypt::CEncrypt()
{
	bzero(&key_rc5, sizeof(key_rc5));
	haveKey_rc5 = false;
	method = ENCDEC_NONE;
	enc_mask = dec_mask = 0;
}

//设置加密方式
void CEncrypt::setEncMethod(encMethod m)
{
	method = m;
	enc_mask = dec_mask = RC5_32_MASK;//0xffffffffL
}
void CEncrypt::setEncMask(unsigned int m)
{
	enc_mask = m;
}


void CEncrypt::setDecMask(unsigned int m)
{
	dec_mask = m;
}
void CEncrypt::set_key_rc5(const unsigned char *data, int nLen, int rounds = RC5_8_ROUNDS)
{
	::RC5_32_set_key(&key_rc5, nLen, data, rounds);
	haveKey_rc5 = true;
} 
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
int CEncrypt::encdec_rc5(unsigned char *data, unsigned int nLen, bool enc)
{
	if (0==data) return -1;
	unsigned int offset = 0;
	while (offset<=nLen-8)
	{
		RC5_32_INT d[2];
		if (0x80000000 & (enc?enc_mask:dec_mask))
		{
			memcpy(d, data+offset, sizeof(d));
			if (enc)
				RC5_32_encrypt(d, &key_rc5);
			else
				RC5_32_decrypt(d, &key_rc5);
			memcpy(data+offset, d, sizeof(d));
		}
		offset += sizeof(d);//后移8字节
		if (enc)
			enc_mask = ROTATE_LEFT(enc_mask, 1);//循环左移
		else
			dec_mask = ROTATE_LEFT(dec_mask, 1);
	}
	return nLen-offset;
}


int CEncrypt::encdec(void *data, unsigned int nLen, bool enc)
{
	if (ENCDEC_NONE==method) return -1;
	if (ENCDEC_RC5==method) return encdec_rc5((unsigned char *)data, nLen, enc);
	return -2;
}



测试用例文件
int main()
{
	unsigned char key[16] = { 0x3f,0x79,0xd5,0xe2,0x4a,0x8c,0xb6,0xc1,0xaf,0x31,0x5e,0xc7,0xeb,0x9d,0x6e,0xcb};//加密密钥
	CEncrypt enc;	/**< 加密接口 */		
	enc.set_key_rc5((const unsigned char *)key, 16, 12);//加密密钥和轮数
	unsigned char toEncrypt[16] = {0};
	snprintf(toCEncrypt,sizeof(toCEncrypt),"123456789012345");//加密前
	printf("before Encrypt %s",toCEncrypt);
	enc.encdec(toEncrypt,sizeof(toEncrypt),true);//加密
	printf("after Encrypt %s",toCEncrypt);
	enc.encdec(toEncrypt,sizeof(toEncrypt),false);//解密
	printf("after decrypt %s",toCEncrypt);
	return 0;
}





版权声明:本文为博主原创文章,未经博主允许不得转载。

RC5分组密码算法

标签:

原文地址:http://blog.csdn.net/chenjiayi_yun/article/details/46840835

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!