### Padding Oracle Attack 讲讲

**攻击的核心原理**

要理解这个攻击，我们首先需要了解几个关键概念：

**1. 分组密码和 CBC 模式**

- **分组密码**将明文分割成固定大小的**分组**进行加密
- **CBC（密文分组链接）模式**是一种常用的分组密码模式。在 CBC 模式中，每个明文分组在加密前，会先与前一个密文分组进行**异或**（XOR）运算。这使得每个密文分组都依赖于其之前的所有分组，从而提供了更好的安全性
- **IV（初始化向量）**：第一个明文分组加密时没有前一个密文分组，因此需要一个**初始化向量**（IV）来代替

**2. 填充（Padding）**

为了确保最后一个明文分组能够填满整个分组长度，需要进行**填充**。例如，如果分组大小是 16 字节，而最后一个明文分组只有 13 字节，就需要填充 3 个字节。 **PKCS#7 填充**是常用的填充标准。它将填充的每个字节都设置为填充的长度。例如，如果需要填充 3 个字节，就会在明文末尾添加 `0x03 0x03 0x03`。解密后，系统会检查最后一个字节的值，并移除相应数量的填充

**攻击的步骤**

Padding Oracle Attack 利用的就是**填充验证机制**的漏洞。攻击者通过发送修改后的密文到服务器，并观察服务器是否返回“填充正确”或“填充错误”的信息。这个“神谕”（Oracle）就是指服务器的这个响应行为

攻击者可以**逐字节地**解密密文。假设我们要解密密文分组 Cn：

1. **构造密文**：攻击者需要控制一个密文分组 Cn−1′（通常是伪造的）和一个目标密文分组 Cn
2. **暴力破解**：攻击者会尝试 Cn−1′ 的最后一个字节，从 0 到 255 遍历所有可能的值
3. **发送给服务器**：将伪造的 `(IV + C_0 + ... + C_{n-2} + C_{n-1}' + C_n)` 发送给服务器
4. **观察响应**：
   - 如果服务器返回**“填充正确”**，说明填充字节的解密结果为 `0x01`
   - 如果服务器返回**“填充错误”**，说明填充字节的解密结果不为 `0x01`
5. **推导**：
   - 当我们找到一个让服务器返回“填充正确”的 Cn−1′ 时，根据CBC模式的解密公式： `$P_n = D(C_n) \oplus C_{n-1}$`
   - 那么，伪造的密文解密后，其最后一个明文字节为 `0x01`： `$P_n'[last] = D(C_n)[last] \oplus C_{n-1}'[last] = 0x01$`
   - 我们可以推导出 `D(C_n)[last]` 的值： `$D(C_n)[last] = P_n'[last] \oplus C_{n-1}'[last] = 0x01 \oplus C_{n-1}'[last]$`
   - 既然我们已经知道了 D(Cn) 的最后一个字节，我们就可以用同样的方法，依次解密倒数第二个字节、倒数第三个字节……
   - 每解密一个字节，攻击者就构造一个新的 Cn−1′，使得它能让下一个填充字节的解密结果为 `0x02`，然后继续这个过程，直到解密完整个分组