对称加密之流密码RC4

对称流式加密RC4算法

在前面文章中介绍了两种对称分组加密算法DES和AES,在本文将介绍另外一种对称加密方式——对称流式加密(流密码),和对称分组加密一样,流密码也是采用单密钥,但与分组加密不同,流式加密不是对明文分组后对每个分组进行同样的加密操作,而是根据密钥产生一个伪随机密码流,连续不断地对明文字节流进行处理,产生密文输出流。

一. 随机数和伪随机数介绍

在给多样的网络安全应用程序加密的过程中,随机数起了一个很重要的作用。而根据密码学原理,校验随机数的随机性有以下三个标准:

  1. 统计学伪随机性。统计学伪随机性指的是在给定的随机比特流样本中,1和0出现的频率必须大致相同;
  2. 密码学安全的伪随机性。即给定随机样本的一部分和随机算法,不能有效的演算出随机样本的剩余部分;
  3. 真随机性。其定义为随机样本不可重现。实际上只要给定边界条件,真随机数并不存在,可是如果产生一个真随机数样本的边界条件十分复杂且难以捕捉(比如计算机系统的瞬间系统时钟),可以认为用这个方法演算出来了真随机数。

相应的,随机数也分为以下三类:

  1. 伪随机数,满足上述第一个标准;
  2. 密码学安全的伪随机数,满足上述第1、2标准;
  3. 真随机数,同时满足上述三个标准。

实际上,用通俗易懂的方式解释真随机数(Random Number)和伪随机数(Pseudo Random Number)的本质区别就是,真随机数采用一个完全随机、不可复制的随机源作为输入端(熵源),比如计算机瞬时的电气特性、鼠标移动的坐标、计算机瞬间的系统时钟等,根据这个真随机输入端产生二进制数输出,这个过程是不可复现的(除非保留了这个熵源和输出产生规则)。而伪随机数采用一个事先约定的不变值作为输入端,这个不变值称为种子(在加密算法中即为密钥),按照确定的算法来产生一系列的被种子所决定的输出流,这个输出流在同时掌握种子和确定性算法的情况下可以被复现获得,而在没有种子的情况下,这个输出流“看起来”是随机的(Pseudo-randomness)。

Created with Raphaël 2.1.2 真随机源 转化为二进制 真随机比特流
图 1.1 真随机数发生器
Created with Raphaël 2.1.2 种子 确定性算法 伪随机比特流
图 1.2 伪随机数发生器

二. 流密码

在之前文章中讲到的分组密码每次使用相同的密钥按照相同的流程处理一个输入元素分组,并为每个输入分组产生一个输出分组。而流密码加密过程则是使用初始密钥产生一个伪随机的密码流,连续地处理输入元素序列(通常是用密码流和输入序列做异或运算),产生对应的连续输出序列(密文)。而解密过程则是采用和加密过程同样的伪随机流产生器算法对初始密钥产生一个相同的伪随机密码流,与密文序列做异或运算,得到明文序列。

流密码结构


图 2.1 流密码结构


伪随机字节产生器(PRNG)以初始密钥作为种子,输出不断重复的周期密钥流,这个重复的周期越长,密码破解就越困难。而PRNG采用的伪随机函数(PRF)产生的周期内密码流越“随机”,对应输出的密文流也就越随机化。因此 初始密钥的长度和PRF的合理设计是流密码加密安全性的关键。对于密钥长度,分组密码中考虑的因素在这里同样适用,在当前的科技水平下,流密码至少需要128位长度的密钥。

三. RC4算法

RC4算法是Ron Rivest在1987年设计的流密码,密钥长度可变,使用面向字节的操作。有分析指出,RC4算法的密码流周期完全可能大于 10 100

RC4算法非常简单,相当容易解释。256字节的状态向量S= {0,1,…,255},用比特字节表示为S= {00000000, 00000001, ….,11111111}。用一个可变长度为1~256字节(8~8048位)的密钥来初始化256字节的状态向量S={S[0], S[1], …, S[255]},任何时候,S都包含0~255的8位无符号数的排列组合。加密和解密时,密码流中的每一个字节k由S产生,通过系统的方式随机从S的256个元素中选取一个。每产生一个字节k,S的元素都要被再次排列。具体步骤如下。

步骤一、S向量原状态:

S = [ 0 , 1 , 2 , . . . , 255 ]

