RC5分组密码算法

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加密算法头文件

/*
 * rc5.h
 *
 *  Created on: 2015年12月28日
 *      Author: chen
 */

#ifndef RC5_H_
#define RC5_H_
#include <stdlib.h>
#include <stdio.h>
#include <string.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_H_ */

RC5 加密算法源文件

#include "rc5.h"

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];
}

加密解密封装头文件

/*
 * CEncrypt.h
 *
 *  Created on: 2015年12月28日
 *      Author: chen
 */

#ifndef CENCRYPT_H_
#define CENCRYPT_H_
#include "rc5.h"

//声明加密函数
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);
    void setEncMask(unsigned int m);
    void setDecMask(unsigned int m);
    int encdec_rc5(unsigned char *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;//需要解密的位置(跟加密位置一致)
};



#endif /* CENCRYPT_H_ */

加密解密封装源文件

/*
 * CEncrypt.cpp
 *
 *  Created on: 2015年12月28日
 *      Author: chen
 */
#include "CEncrypt.h"

//加密解密封装源文件
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 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;
}

测试用例文件

/*
 * testrc5.cpp
 *
 *  Created on: 2015年12月28日
 *      Author: chen
 */
#include "CEncrypt.h"



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.setEncMethod(CEncrypt::ENCDEC_RC5);
    enc.set_key_rc5((const unsigned char *)key, 16, 12);//加密密钥和轮数
    char toEncrypt[32] = {0};
    snprintf(toEncrypt,sizeof(toEncrypt),"123你好úù11\0\0\022");//加密前
    printf("before Encrypt %s strlen(%d)\n",toEncrypt,strlen(toEncrypt));
    int len = enc.encdec(toEncrypt,sizeof(toEncrypt),true);//加密
    printf("after Encrypt %s len(%d)\n",toEncrypt,len);
    len = enc.encdec(toEncrypt,sizeof(toEncrypt),false);//解密
    printf("after decrypt %s len(%d) strlen(%d)\n",toEncrypt,len,strlen(toEncrypt));
    if(toEncrypt[strlen(toEncrypt)] == '\0')
    printf("strlen(%d) strlen(%d) + 1 is zero");
    return 0;
}

点赞