RC4 加密算法

目录

RC4

RC4 于 1987 年提出,和 DES 算法一样,是一种对称加密算法。但不同于 DES 的是,RC4 不是对明文进行分组处理,而是以字节流的方式依次加密明文中的每一个字节,解密的时候也是依次对密文中的每一个字节进行解密。

RC4 算法的特点是算法简单,运行速度快,而且密钥长度是可变的,可变范围为 1-256Byte(8-2048Bit),在如今技术支持的前提下,当密钥长度为 128Bit 时,暴力搜索密钥就不可行了。所以,RC4 的密钥范围任然可以在今后相当长的时间里抵御暴力搜索密钥的攻击。

在这里插入图片描述

RC4 的算法原理

基本概念

  • 密钥流:RC4 算法的关键是根据明文和密钥生成相应的密钥流,密钥流的长度和明文的长度是对应的,也就是说明文的长度是 500 字节,那么密钥流也是 500 字节。当然,加密生成的密文也是 500 字节,因为密文第 i 字节 = 明文第 i 字节 ^ 密钥流第 i 字节;

  • 状态向量 S:长度为 256Byte,S[0],S[1]…S[255]。每个单元都是一个 Byte,算法运行的任何时候,S 都包括 0-255 的 8Bit 的排列组合,只不过值的位置发生了变换;

  • 临时向量 T:长度也为 256Byte,每个单元也是一个 Byte。如果密钥的长度是 256Byte,就直接把密钥的值赋给 T,否则,轮转地将密钥的每个 Byte 赋给 T;

  • 密钥 K:长度为 1-256Byte,注意密钥的长度(keylen)与明文长度、密钥流的长度没有必然关系,通常密钥的长度为 16Byte(128Bit)。

加密原理

在这里插入图片描述

  1. 初始 S 和 T
    1. 先初始化状态向量 S(256 个字节,用来作为密钥流生成的种子 1):按照升序,给每个字节赋值 0,1,2,3,4,5,6…,254,255。
    2. 再初始化临时向量 T(初始密钥 K,由用户输入):长度任意,如果输入长度小于 256Byte,则进行轮转,直到填满。例如:输入密钥的是 1,2,3,4,5,那么填入的是 1,2,3,4,5,1,2,3,4,5,1,2,3,4,5…。由上述轮转过程得到 256 个字节的临时向量 T(用来作为密钥流生成的种子 2)
for i = 0 to 255 do
    S[i] = i;
    T[i] = K[imodkeylen];
  1. 初始置换 S:开始对状态向量 S 进行置换操作(用来打乱初始种子 1),按照下列规则进行,从第零个字节开始,执行 256 次,保证每个字节都得到处理这样处理后的状态向量 S 几乎是带有一定的随机性了。
j=0;

for i = 0 to 255 do
	j= (j + S[i] + T[i]) mod 256;
	swap(S[i], S[j]);
  1. 生成、加密秘钥流:假设明文字节数是 datalength=1024 个字节(当然可以是任意个字节),那么:
i=0;
j=0;

while(datalength--){            // 相当于执行 1024 次,这样生成的秘钥流也是 1024 个字节。
	i = (i + 1) mod 256;
	j = (j + S[i]) mod 256;
	swap(S[i] , S[j]);

	t = (S[i] + S[j]) mod 256;
	k = S[t];                   // 这里的 K 就是当前生成的一个秘钥流中的一位。

    // 可以直接在这里进行加密,当然也可以将密钥流保存在数组中,最后进行异或就可以了。
	data[] = data[]^k; //进行加密,"^" 是异或运算符。
}

C 程序实现示例

#include<stdio.h>
#include<string.h>

typedef unsigned longULONG;

/* 初始化算法(KSA)函数
 * 参数 1: 一个 256 长度的 char 型数组,定义为: unsigned char sBox[256];
 * 参数 2: 密钥,其内容可以随便定义:char key[256];
 * 参数 3: 密钥的长度,Len = strlen(key);
 */
