RC4 加密算法

算法简介

RC4 算法也称为 “Rivest Cipher 4”, 是使用最广泛的流加密之一。
它以字节流的方式依次对明文、密文进行加密、解密。
它的特点就是算法简单,运行速度快,且密钥长度可变(256 byte 内)

加密原理

加密原理如下图所示:
rc4加密原理
由于异或运算的特性,所以RC4加密解密使用同一套算法

加密过程

第一步: 先初始化状态向量 S,S 为 256 个字节,用来作为密钥流生成的种子,按照升序,给每个字节从 0 开始赋值,一直到 255。

extern uint8_t S[256];

// 初始化向量S
for (i = 0; i < 256; i++)
{
	S[i] = i;
}

第二步: 定义临时向量 T,T 为 256 字节, 初始密钥由用户输入,长度任意(不得高于256个字节),把密钥赋值给 T, 如果密钥不足 256 字节,则将其进行轮转,直到填满 T 向量。

extern uint8_t T[256];

// 轮转密钥赋值给 T
for (int i = 0; i < 256; i++)
{
	T[i] = K[i % K_len]
}

第三步: 对向量 S 进行置换操作,用来打乱初始种子,置换规则如下:

int j = 0;
for (int i = 0 ; i < 256 ; i++)
{
    j = (j + S[i] + T[i]) %256;
    swap(S[i] , S[j]);
}

第四步: 生成加密、解密的密钥流

i , j = 0;

for (int l = 0; l < data_len; l++)
{
    i = (i + 1) %256;
    j = (j + S[i]) %256;
    swap(S[i] , S[j]);
    
    // 这里 k 则是当前密钥流中的一位,数据与其进行异或
    t = (S[i] + S[j]) %256;
    k = S[t];
	
	// 对相应下标的数据进行异或,则完成一个字节的加、解密
	data[l] = data[l]^k;
}

代码实现(C语言)

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


typedef struct
{
	uint8_t	i;
	uint8_t	j;
	uint8_t S[256];
}rc4_ctx;


void rc4_init(rc4_ctx* ctx, uint8_t* key, uint32_t keylen)
{
	uint32_t i;
	uint32_t j;
	uint8_t T[256];
	uint8_t tmp;

	//初始化向量 S 和 向量 T
	for (i = 0; i < 256; i++)
	{
		ctx->S[i] = i;
		T[i] = key[i % keylen];
	}


	for (i = 0, j = 0; i < 256; i++)
	{
		// i 从 0 开始一直到255下标结束. j 是 S[i] 与 T[i] 组合得出的下标
		j = (j + ctx->S[i] + T[i]) % 256;

		// 交换 S[i] 与 S[j]
		tmp = ctx->S[i];
		ctx->S[i] = ctx->S[j];
		ctx->S[j] = tmp;
	}

	ctx->i = 0;
	ctx->j = 0;
}

// 因为 rc4 加密是取当前下标的一个字节与密钥流中的一位进行异或的,每次修改到的只会是当前下标所指向的一个字节
// 所以这里的输入 in 和 输出 out 可以是一个缓冲区,当然也可以是不同的缓冲区
void rc4_crypt(rc4_ctx* ctx, uint8_t* in, uint32_t inlen, uint8_t* out)
{
	uint32_t i = 0;
	uint32_t v = 0;
	uint8_t tmp;

	for (i = 0; i < inlen; i++)
	{
		// i 确保 S 中的每个元素都得到处理, j 确保 S 的搅乱是随机的
		ctx->i = (ctx->i + 1) % 256;
		ctx->j = (ctx->j + ctx->S[ctx->i]) % 256;

		// 交换 S[i] 与 S[j]
		tmp = ctx->S[ctx->i];
		ctx->S[ctx->i] = ctx->S[ctx->j];
		ctx->S[ctx->j] = tmp;

		// 交换完之后 再把 S[i] + S[j] 的组合当做下标再去异或.
		v = (ctx->S[ctx->i] + ctx->S[ctx->j]) % 256;
		v = ctx->S[v];

		out[i] = in[i] ^ v;
	}
}

int main()
{
	// 分别定义加密、解密的密钥流
	rc4_ctx rc4_encrypt;
	rc4_ctx rc4_dectypt;

	// 定义 key
	uint8_t * key = (uint8_t*)"abcd1234.";

	// 定义要解密的数据
	char buff1[] = "Hello World";
	char buff2[] = "你好 世界";

	// 分别对其进行初始化
	rc4_init(&rc4_encrypt, key, strlen((char *)key));
	rc4_init(&rc4_dectypt, key, strlen((char *)key));

	// 加密
	rc4_crypt(&rc4_encrypt, (uint8_t *)buff1, strlen(buff1), (uint8_t *)buff1);
	printf("Hello World 加密后 ===> %s\n", buff1);

	// 解密
	rc4_crypt(&rc4_dectypt, (uint8_t*)buff1, strlen(buff1), (uint8_t*)buff1);
	printf("Hello World 解密后 ===> %s\n", buff1);

	// 加密
	rc4_crypt(&rc4_encrypt, (uint8_t*)buff2, strlen(buff2), (uint8_t*)buff2);
	printf("你好 世界 加密后 ===> %s\n", buff2);

	// 解密
	rc4_crypt(&rc4_dectypt, (uint8_t*)buff2, strlen(buff2), (uint8_t*)buff2);
	printf("你好 世界 解密后 ===> %s\n", buff2);

	return 0;
}

代码的执行结果如下:

Hello World 加密后 ===> y鴽Z泆}塛?
Hello World 解密后 ===> Hello World
你好 世界 加密后 ===> 鋁鎎G屭]b
你好 世界 解密后 ===> 你好 世界
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值