流加密又称序列加密,是对称加密算法的一种,加密和解密双方使用相同伪随机数据流(Pseudo-Randomstream)作为密钥(因此这个密钥也称为伪随机密钥流,简称密钥流),明文数据每次与密钥数据流顺次对应加密,得到密文数据流。实践中,数据通常是一个位(Bit)并用异或(XOR)操作加密。
最早出现的类流密码形式是Veram密码。直到1949年,信息论创始人Shannon发表的两篇划时代论文《通信的数学理论》和《保密系统的信息理论》证明了只有“一次一密”的密码体制才是理论上不可破译的、绝对安全的,由此奠定了流密码技术的发展基石。流密码长度可灵活变化,且具有运算速度快、密文传输中没有差错或只有有限的错误传播等优点。目前,流密码成为国际密码应用的主流,而基于伪随机序列的流密码成为当今通用的密码系统,流密码的算法也成为各种系统广泛采用的加密算法。目前,比较常见的流密码加密算法包括RC4算法、B-M算法、A5算法、SEAL算法等。
在流加密中,密钥的长度和明文的长度是一致的。假设明文的长度是n比特,那么密钥也为n比特。流密码的关键技术在于设计一个良好的密钥流生成器,即由种子密钥通过密钥流生成器生成伪随机流,通信双方交换种子密钥即可(已拥有相同的密钥流生成器),具体如图3-2所示。
图3-2
伪随机密钥流(Pseudo-Random-Keystream)由一个随机的种子(Seed)通过算法PRG(Pseudo-Random Generator)得到,若k作为种子,则G(k)作为实际使用的密钥进行加密解密工作。为了保证流加密的安全性,PRG必须是不可预测的。
设计流密码的一个重要目标就是设计密钥流生成器,使得密钥流生成器输出的密钥流具有类似“掷骰子”一样的完全随机特性。但实际上密钥流不可能是完全随机的,通常从周期性、随机统计性和不可预测性等角度来衡量一个密钥流的安全性。
鉴于流密码在军事和外交保密通信中有重要价值,因此流密码算法多关系到国家的安全,而作为各国核心部门使用的流密码,都是在各国封闭地进行算法的标准化的,规范化情况都不公开,所以各国政府基本都把流密码算法的出口作为军事产品的出口加以限制。允许出口的加密产品对其他国家来说已不再安全。这使得学术界对于流密码的研究成果远远落后于各个政府的密码机构,从而限制了流密码技术的发展速度。幸运的是,虽然目前还没有制定流密码的标准,但是流密码的标准化、规范化、芯片化问题已经引起政府和密码学家的高度重视,并开始着手改善这个问题,以便能为赢得高技术条件下的竞争提供信息安全保障。像目前公开的对称算法更多的是分组算法,比如SM1和SM4等。
在通常的流密码中,解密用的密钥序列是由密钥流生成器用确定性算法产生的,因而密钥流序列可认为是伪随机序列。
流密码算法的优点主要有:
(1)流密码的加密和解密每次都是以Bit或Byte为单位进行处理的,更符合硬件上的实现。
(2)流密码较难受到密码分析的影响,因为它每一个单位加密时使用的密钥都是不同的。
(3)流密码所用密钥的产生独立于信息流。
(4)硬件实现电路更简单。
(5)对于字符数据的处理都是实时的。
(6)转换速度快,低错误传播。
流密码算法的缺点主要有:
(1)某一比特发生错误时会影响到其他比特。
(2)不太适用于软件。
(3)低扩散、插入、删除的不敏感性。
分组密码算法的优点主要有:
(1)可以重复使用密钥。
(2)在某些工作模式下,如果某个块的处理发生了错误,并不会影响之后的块的运算。(3)分组密码在软件上更容易实现,即容易被移植,成本也较低。
(4)在现实生活中,分组密码更常见,它有4种工作模式,包括ECB模式、CBC模式、OFB模式、CFB模式。
(5)易于标准化,当今信息大多是按块进行传输处理的。
(6)扩散性好,插入敏感。
分组密码算法的缺点主要有:
(1)相同的明文产生相同的密文。
(2)加解密处理速度慢。
(3)分组加密更容易受到密码分析的影响。
(4)存在错误传播。
RC4算法是著名的流加密算法。RC4算法是大名鼎鼎的RSA三人组中的头号人物Ron Rivest在1987年设计的一种流密码。当时,该算法作为RSA公司的商业机密并没有公开,直到1994年9月,RC4算法才通过Cypherpunks置名邮件列表匿名地公开在Internet上。泄露出来的RC4算法通常称为ARC4(Assumed RC4),虽然它的功能经证实等价于RC4,但RSA从未正式承认泄露的算法就是RC4。目前,真正的RC4要求从RSA购买许可证,但基于开放源代码的RC4产品使用的是当初泄露的ARC4算法。它是以字节流的方式依次加密明文中的每个字节。解密的时候也是依次对密文中的每个字节进行解密。
RC4算法的特点是算法简单、执行速度快。RC4算法的密钥长度是可变的,可变范围为1~256字节(8~2048比特),在现在技术支持的前提下,当密钥长度为128比特时,用暴力法搜索密钥已经比较吃力了,所以能够预见RC4的密钥范围依然能够在今后相当长的时间里抵御暴力搜索密钥的攻击。实际上,现在也没有找到对于128比特密钥长度的RC4加密算法的有效攻击方法。
由于RC4算法具有良好的随机性和抵抗各种分析的能力,该算法在众多领域的安全模块得到了广泛的应用。在国际著名的安全协议标准SSL/TLS(安全套接字协议/传输层安全协议)中,利用RC4算法保护互联网传输中的保密性。在作为IEEE802.11无线局域网标准的WEP协议中,利用RC4算法进行数据间的加密。同时,RC4算法也被集成于Microsoft Windows、Lotus Notes、Apple AOCE、Oracle Secure SQL、Adobe Acrobat等应用软件中,还包括TLS(传输层协议),其他很多应用领域也使用该算法。
RC4算法主要有两个特点:
(1)算法简洁,易于软件实现,加密速度快,安全性比较高。
(2)密钥流长度可变,一般用256个字节。
前面提过,流密码就是使用较短的一串数字(称为密钥)来生成无限长的伪随机密钥流(事实上只需要生成和明文长度一样的密码流就够了),然后将密钥流和明文异或就得到密文了,解密就是将这个密钥流和密文进行异或。
用较短的密钥产生无限长的密码流的方法非常多,其中有一种就叫作RC4。RC4是面向字节的序列密码算法,一个明文的字节(8比特)与一个密钥的字节进行异或就生成了一个密文的字节。
RC4算法中的密钥长度为1~256字节。注意,密钥的长度与明文长度、密钥流的长度没有必然关系。通常密钥的长度取16字节(128比特)。
RC4算法的关键是依据密钥生成相应的密钥流,密钥流的长度和明文的长度是相应的。也就是说,假如明文的长度是500字节,那么密钥流也是500字节。当然,加密生成的密文也是500字节。密文第i字节=明文第i字节^密钥流第i字节,^是异或的意思。RC4用三步来生成密钥流:
第一步,初始化向量S,S也称S盒,也就是一个数组S[256]。指定一个短的密钥,存储在key[MAX]数组里,令S[i]=i。
第二步,排列S盒。利用密钥数组key来对数组S进行置换,也就是对S数组里的数重新排列,排列算法的伪代码为:
第三步,产生密钥流。利用上面重新排列的数组S来产生任意长度的密钥流,算法为:
一次产生一字符长度(8 Bit)的密钥流数据,一直循环,直到密码流和明文长度一样为止。数组S通常称为状态向量,长度为256,其每一个单元都是一个字节。元论算法执行到什么时候,S都包含0~255的8比特数的排列组合,仅仅只是值的位置发生了变换。
产生密钥流之后,对信息进行加密和解密就只是做一个异或运算。
我们将分别用C语言、C++语言和OpenSSL库来实现RC4算法。
【例3.1】RC4算法的实现(C语言版)
(1)打开VC 2017,新建一个控制面板工程,工程名是test。
(2)在工程中打开test.cpp,并输入代码如下:
(3)保存工程,如果在VC中直接运行工程,就要把“明文.txt”新建在工程目录下,如果是在解决方案的Debug目录下直接运行可执行程序,就要在解决方案的Debug目录下新建一个“明文.txt”文件。运行结果如图3-3所示。
图3-3
下面再来看一个C++版本的,稍微不同的是密钥key是程序随机生成的,然后把生成的密钥流保存在文件中,以供解密时使用,这样加密和解密就可以使用同一个密钥流了。
【例3.2】RC4算法的实现(C++版)
(1)打开VC 2017,新建一个控制面板工程,工程名是test。
(2)在工程中新建一个rc4.h文件,该文件定义RC4算法的加密类和解密类,输入代码如下:
再在工程中新建一个rc4.cpp文件,然后输入代码如下:
类RC4Enc的成员函数encryption用于RC4的加密,加密时需要一个文本文件作为数据源的输入,生成的密钥流和密文都会存放在文件中。类RC4Dec的成员函数decryption用于RC4的解密,解密时会把生成的解密后的明文保存在文件中。
至此,RC4算法的加密和解密类实现完毕。下面开始使用该类。
(3)在文件test.cpp输入代码如下:
注意要在文件开头包含头文件rc4.h。在main函数中,我们定义了加密类RC4Enc的对象rc4enc,解密类RC4Dec的对象rc4dec。另外,运行程序前,需要在工程目录下新建文本文件“明文.txt”,可以随便输入一些文本数据。
(4)保存工程,如果在VC中直接运行工程,就要把“明文.txt”新建在工程目录下,如果是在解决方案的Debug目录下直接运行可执行程序,就要在解决方案的Debug目录下新建一个“明文.txt”文件。运行结果如图3-4所示。
图3-4
值得注意的是,密钥流.txt和密文.txt都是二进制文件,直接打开都是乱码的,如果要查看详细数据,可以使用UltraEdit等专业文本工具查看,这类工具有二进制查看方式。比如明文的内容是:“伟大的中国!”,密文的内容如图3-5所示。
图3-5
上面我们亲自实现了RC4算法,但在实际开发中,有时候没必要重复造轮子,因为已经有现成的轮子可供使用,比如OpenSSL库里提供了RC4算法的调用。通过OpenSSL来使用RC4算法非常简单,通常有以下几步:
(1)定义密钥流结构体RC4_KEY。
(2)生成密钥流。
通过函数RC4_set_key来生成密钥流,函数RC4_set_key声明如下:
void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data);
其中,key是输出参数,用来保存生成的密钥流;len是输入参数,表示data的长度;data是输入参数,表示用户设置的密钥。
(3)加密或解密。
通过函数RC4来实现加密或解密,该函数声明如下:
void RC4(RC4_KEY *key, unsigned long len, const unsigned char *indata,unsigned char *outdata);
其中,输入参数key表示密钥流;输入参数len表示indata的长度;输入参数indata表示输入的数据,当加密时,表示明文数据,当解密时,表示密文数据;输出参数outdata存放加密或解密的结果。
【例3.3】RC4算法的实现(OpenSSL版)
(1)打开VC 2017,新建一个控制面板工程,工程名是test。
(2)打开工程属性,在“C/C++”→“附加包含目录”旁输入头文件路径:D:\openssl-1.1.1b\win32-debug\include,然后在“链接器”→“常规”→“附加库目录”旁输入静态库路径:D:\openssl-1.1.1b\win32-debug\lib,再在“链接器”→“输入”→“附加依赖项”旁增加3个库名:ws2_32.lib;Crypt32.lib;libcrypto.lib;,注意每个库名之间用英文分号隔开。单击“确定”按钮关闭对话框。
(3)下面开始添加代码,在工程中打开test.cpp,输入代码如下:
(4)保存工程并运行,运行结果如图3-6所示。
图3-6