本文主要是对《信息安全技术》的DES算法实验作业的一些总结,不会着重地介绍算法原理,而会在算法实现过程中给出自己的理解(因为有些部分我也不知道正确与否,如有错误请指教)。文章中出现的原理介绍和配图,均参考自其它博客,相关链接将在文中给出。
另外,文中的代码都是根据内容截取的,若想查看完整代码,请参考 DES - github
一、DES算法简介(参考自DES算法实例详解)
DES(Data Encryption Standard)是一种用于电子数据加密的对称密钥块加密算法。它以64bit一组的明文(Input)作为算法的输入,通过一系列复杂的操作,输出同样64bit长度的密文(Output)。DES 同样采用64位密钥(Key),但由于每8bit中的最后1位用于奇偶校验,实际有效密钥长度为56bit(Tips:输入的Key依然是64bit,只是在映射时不对每个字节最后1位进行处理,所以变为了56bit)。
DES 使用加密密钥定义变换过程,因此算法认为只有持有加密所用的密钥的用户才能解密密文。DES的两个重要的安全特性是混淆和扩散。其中混淆是指通过密码算法使明文和密文以及密钥的关系非常复杂,无法从数学上描述或者统计。扩散是指明文和密钥中的每一位信息的变动,都会影响到密文中许多位信息的变动,从而隐藏统计上的特性,增加密码的安全。

上图是DES算法的流程图。左侧是算法的工作流程,可以看到:
(1)用64bit的密钥Key产生16个48bit的子密钥;
(2)对输入的64bit明文先进行了Initial Permutation(IP初始置换);
(3)将64bit分为左右两部分(各32bit),用16个子密钥辅助进行16轮的F变换;
(4)两部分合成为64bit,进行Final Permutation(FP最终置换/逆置换)形成密文输出
而我们可以看到,在(3)中的16轮变换中,都需要右侧图中由密钥(Key)产生的子密钥(Sub-Key #i)。因此,我们可以首先来处理初始置换部分和子密钥算法部分。
二、算法准备
2.1、数据结构
首先要确定的是数据结构,即如何保存算法过程中出现的二进制、八进制和字符串数据?显然的,在C++中,我们可以全都用string来进行存储,但是对于算法中经常进行的异或操作,就不是很方便了。
对于整数和单个字符,我们的数据范围不会很大,不论是字符还是数字使用unsigned char即可。因此先定义类型:
typedef unsigned char Byte;
对于其它数据,我们使用string类型来保存这些数据。但是需要进行位操作时,我们就将这些数据转换为C++中bitset类型来保存。关于bitset类型的介绍可以参考博客C++ bitset 用法,这里不再赘述。但是有一点需要特别特别注意,使用索引index来获取数据时,是从低位开始的。也就是说,若有bitset<4> bs("0001"),那么bs[0]==1,bs[3]==0。
2.2、置换操作
在算法过程中,我们经常可以看到对位数据进行置换操作。那么到底置换操作是怎么进行的呢?
// 要特别注意的是bitset的index由0->size-1是从 低位->高位,即右边->左边
// 置换操作模板函数
template <typename Input, typename Output>
void DES_Permutation(const Input& input, Output& output
, const Byte Table[], const Byte tableSize)
{
for(Byte i = 0; i < tableSize; ++i)
output[tableSize - i - 1] = input[input.size() - Table[i]];
}
举一个简单的例子,