块加密工作模式
-
对于加密按照对加密数据的处理可分为流加密和块加密,块加密的算法一般都在对称加密中体现,而这里只介绍块加密工作模式,以及相应的攻击。
-
块加密的工作模式分为以下几类:
ECB模式
、CBC模式
、CTR模式
、CFB模式
、OFB模式
、GCM模式
,接下来逐一介绍这些工作模式的具体过程。以及这些模式的相关攻击,有些攻击会有对应的CTF
题目为例题。 -
下面这些块加密模式都以
AES
块加密算法为例子,我们并不需要具体了解AES
加密算法的过程。
明文处理
- 对于块加密,我们都要对明文进行分组处理,既然对明文要分组处理,这就会导致分得的最后一组会存在不足,此时我们就要用特定的数据对分组后的明文进行填充操作
- 块加密的分组方式一般还取决于块加密的一些算法,比如使用
AES
加密算法一般就是将明文分为128
位为一组,而使用DES
加密一般就是将明文分为64
位为一组 - 所以我们一开始会对明文进行如下的分组处理:
- 明文被分成固定大小的块(每块多少位取决于加密算法)
- 如果明文长度不是块大小的整数倍,最后一个块需要填充(通常使用PKCS#7填充)
- 注:有些填充方式如果明文长度是块大小的整数倍,那么最后还要填充一整块。
- 接下来简单介绍一下一些填充方式:
- PKCS#7(最常用):补多少字节就填充该字节的值,比如最后一块差
3
个字节才满,此时就要补3个0x03
。如果是要填充一整块的话,假设每块16字节
,此时就要填充16个0x10
。该填充方式在满足明文长度是块大小整数倍的时候还要填充一整块 - ISO/IEC 7816-4:在尾部填充一个
0x80
,然后剩下的填充0
,在明文长度是块大小整数倍的时候还要填充一整块。 - ANSI_X.923:全部填充
0x00
,最后一个字节填充差的长度,比如差4个字节需要这样填充0x00 0x00 0x00 0x04
在明文长度是块大小整数倍的时候还要填充一整块。 - Zero_Padding:填充部分全部填充
0x00
,并且在明文长度是块大小整数倍的时候不需要额外填充一整块 - ISO_10126(已弃用):填充的时候全部填充随机数,只有最后一个字节填充差的长度(类似于
ANSI_X.923
),在明文长度是块大小整数倍的时候还要填充一整块。
- PKCS#7(最常用):补多少字节就填充该字节的值,比如最后一块差
ECB模式
工作方式
AES-ECB加密首先输入明文,首先将这些明文转化为16进制的ASCII值;其次将这些明文以16字节为一组进行分块处理。如果明文的字节数不是16进制,那么就会将最后一块明文块,按照某种填充方式,使其达到16字节。
接下来就是使用AES加密对每一个明文块单独加密,明文块与明文块之间相互独立。
然后明文块再与密钥一起,经过AES加密,输出密文块。密文块同样也是128bit
注意:ECB加密模式要注意的是,每个明文块都是使用相同的密钥进行加密的。这也就是说相同的明文会输出相同的密文。
- 总结:
ECB
的工作模式其实就是这么简单,就是利用加密算法,对每一个明文块单独加密,明文块与明文块之间相互独立,没有什么联系。所以ECB
这种简单的块加密方式就非常容易被选择明文攻击
选择明文攻击
-
该方法是利用相同的明文块经过加密后,会产生相同的明文块。这样就可以进行逐个字节的爆破,从而得到flag
-
这里直接以CTF题入手,题目描述如下:
- 中文翻译过来如下:
- 先nc一下连接靶机,看看靶机上的程序是如何运行的,发现nc过后系统会将flag经过AES-ECB加密后的密文输出过来
- 然后再看密文上面的字,可以得到信息,用户可以输入base64编码的数据,然后靶机会重新加密,并输出重新加密过后的密文
确定明文个数
- 所以我们可以进行如下攻击,首先确定明文个数,先将得到的密文进行base64解码,解码成16进制的形式
- 然后以两个十六进制数为1组,进行加密的明文一共有多少字节多少块。发现密文解码后一共有48个字节,所以按照16字节为一组的明文块,一共就有3块。初步得出明文flag的长度在
32-48
字节字节
1 | a = '1F478C9B50E20C146B2204BDFBF8CD85D3439B280CB59A64E5E0EDD7D99F03C4BFC4606660026280E174A847FFB02A24' |
- 然后再进行明文填充,先输入
a
查看密文字节数有没改变,如果没有改变再输入aa
。如果还是没有改变继续增加a的个数,然后输入进去,再检查发送过来的密文字节数 - 这里发现当发送一个a过后密文的字节数就改变了,这就可以得到明文flag的长度为47个字节这里为什么为47个字节,而不是48个字节,是与明文块的填充方式有关
1 | a |
爆破明文原理
- 然后确定了明文长度,就可以通过相同明文加密后的密文是相同的进行逐个字节爆破,最后得到flag。
- 逐个字节爆破过程如下,这里为了更好的演示就直接利用本题flag进行爆破演示,从而得到flag
1 | grodno{a50f00AES_1n_ECB_m0de_1s_hackableaf1aef} |
- 爆破过程如下,先构造
payload='aaaaaaaaaaaaaaa?(可见字符)aaaaaaaaaaaaaaag'
- 然后对发送出来的密文块1,密文块2进行判断是否相同,如果相同即可得出可见字符(?)对应的字符是
g
,那么flag第一个字符就给爆破出来了
- 然后再进行第二个字符的爆破,之后就这样重复爆破下去
exp
- exp如下:
1 | from pwn import * |
CBC模式
工作方式
密文填充攻击(Padding Oracle)
参考文章:AES-CBC密文填充攻击—深入理解和编程实现 | 网络热度
参考文章:Padding Oracle攻击解密AES - poziiey - 博客园
Padding Oracle Attack
是由Vaudenay
在Eurocrypt 2022
首次提出。由于要满足块加密16
字节为一块,通常最后一块可能不能被填满,这时就需要使用一些填充规则进行填充操作。并且将密文发送回服务器解密时,如果解密后不满足填充规则服务器会给出填充错误的提示。这就导致可以进行Padding Oracle Attack
-
利用前提条件:
- 需要采用
PKCS5
这个填充标准,填充值为需要填充的字节数。 - 使用
AES-CBC
加密算法 - 攻击者需要获得密文,以及初始向量
IV
- 攻击者可以通过服务器知道
padding
是否正确
- 需要采用
-
攻击效果:可以在未知
key
的条件下解出密文 -
这里直接模拟一个
加密和验证padding
的服务,使用Python编写如下代码
1 | from Crypto.Cipher import AES |