【问题标题】:HMAC failing to detect slight change on keysHMAC 未能检测到密钥的细微变化
【发布时间】:2020-07-30 22:25:09
【问题描述】:

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

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")

【问题讨论】:

  • 我正在使用 PyCryptodome 模块。我也更新了这个问题,所以这也会反映出来。

标签: python encryption aes hmac cbc-mode


【解决方案1】:

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

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

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

【讨论】:

  • 嗨@Maarten Bodewes,感谢您向我解释这一点。我还注意到,如果不是更改倒数第二个字符,而是将其转换为小写,则解密将失败。你对此有何看法?谢谢。
  • base 64 alphabet 的表格将向您解释这一点:大写 ABC、小写 abc、数字,然后是 + 和 /。所以小写字母“更远”,因此更重要的(即最左边的)位会发生变化。
猜你喜欢
  • 1970-01-01
  • 2014-02-04
  • 1970-01-01
  • 2015-01-25
  • 1970-01-01
  • 2014-08-15
  • 1970-01-01
  • 2011-08-22
  • 1970-01-01
相关资源
最近更新 更多