用二进制字节方式表示为:
S = [ 00000000 , 00000001 , . . . , 11111111 ]

步骤二、创建临时向量T(256位),如果密钥K的长度为256位,则直接将K赋给T,否则一直重复复制K,直到填满256位的向量T。对于keylen长度的密钥K,产生S向量和T向量的伪代码如下:

/*初始化T向量*/
for i = 0 to 255 do
    S[i] = i;
    T[i] = K[i mod keylen]

步骤三、接下来我们使用T向量来产生S的初始排列。这个过程从S[0]开始一直处理到S[255],同时对每个S[i],根据T[i指定的方案将S[i]与S的另一个元素进行交换:

/*S的初始排列*/
j = 0;
for i = 0 to 255 do
    j = (j + S[i] + T[i]) mod 256;
    Swap(S[i], S[j]);

由于上述过程对S的唯一操作就是元素交换,因此S仍然是包含0~255所有元素的排列组合。

步骤四、密码流产生。一旦S向量的初始排列完成后,密钥就不再被使用。接下来就是使用S自身来不断输出伪随机密码流的过程了。具体流程伪代码如下:

/*流产生*/
i,j = 0;
while (true)
    i = (i + 1) mod 256;  //i 不断从0~255循环
    j = (j + S[i] ) mod 256;
    Swap (S[i], S[j]);  //每产生一个k都重新排列S
    t = (S[i] + S[j]) mod 256;
    k = S[t];  //获取S中的一个随机元素作为密码流字节

步骤五、加密。将步骤四中获得的随机字节k与明文的下一字节做异或运算,产生的字节即为对应的密文字节。

解密过程:由于加密只是使用密码流对明文做了异或运算,因此解密过程只需要使用相同步骤产生密码流并对密文进行同样的异或运算即可得到加密前的明文。

RC4流程图


图 3.1 RC4算法密码流产生流程图


四. 流密码和分组密码对比


流密码的加密过程较之分组密码来说实在是简单太多,本文仅用寥寥一节就把RC4算法的具体流程介绍得十分详尽,由于算法实现的简单,甚至可以在文中直接给出算法的伪代码实现,其在加密效率上对分组密码的碾压优势可谓是不言而喻。事实上,RC4较之DES和三重DES的加密效率确实是高出了一个数量级,实践表明,在奔腾II机器上,这三者的加密效率对比如表4.1可见。

密码 密钥长度 加密速率(Mbps)
DES 56 9
3DES 168 3
RC4 可变 45


表 4.1 三种对称加密算法加密速率对比表


既然RC4算法的加密速率远高于经典的对称分组算法,那其安全性和强度是否满足加密需要呢?密码学领域已经发表过很多分析RC4攻击方法的文章,表明对于合理密钥长度(比如128位)的RC4,只要伪随机数产生器(PRNG)设计合理,对于同样的密钥长度,流密码和分组密码一样安全。因此 流密码的强度关键在于其采用的伪随机函数(PRF)

流密码在安全性强度上不逊分组密码,而加密速率又远优于后者,那是不是说明流密码可以完全取代分组密码呢?很可惜,答案是否定的。

在本文第一节提到,伪随机数字节流的产生依赖种子(密钥)和伪随机函数,而如果种子和伪随机函数不变的情况下,每次产生的伪随机数字节流都是一样的。如果每次都用同样的密钥作为PRF的输入,产生同样的密码流来与两个不同的明文流分别进行异或运算得到两个密文流,那么将这两个密文流进行异或,结果就是两个原始明文的异或值。如果明文是文本字符串或其他已知其性质的字节流,那么密码破解很可能会成功。因此,对于这些已知性质的字节流进行流密码加密,密钥就不能被重复使用了。在这一点上,分组密码的优点就体现出来了。

k e y b y t e s = P R F ( K )

c i p h e r t e x t 1 = p l a i n t e x t 1 k e y b y t e s

c i p h e r t e x t 2 = p l a i n t e x t 2 k e y b y t e s

c i p h e r t e x t 1 c i p h e r t e x t 2 = p l a i n t e x t 1 p l a i n t e x t 2

总结
对于需要加密/解密数据流的应用,比如在数据通信信道或浏览器/网络链路上,流密码可能是更好的选择。而对于处理数据分组的应用,比如文件传递、电子邮件,分组密码则更合适。

猜你喜欢

转载自blog.csdn.net/u012470144/article/details/81411565