0x00写在前面
没有根基也许可以建一座小屋,但绝对不能造一座坚固的大厦
0x01现代对称密码设计
重点是对密钥的理解:密钥是加密算法的输入,但是独立于明文和算法。算法根据所用的特定的密钥产生不同的输出。算法使用的确切代替和变换也依赖于密钥。
对称密码首要的安全问题是:密钥的保密性。
0x02分组密码结构
分组密码是将明文分组作为整体加密,并且通常得到与明文等长的密文分组。典型的分组大小是64位或者128位。分组密码属于对称密码体制。
与分组密码相对应的还有流密码,但是流密码的应用远没有分组密码广泛,绝大部分基于网络的对称密码应用的是分组密码。
数学描述:
①将明文消息编码表示后的序列:$x0,x_1,\dots,x_i,\dots 划分成长为n位的组 (x_0,x_1,\dots,x{n-1})$ (长为n的矢量)
②各组分别在密钥空间 $K=(k0,k_1,\dots,k{t-1})
③加密算法
若
通常我们取
👉
✍特点:同一密钥、加密算法,分组加密,分组长度固定
1945年,
👋混淆:使密文与密钥之间的关系变得复杂。eg:DES中的S盒
👋扩散:密钥或明文的一个位变化要引起密文许多位的变化;密文每个位受多个明文位影响,可以使明文的统计特征消散在密文中,也可以引起雪崩效应(明文一个位变化引起密文多个位变化,且变化位未知)。对扩散的实现,一般采用线性变换、置换、循环移位等手段。
0x03Feistel密码结构
首先,记住这样一个事实:基于1945年的
乘积密码:依次使用两个或两个以上基本密码进行多次迭代,所得结果的密码强度将强于所有单个密码的强度。多次迭代可以大大增强混淆和扩散的强度,使密文、明文、密钥之间的关系异常复杂,以至于攻击者极其难以分析。
数学描述:
乘积密码通过交替使用代替(Substitution)和置换(Permutation)来实现混淆和扩散:
👋代替:每个明文元素或元素组被唯一替换为相应的密文元素或元素组。
👋置换:明文元素的序列被替换为该序列的一个置换。(置换:序列中元素出现的顺序改变,没有元素的增减)
✍分组长度:分组越长
✍密钥长度:密钥越长
✍迭代轮数:
✍子密钥产生算法:产生越复杂,密码分析越难。
✍轮函数:越复杂抗攻击越强。
0x04DES算法
(Ⅰ)总览
DES(Data Encryption Standard)是在
DES算法分为两大部分:迭代加密(左侧16轮迭代操作)、密钥调度(右侧生成子密钥的算法)。
密钥调度:从一把64-bit的主钥匙得到16把48-bit的子钥匙,然后把这些子钥匙用于迭代加密。
得到子钥匙:
1.从64-bit的主钥匙选特定的56位,其余位没有用,将这56位分成左右两个半密钥,都是28-bit的数组。
2.左右两个半密钥都循环左移一定位数,有些轮是1位,有些是2位。
3.把左右半密钥拼起来,再做一次置换,就得到了这一轮生成的子密钥。这个置换是从56-bit的数组里面选取指定的48位。所以每一轮都可以生成一个48位的子密钥。
4.重复2、3共16次即可。
迭代加密:
1.输入64位明文(长度为64位的布尔数组)做IP置换,仍然是64-bit数组
2.拆成左右各32位
3.每一轮迭代,都是接收一组
其中
4.用之前的16个子密钥执行步骤3共16次
5.将步骤4得到的
DES算法加密解密过程几乎一致,唯一不同的是解密时子密钥使用顺序,是和加密过程使用子密钥相反的。
注✍IP 和 FP 其实只是一个标准而已,与安全性完全无关,因为 IP 和 FP 是完全公开的,大家都能做,所以这个步骤其实大可删了。比如 SM4 其实就没有这一步。
(Ⅱ)编码与加密
编码(encode)与加密(encrypt)都是把一条数据变成另一条数据的函数,但是有本质上的区别:
编码是公开的,是双向函数,比如:base64编码等
加密是私密的,必须有密钥才能加密或解密。
(Ⅲ)密钥调度算法
首先,是PC1置换,从64bit选出56位,这一步是
1 | # PC1,输入key,长度为64位的 0/1数组 |
现在我们有两个28位的半密钥了,下面我们每一轮要把左、右半密钥循环左移,然后调用PC2方法来制造子密钥,框架如下:
1 | def KeyGen(key): |
leftRotate
是循环左移:
1 | def leftRotate(a,off): |
PC2
是置换,将从左右半密钥拼起来的56位密钥中选48位作为一个子密钥:
1 | # PC2,输入56位的Key |
✍补充python
中的assert
(断言):
写python
代码使用assert
是一个好习惯,用于判断一个表达式,在表达式条件为 false
的时候触发异常,条件为true
时正常执行后面的代码。
语法如下:
1 | assert exp |
含有参数的情况:
1 | assert exp [, arguments] |
到现在,我们就完成了密钥调度的部分。
(Ⅳ)加密迭代
首先,把明文进行IP
置换,下一步进行16轮迭代,然后得到R+L
并FP
置换,输出密文,框架如下:
1 | def DES(plain,key,method): |
对于IP
和FP
这两个置换函数,这二者只是简单置换,对于安全没有任何意义,只是历史遗留原因,规定如下:
1 | # 初始置换 |
✍注意:FP
就是IP
的逆函数
对于goRound
每一轮要做的事情,我们知道是:
1 | def goRound(l,r,subKey): |
对于Feitel
函数(轮函数):
轮函数本质是一个PRF(伪随机函数),它的目的就是根据输入生成一个随机程度很高的比特串,将这个比特串异或到另一个比特串上就实现了加密。
轮函数有4个过程:明文扩展、轮密钥异或、S 盒和 P 盒。
一个32bit的块,经过Expand
函数变成48位,然后与子密钥异或,得到的48位结果分为8组,每一组是6位,丢进对应的S盒,输出4bit的信息,把这些信息收集起来一共是32位,做一次P置换,得到此轮32bit的结果:
1 | def Feistel(a, subKey): |
Expand
算法是指定的:
1 | # 扩张置换,将32位的数据扩展到48位 |
P置换:
1 | # P置换 |
S盒:在分组密码结构中,是唯一的非线性结构,一共有8张表,我们之前分完的8组分别使用
1 | # S盒变换,输入48位,输出32位 |
(Ⅴ)完整加密解密代码
1 | from functools import reduce |
0x05DES差分攻击
(Ⅰ)总览
数学中把一个数列
密码学中的差分运算实质上是两个01比特串之间做异或操作。
DES的核心是
于是我们可以绕过密钥随机性的影响,直接得到S盒的差分,但是要注意:差分攻击是选择明文攻击,也就是要用待破解的算法加密任意字节,并得到加密结果,才能实现攻击。
(Ⅱ)差分密码分析
差分密码分析(
最基本的差分密码分析密钥破解形式中,攻击者首先获取大量明文对的密文,并假设差分在至少
自从差分密码分析进入公众视野,其就成了加密设计者的基本考量。新的加密设计通常需要举证其算法可以抗此类攻击。包括AES在内的许多算法都被证明在差分分析攻击下是安全的。
(Ⅲ)攻击细则
攻击主要依赖于一点:给定输入/输出,差异特征仅在特定输入下出现。这种方法通常用于线性结构组成的加密方式,如S盒。给定两个已知密文或明文后,观察其输出差异可猜测密钥的可能值。
(Ⅳ)差分攻击一些定义
①差分值(difference)
设 $X,X^ \in {0,1}^n
②差分对(differential)
设
③差分特征
迭代分组密码的一条
差分特征也称差分路径,它与差分对的区别在于差分对只规定了输入和输出差分,而差分路径则指定了中间状态的差分值。
④差分概率
迭代分组密码的一条
⑤差分特征概率
迭代分组密码的一条
当
⑥正确对与错误对
给定一条差分特征
⑦差分区别器
对于
如果找到了一条
⑧异或运算的差分性质
假设
$\Delta z = \Delta (x \oplus y) = (x\oplus y)\oplus (x^ \oplus y^)=(x \oplus x^) \oplus (y \oplus y^)=\Delta x \oplus \Delta y$
注👋差分密码相关英文文献中,
(Ⅴ)S盒差分攻击模型
DES 能够使用差分攻击的原因在于 S 盒的差分分布具有不均匀性。也就是说对于相同的输入差分,不同的输入对应着不同的输出差分(👋注意区分输入和输入差分)。
我们记输入差分为
其中
我们随意选取一个输入差分
(Ⅵ)5轮DES差分攻击分析
需要选取合适的输入差分,就有办法求出最后一个 S 盒的输出差分。
注👋此处的差分是
现在取差分对
其中:
我们看到,输入差分仅有 1 个比特为 1 ,在第 3 轮时差异还没有完全扩散开。只需要对第 3 轮
下面是DES差分攻击最精彩的地方,我们写出最后一轮
展开:
由于 P 盒也是一个一一置换,所以如果 P 盒的输入差分为 0 (输入没有区别),那么输出差分也为 0 (输出也没有区别)。那么有
然后我们对
1 | graph LR |
对于P盒,它仅仅替换字节的顺序,有
到此,我们求出了第1个和第7个S盒的输出差分;S盒的输入差分就是
0x06python代码细节补充
reduce()
在 python 2 是内置函数, 从python 3 开始移到了 functools 模块。
reduce的工作过程是 :在迭代序列的过程中,首先把 前两个元素(只能两个)传给 函数,函数加工后,然后把 得到的结果和第三个元素 作为两个参数传给函数参数, 函数加工后得到的结果又和第四个元素 作为两个参数传给函数参数,依次类推。
1 | reduce(function, iterable[, initializer]) |
举例1:阶乘
1 | def mul(x, y): |
举例2:整数列表
1 | from functools import reduce |
flatten()
只适用于numpy对象,即array或mat;
默认缺省参数为0;
数组降维:默认按照行的方向降维到一维
tolist()
数组转换为列表
0x07实验感想
通过本次DES实验,我深刻理解了DES加解密的过程与细节,同时通过对密码差分攻击的深入学习,也适当锻炼了数学思维,拓展了其它方面的知识如:离散数学中域的概念、python的一些库函数、异或运算的性质、typora绘制流程图等,同时也意识到向更优秀的学长们学习的必要性,这次实验对我是一次很好的锻炼与成长。
0x08参考资料
1.阮师傅的Blog
(阮师傅的博客和cdcq学长的博客写的非常好,我就是根据他们的文章进行学习的)
3.《密码编码学与网络安全——原理与实践(第八版)》William Stallings著 电子工业出版社
4.《分组密码的攻击方法与实例分析》李超 孙兵 李瑞林著 科学出版社
5.《Python密码学编程(第二版)》Al Sweigart著 人民邮电出版社
6.Wiki-pedia:Data Encryption Standard
0x09 DES C语言版
1 |
|