void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len)
{
    int i = 0, j = 0;
    char k[256] = { 0 };
    unsigned char tmp = 0;
    for (i = 0; i < 256; i++)
    {
        s[i] = i;
        k[i] = key[i%Len];
    }
    for (i = 0; i < 256; i++)
    {
        j = (j + s[i] + k[i]) % 256;
        tmp = s[i];
        s[i] = s[j]; // 交换 s[i] 和 s[j]
        s[j] = tmp;
    }
}

/* 伪随机子密码生成算法(PRGA)函数完成加、解密。
 * 过程中,密钥的主要功能是将 S 搅乱,i 确保 S 的每个元素都得到处理,j 保证 S 的搅乱是随机的。
 * 由此,不同的 S 在经过 PRGA 处理后可以得到不同的子密钥序列,将 S 和明文进行 xor 运算,得到密文,解密过程也完全相同。
 * 参数 1:是上边 rc4_init 函数中,被搅乱的 S;
 * 参数 2:是需要加密的 Data 数据;
 * 参数 3:是 Data 的长度。
 */
void rc4_crypt(unsigned char* s, unsigned char* Data, unsigned long Len)
{
    int i = 0, j = 0, t = 0;
    unsigned long k = 0;
    unsigned char tmp;
    for (k = 0; k < Len; k++)
    {
        i = (i + 1) % 256;
        j = (j + s[i]) % 256;
        tmp = s[i];
        s[i] = s[j]; // 交换 s[x] 和 s[y]
        s[j] = tmp;
        t = (s[i] + s[j]) % 256;
        Data[k] ^= s[t];
    }
}

int main()
{
    unsigned char s[256] = { 0 }, s2[256] = { 0 };   // S
    char key[256] = { "justfortest" };
    char pData[512] = "这是一个用来加密的数据 Data";
    unsigned long len = strlen(pData);
    int i;

    printf("pData=%s\n", pData);
    printf("key=%s, length=%zu\n\n", key, strlen(key));

    rc4_init(s, (unsigned char*)key, strlen(key));   // 已经完成了初始化
    printf("完成对 S[i] 的初始化,如下:\n\n");
    for (i = 0; i<256; i++)
    {
        printf("%02X", s[i]);
        if (i && (i + 1) % 16 == 0)putchar('\n');
    }
    printf("\n\n");
    for (i = 0; i<256; i++)                          // 用 s2[i] 暂时保留经过初始化的 s[i],很重要!
    {
        s2[i] = s[i];
    }

    printf("已经初始化,现在加密: \n\n");
    rc4_crypt(s, (unsigned char*)pData, len);        // 加密
    printf("pData=%s\n\n", pData);

    printf("已经加密,现在解密: \n\n");
    rc4_crypt(s2, (unsigned char*)pData, len);       // 解密
    printf("pData=%s\n\n", pData);

    return 0;
}

执行:

$ gcc -Wall rc4.c -o rc4

$ ./rc4
pData=这是一个用来加密的数据 Data
key=justfortest, length=11

完成对 S[i] 的初始化,如下:

21E0944A8CAA5C851A95374358840E32
EE3AF7C8F67F898BFF52235F3B51CAE6
31E2A570C698C046CE836EB91EBC9235
FD6B1CB62C2D69B565631B933EA60762
13EAE7775BA159DD745491C181B7FB49
66037D2E47331538F8A820AE22D2345A
64FA3F87714DFCBF2490D32ADF9EB85E
0A2780E40CAD1497E3D8C7F2F4424176
DC8D45A9789DE1B0D9044F0F36C3C5BE
4C7AEB6C4B8640E59A7919B39BABAFE8
C4AC8EFE963CEDEF0B091202BAB1D001
CB60D4F91D557BCC7544D750F17E67C9
88DB111826F0B299B4BB482BA41FF58A
C2E9A0CF5DDA6FCD57003D0830A2A316
9F0D6AF36D682F8FBD28A7DE4ED15373
7C2956D51706058225EC617210399CD6


已经初始化,现在加密:

pData={�C��{T�4<���Zi̿+��ă�����XX�

已经加密,现在解密:

pData=这是一个用来加密的数据 Data
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付 49.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值