从这一次作业开始感觉没学过本科密码学的应该就看不懂了,因为涉及到不少的概念。不过就当一个自己的笔记吧。
第三次作业的链接(可以点击阅读原文直接跳转):https://cseweb.ucsd.edu/classes/sp22/cse207B-a/hw3/
作业要求:给定一段使用了 AES128 + CBC-mode + PKCS7 padding 加密的密文,以及一个判断任意密文解密出的明文是否满足 PKCS7 padding 的 oracle ,恢复完整的明文。
AES 是一种对称加密方式,以 AES128 为例,它需要一个 128bit key,每次可以把一个 128bit 的明文 block 加密成一个等长度的密文 block。这里的「加密」是可逆的,所以在 key 固定的情况下,AES128 是一个 permutation(一一映射)。
显然我们加密的东西不可能恰好是 128bit 的,所以这里就会有两个问题:
如果明文长度超过 128bit 咋办; 如果明文长度不是 16(128bit = 16byte)的倍数咋办。
第一个问题看似很好解决,我们把明文每 16byte 分成一个块,然后用同一个 key 加密就行了。这叫做 ECB-mode,它是一个解决方法,但它不是 CPA-secure 的,因为相同的块会被加密成相同的密文,所以如果我们在加密例如图片等块状信息的时候,仍然可以从密文中得到一些很明显的 pattern。感兴趣的读者可以搜索「ECB penguin」看到那只可爱的 Linux 企鹅。
因此 CBC-mode 就被引入了。我们首先需要生成一个 128bit 的 IV(初始向量,initialization vector),如果明文被分成了 这 个块,那么加密的过程为:
其中 是密文的第 个块, 是异或运算。当 时,。最后返回 作为密文。
可以证明 ECB-mode 是 CPA-secure 的,那么第一个问题就解决了。
第二个问题可以使用 padding 把最后一个不满的 block 补齐。例如 PKCS7 padding,如果最后一个 block 缺 x 个 byte,那么就补上 x 个 x。特别地,如果最后一个 block 本来就是满的,就需要补一个额外的 16 个 16 的 block,如果不这样做,我们就无法区分末尾的 x 个 x 到底是 padding 还是明文了。
PKCS7 padding 本身也不会引入啥问题,因为攻击者不知道密钥 ,所以也没啥办法。但如果攻击者可以借助一个 oracle :输入任意构造的密文,输出一个 bool 值,表示该密文解密出的明文是否有正确的 PKCS7 padding,那么就可以恢复明文了。这在现实中也是有意义的,比如攻击者上传一段 session cookie 对应的密文,如果解密出的明文不满足 PKCS7 padding,服务器可能会返回一个 decryption error,如果满足但是明文并没有什么意义,服务器可能会返回 session not found,这里返回状态的差异就可以当成攻击者利用的 oracle。更具体的例子可以参考论文「Security Flaws Induced by CBC Padding Applications to SSL, IPSEC, WTLS...」
恢复的方法就是每次给 喂一个长度为 2 block 的密文,其中第 2 个 block 是 (我们希望得到其对应的明文 ),第 1 个 block 我们可以一位一位来猜。我们的目的就是调整第 1 个 block,使得 返回 True,这样就表示 异或上第 1 个 block 得到的东西有正确的 padding。padding 只有 16 种:1 个 1,2 个 2,3 个 3,...,16 个 16,所以我们先让 padding 变成 1 个 1,得到明文的最后一位,然后让 padding 变成 2 个 2,得到明文的倒数第二位,以此类推,直到得到 block 里面的全部 16 个 byte,这样就得到了 。
具体的细节我不想写了,感兴趣的就看上面那篇论文吧。