標籤:
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_ENCRYPT1#define RC5_DECRYPT0/* 32 bit. For Alpha, things may get weird */#define RC5_32_INT unsigned int#define RC5_32_BLOCK8#define RC5_32_KEY_LENGTH16 /* 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_ROUNDS8#define RC5_12_ROUNDS12#define RC5_16_ROUNDS16typedef 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_MASK0xffffffffL#define RC5_16_P0xB7E1#define RC5_16_Q0x9E37#define RC5_32_P0xB7E15163L#define RC5_32_Q0x9E3779B9L#define RC5_64_P0xB7E151628AED2A6BLL#define RC5_64_Q0x9E3779B97F4A7C15LL#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);elseRC5_32_decrypt(d, &key_rc5);memcpy(data+offset, d, sizeof(d));}offset += sizeof(d);//後移8位元組if (enc)enc_mask = ROTATE_LEFT(enc_mask, 1);//迴圈左移elsedec_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分組密碼演算法