HMAC 未能检测到键上的细微变化

HMAC failing to detect slight change on keys

假设用于加密文件的密钥是这个。

SDEREvalYDHK3xcuzChG7CU4hLBaoaVSvaJg_Fqo7UY=

加密工作正常。但是,当我使用 hmac.compare_digest() 时,未检测到所用密钥的细微变化。

SDEREvalYDHK3xcuzChG7CU4hLBaoaVSvaJg_Fqo7UZ=

请注意倒数第二个字符已从 Y 更改为 Z。解密仍然有效,但我预计它会失败。

我做错了什么?如果有任何帮助,我正在使用 PyCryptodome 模块。

import os, hmac, hashlib
from base64 import urlsafe_b64encode, urlsafe_b64decode
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad

BS = AES.block_size
class CRYPTOPRACTICE:
    def key(self):
        with open("k.txt", "rb") as k:
            return urlsafe_b64decode(k.read())

    def e(self, file):
        with open(file, "rb") as data:
            IV = os.urandom(BS)
            e = AES.new(self.key(), AES.MODE_CBC, IV).encrypt(pad(data.read(), BS))
            sig = hmac.new(self.key(), e, hashlib.sha256).digest()
            with open(file + ".encrypted", "wb") as enc:
                enc.write(IV + e + sig)
        os.remove(file)

    def d(self, file):
        with open(file, "rb") as data:
            IV = data.read(BS)
            e = data.read()[:-32]
            data.seek(-32, os.SEEK_END)
            sig = data.read()
            auth = hmac.new(self.key(), e, hashlib.sha256).digest()

            if hmac.compare_digest(sig, auth):
                d = unpad(AES.new(self.key(), AES.MODE_CBC, IV).decrypt(e), BS)
                with open(file[:-10], "wb") as dec:
                    dec.write(d)
                data.close()
                os.remove(file)
            else: print(f"Fail: {file}")

a = CRYPTOPRACTICE()
a.e("test.txt")
a.d("test.txt.encrypted")

您假设微小的变化确实改变了二进制文件。但是,base 64 将 6 位编码为一个字符。这也意味着,除非您对 3 个字节的倍数进行编码,否则填充字符 之前的 最后一个字符可能无法编码完整的 6 位。

在你的例子中有一个最后的填充字符,这意味着最后三个字符编码 2 * 8 = 16 位,而它们可以编码 3 * 6 = 18 位。所以最后两位(索引到 base 64 字母表中的)通常设置为零,否则将被忽略。通常解码器也简单地忽略编码的两位。所以除非你做出更大的改变,否则字符编码完全相同的 4 位。

如果你有两个填充字符,那么你甚至有 4 位设置为零。如果没有填充字符,那么每个字符都必须相同,否则二进制文件将改变。