
2.2 TDES算法
经过长期的实践应用,现在公认在安全性方面DES算法的唯一缺点是密钥太短,从而密钥空间太小,不能有效地对抗穷举攻击,特别是计算机高速发展的今天,56位长的密钥使得DES已经不具备保密性了。一种常用的扩展DES密钥的方法是使用3个DES的串联,如图2-7所示。

图2-7 TDES结构框图
图2-7(a)中使用了2个DES加密过程和1个DES解密过程,完成TDES加密,即
y=TDES(key1,key2,key3,x)=DES(key3,DES-1(key2,DES(key1,x))) (2-11)
图2-7(b)是TDES的解密过程,是图2-7(a)的逆过程,即
x=TDES-1(key1,key2,key3,y)=DES-1(key1,DES(key2,DES-1(key3,x))) (2-12)
图2-7的优势在于当key1=key2=key3=key时,相当于只使用一次DES,这样可以兼容使用DES算法的陈旧设备。由于图2-7中使用了3个DES,所以常被称为TDES(Triple DES)或3DES,或TDEA(Triple Data Encryption Algorithm),本书中使用TDES这一说法。
由图2-7可知,TDES具有3个56位的密钥,从而总的密钥长度达到168位,可以有效地对抗穷举攻击。
2.2.1 TDES图像密码系统
TDES的输入为64位(8B)的数据,输出也是64位(8B)的数据,数据间是按位异或(或称模2加)运算,特别适合于借助FPGA或ARM微处理器实现。TDES用于图像加密时,需要将图像分割为8B一组的小数据块序列,如果图像不能实现整数分割,即灰度图像的像素点个数除以8的商不是整数,则在最后一组填充0,以达到8B。一般地,常使用密码分组链接(CBC)方式对图像的各个小数据块进行加密,如图2-8所示。

图2-8 TDES工作在CBC模式下的灰度图像密码系统
参考图2-8(a),TDES工作在CBC模式下加密数字图像的步骤如下。
Step 1.设明文图像P的大小为M×N,不妨假设8能整除MN,令n=MN/8,将P逐行展开成一维行向量,然后,每8B一组,划分为n组,即{Pi,i=1,2,…,n}。
Step 2.按i取1,2,…,n依次对于Pi,经TDES加密后得到相应的密文块,记为Ci,即

其中,C0可取任意64位的公开的常数,这里取C0=0x0000000000000000。密钥key为168位,由图2-7中的key1、key2和key3组成。
Step 3.将{Ci,i=1,2,…,n}逐行填充为M×N的图像C,C为密文图像。
结合图2-8(b)可知,图像解密过程是加密过程的逆过程,可借助式(2-14)由Ci还原出Pi,即

C0=0x0000000000000000。
加密方通过“私有信道”与合法的收信方共享密钥key,而通过公共信道将C0和密文C传递到收信方,收信方借助密钥和解密算法即可还原原始图像。下面3个小节将依次使用MATLAB、C和C#编写TDES应用于灰度图像的加密算法,同时,考虑到DES的解密算法与加密算法相同(但子密钥输入顺序相反),为了节省篇幅,C语言工程和C#工程分别在MyCPFrame工程和MyCSFrame工程的基础上仅介绍新添加的代码。
2.2.2 TDES MATLAB程序
下面首先给出DES加密算法的MATLAB函数myDES.m和测试程序pc002.m。由于DES解密算法的MATLAB函数myDESinv.m是在myDES的基础上倒置16个子密钥的输入顺序得到的,故这里不再赘述其代码。
【程序2-1】 DES加密函数myDES.m。



程序2-1中,第3~26行用于产生子密钥,保存在二维数组K中,K的第i行对应子密钥Ki(图2-4),i=1,2,…,16。第28~53行为DES的加密过程。对于DES的解密函数myDESinv而言,除了将第41行改为[L,R]=myFeistel(L,R,K(16-i+1,:));外,其余代码与myDES完全相同。第54~116行为Feistel结构的实现函数。
【程序2-2】 DES测试程序pc002.m。

程序2-2中,第5~6行为64位的输入密钥key,第7~8行为64位的输入文本x。第10行显示原始的输入文本x(以十六进制方式),第12行调用myDES函数加密x得到密文y1,第13行将y1转化为十六进制形式y2,第14行输出y2;第16行调用myDESinv函数解密y1得到还原后的文本x1,第17行将x1转化为十六进制形式x2,第18行输出x2。
使用程序2-2测试的一组数组见表2-15。
表2-15 DES测试结果(十六进制形式)

