DES
简介
DES加密是经典的基于Feistel网络结构的块加密,DES标准中字节的处理方式为大端序,DES接受一个64位(64bit)的明文和一个64位的key,返回64位的密文
在DES流程的开始,64位的key被传入PC1函数生成56位的真正密钥,因为原密钥中有8位是校验位
而这56位的密钥会再被拆分成左右两个各28位的密钥
1 | pair<uint32_t, uint32_t> PC1(uint64_t key) |
两个28位密钥分别左旋特定位数后进入PC2用于生成16个48位子密钥,PC2中有一个盒用于决定选择哪48位来作为密钥
1 | void keyGen(pair<uint32_t, uint32_t> keyPair) |
至此为止密钥全部准备完毕,明文被分为左右各32位进入Feistel网络循环流程
1 | void desEncrypt(uint64_t *plain, uint64_t key) |
明文在进入和结束加密时还要经历IP,FP两次置换,这两次置换只是简单映射
1 | uint64_t IP(uint64_t messagge) |
Feistel轮函数如下所示
1 | uint32_t feistel(uint32_t a, uint64_t key) |
数据先经过E盒拓展为48位后与48位密钥异或,然后进入S盒重新映射为32位,最后由P盒再进行一轮置换后输出
1 | uint64_t expand(uint32_t a) |
S盒有8个,每个S盒是一个4*16的结构,48位的输出被分为8个6位的块分别进入对应的S盒,每块的第1和第6个位用于索引行(0x00 ~ 0x11),其余四位用于索引列(0x0000 ~ 0x1111),S盒中的数都是4位的,最后合起来得到一个32位的输出
1 | uint64_t S(uint64_t a) |
P置换就是再次打乱S盒的输出
1 | uint32_t P(uint64_t a) |
至此DES的流程全部结束,按照图例的话如下图所示
特征
因为DES的代码过于庞大,且涉及大量位操作,在反编译器中观察DES的特征非常困难,但是DES有非常多的盒,其中部分盒是精心设计的,修改这部分盒会严重影响DES在对抗暴力破解时的安全性,所以我们可以通过这些一般不会修改的盒识别DES
S盒
S盒引入了非线性操作,且S盒的每一位都设计过用以抵抗差分和线性密码分析,一般不会修改S盒
1 | uint8_t S_box[8][64] = |
P盒
P盒的特殊设计使得每一轮由同一个S盒输出的4个bit在下一轮都被分散到另外4个不同S盒中进行处理(增强扩散性)
1 | uint8_t p[] = |
E盒
E盒负责将32位的输入扩展到48位,对混淆能力由很大影响
1 | uint8_t e[] = |
实现
考虑到DES现在已经被证明不安全,且其加密过程严重依赖系统端序,DES标准为大端序,而现代计算机大多数为小端序,故不给出完整实现,如果遇到需要手动解密的DES,只需要根据Feistel网络的性质,将16个子密钥倒着使用即可解密