备注:表2-15中的第2行测试文本引用自W.Stallings的Cryptography and Network Security:Principles and Practice,Sixth Edition。
在上述DES加密算法的基础上,下面结合第2.2.1节设计TDES图像加密算法的函数,如程序2-3所示。为了叙述方便,这里仅对256×256像素大小的灰度图像进行加密与解密处理,而对于像素点总个数不能被8整除的图像,需要对其进行像素点填补(例如,补255或补0等),使得填补后的图像像素点总个数能被8整除,然后才能进行TDES解密处理。
【程序2-3】 TDES图像加密算法myTDES.m。

程序2-3中,第2行获得明文图像P的大小,这里要求M×N能被8整除,然后,第3~ 8行将程序P按行展成一行,按8个像素点一组,分成M×N/8组,保存在二维数组x中。第9~16行按图2-8(a)所示方法加密x,得到密文分组C1。第17~22行将密文分组C1连接成一行,然后按行填充得到M行N列的矩阵C,C即所求的密文图像。
【程序2-4】 TDES图像解密算法myTDESinv.m。

程序2-4为TDES的图像解密算法,工作原理如图2-8(b)所示。
【程序2-5】 TDES加密与解密图像测试算法pc003.m。

程序2-5测试了Lena图像(第4行输入Lena图像),第7行调用myTDES得到图像P的密文图像C,第9~10行显示密文图像C,第12行调用myTDESinv解密密文图像C得到还原后的图像Pd,第14~15行显示还原后的图像Pd。
使用程序2-5测试了图1-1中的全部明文图像,为了节省篇幅,这里仅给出图1-1(a)、(e)、(f)的测试结果,如图2-9所示。图2-9中的密钥使用了key=[125,75,220,190,88,246,195,78];,即用该语句替换程序2-5中的第3行。测试全黑图像或全白图像时,使用P=zeros(256,256);或P=ones(256,256)∗255;替换程序2-5中的第4~5行。

图2-9 TDES加密与解密图像实例结果
图2-9(a)~(c)依次为Lena、全黑图像和全白图像的密文图像,图2-9(d)~(f)依次为解密图2-9(a)~(c)后的图像,与原始图像完全相同。在没有对MATLAB代码进行优化的条件下,MATLAB执行TDES加密256×256像素大小的灰度图像所需的时间约为7.5011s,解密相同大小的图像所需的时间约为8.5629s。需要特别说明的是,因为MATLAB代码是解释方式执行的,一般地,MATLAB下的加密与解密算法的执行时间仅用作算法复杂度的分析,加密与解密算法的执行速度需要借助C或C#语言程序评定。
2.2.3 TDES C程序
这里在第1.2.3节介绍的C工程myCPFrame基础上,修改main.c、algr.h和algr.c文件实现TDES加密与解密数字图像的功能,因此,下文仅给出main.c、algr.h和algr.c文件的C代码,并简要做了分析,供钟爱使用C语言研究密码学的读者参考。C语言是评价密码算法性能最好的语言之一。
【程序2-6】 algr.h头文件。

第7~8行依次声明了加密函数和解密函数,4个参数的含义分别为原始明文图像P/解密的图像R、密文图像C、加密或解密密钥K、图像的行数M和图像的列数N。
【程序2-7】 algr.c文件。




第131~182 行代码与第56~107 行代码完全相同。

第184~202 行代码与第109~127 行代码完全相同。

程序2-7中,第4~20行定义了S盒,变量名为S。第22~53行为Feistel结构的实现函数MyFeistel,输入为L1、R1和密钥key,输出为L2和R2,参考图2-4中的Feistel结构。第54~128行为DES加密算法的实现函数MyDES,输入为8个字节的文本x和8个字节的密钥key,输出为8个字节的密文y,具体算法请参考MATLAB函数myDES.m。第129~203行为DES解密算法的实现函数MyDESInv,除了第183行外,该函数的其余代码与MyDES完全相同。
第204~223行为DES加密图像的函数zyEnc,输入为明文图像P、密钥K、图像的行数M和列数N,输出为密文图像C。第225~250行为DES解密图像的函数zyDec,输入为密文图像C、密钥K、图像的行数M和列数N,输出为解密的图像R。
【程序2-8】 main.c文件。

程序2-8中,第4、5行宏定义图像的行数H和列数W均为256。第11行定义密钥K。第18行调用zyEnc函数加密图像P得到密文图像C;第24行调用zyDec函数解密密文图像C得到还原后的图像R。
借助上述代码测试了TDES加密与解密图像的速度,使用了第1章图1-1中的各个图像,加密与解密时间约相等,均约为0.297s。图像的加密与解密效果如图2-9所示。
2.2.4 TDES C#程序
在第1.2.4节的项目MyCSFrame基础上,添加一个新类MyTDES(文件MyTDES.cs),然后修改MainForm.cs文件,得到C#语言的TDES图像加密与解密算法工程。
【程序2-9】 MyTDES.cs文件。





第194~260行代码与上述的第101~167行代码完全相同。

第262~283行代码与上述的第169~190行代码完全相同。


程序2-9中,第8行定义图像的行数M和列数N,均为256。第9~25行定义S盒。第26~29行依次定义存放明文图像、密文图像、解密后的图像和密钥的数组plainImage、cipherImage、recoveredImage和key。
第31~36行为实例方法setPlainImage,从对象myImDat中获得明文图像,赋给成员plainImage。第37~42行为实例方法getCipherImage,将密文图像cipherImage赋给对象myImDat的成员CipherImage。第43~48行为方法getRecoveredImage,将解密后的图像recoveredImage赋给对象myImDat的成员RecoveredImage。
第49~53行为方法MyKeyGen,用该方法的形式参数设置密钥key。第54~98行为方法MyFeistel,实现Feistel结构的处理算法。第99~191行为方法MyDES,其3个参数分别表示输出的密文y、输入的明文x和密钥key。第192~284行为方法MyDESInv,为DES解密算法,输入为x和key,输出为y。
第285~308行为DES加密数字图像的方法MyEncrypt。第309~341行为DES解密数字图像的方法MyDecrypt。
【程序2-10】 MainForm.cs文件
第1~40行代码与第1章程序1-11中的第1~40行代码完全相同。

第42~53 行代码与第1 章程序1-11 中的第41~52 行代码完全相同。




程序2-10中,第41行定义MyTDES类的实例myTDES。第54~70行为组合选择框cmbBoxSelectMethod选项变化时触发的方法,如果选择了TDES(即第63行为真),则第65~68行使得文本框txtKey01~txtKey08可以输入文本(即只读属性关闭)。
第71~149行为btnEncrypt按钮的单击事件方法,如果组合选择框cmbBoxSelectMethod选择了TDES(即第101行为真),则第106~127行从文本框txtKey01~txtKey08中读出8个十六进制的数,赋给变量key。第128行将密钥key赋给对象myTDES中的私有成员变量(即程序2-9中第29行的key)。第129行将对象myImageData中的明文图像赋给对象myTDES中的私有成员变量(即程序2-9中第26行的plainImage)。第132行执行对象myTDES的方法MyEncrypt加密明文图像得到密文图像,密文图像保存在myTDES中的私有成员变量(即程序2-9中第27行的cipherImage)中。第130~131、133~135行用于统计并显示TDES加密图像的时间。第136~137行显示密文图像。
第150~197行为btnDecrypt按钮的单击事件方法,如果组合选择框cmbBoxSelectMethod选择了TDES(即第178行为真),则第185行由对象myTDES调用实例方法MyDecrypt执行TDES解密图像的算法,解密的图像保存在对象myTDES的私有数据成员(即程序2-9中第28行的recoveredImage)中。第183~184、186~188行统计TDES解密一幅图像所耗费的时间,单位为ms。第189~190行显示解密后的图像。
此时,项目MyCSFrame执行TDES的运行结果如图2-10所示。在图2-10中,选择了Pepper图像和TDES加密算法,密钥为0F 3C 18 9A 61 2E C7 B4(十六进制形式),密文图像与还原后的图像如图2-10所示,加密和解密时间分别约为0.722s和0.738s。

图2-10 项目MyCSFrame执行TDES的运行结果
表2-16列出了借助MATLAB、C语言和C#语言进行TDES加密/解密灰度数字图像(大小为256×256像素)所花费的时间。
表2-16 MATLAB、C和C#加密/解密时间对比结果(单位:s)

在表2-16中,由于C语言的执行时间的精度为0.001s,为了统一表示精度,所以MATLAB和C#的执行时间均保留了3位小数。从表2-16可以看出,C语言执行速度最快,C#语言次之,MATLAB较前两者慢了一个数量级。事实上,表2-16反映的三者加密/解密时间上的快慢关系具有普遍性意义。