【问题标题】:AES GCM returning "ValueError: MAC check failed"AES GCM 返回“ValueError:MAC 检查失败”
【发布时间】:2021-05-29 06:25:34
【问题描述】:

我正在尝试制作密码管理器,我正在使用 KDF 制作密钥,然后使用 AES GCM 加密数据库中的每一行。每行在密钥中使用不同的盐。我已按照pycryptodome 上的文档使用示例代码加密和解密数据,一切正常,除了 MAC 检查。

我检查了很多次,加密和解密、nonce、salt、tag、密文等都完全一样。

我该如何解决这个问题? (代码如下)

class Crypto(PasswordDatabase):
    def __init__(self):
        PasswordDatabase.__init__(self)
        self.db = None

    def encrypt_db(self):
        self.db = self.get_database()
        master_password = b'password'

        with open("passwords.txt", "w") as file:
            for i in range(len(self.db)):

                current_tuple = list(self.db[i])
                del current_tuple[0]
                current_tuple = tuple(current_tuple)
                plaintext = ",".join(current_tuple)

                salt = get_random_bytes(16)
                key = PBKDF2(master_password, salt, 16, count=1000000, hmac_hash_module=SHA512)
                file.write(f"salt={salt},")

                header = b"header"
                cipher = AES.new(key, AES.MODE_GCM)
                cipher.update(header)
                ciphertext, tag = cipher.encrypt_and_digest(plaintext.encode())

                json_k = [ 'nonce', 'header', 'ciphertext', 'tag' ]
                json_v = [b64encode(x).decode('utf-8') for x in (cipher.nonce, header, ciphertext, tag)]
                result = json.dumps(dict(zip(json_k, json_v)))

                print(result, "\n")
                file.write(result + "\n")

    def decrypt_db(self):
        with open("passwords.txt", "r") as file:
            master_password = b"password"

            for line in file:
                stripped_line = line.strip()
                ssalt = re.findall("salt=(b'.*'),", str(stripped_line))
                salt = ssalt[0]

                key = PBKDF2(master_password, salt, 16, count=1000000, hmac_hash_module=SHA512)

                json_input = re.findall("salt=b'.*',({.*})", str(stripped_line))
                b64 = json.loads(json_input[0])
                json_k = [ 'nonce', 'header', 'ciphertext', 'tag' ]
                jv = {k:b64decode(b64[k]) for k in json_k}

                cipher = AES.new(key, AES.MODE_GCM, nonce=jv['nonce'])
                cipher.update(jv['header'])
                plaintext = cipher.decrypt_and_verify(jv['ciphertext'], jv['tag'])
                print(plaintext)


if __name__ == "__main__":
    crypto = Crypto()
    crypto.encrypt_db()
    crypto.decrypt_db()

【问题讨论】:

  • 您的密钥在加密过程中的大小错误,您似乎在加密过程中将 AES-256 与解密过程中的 AES-128 混合在一起。
  • @MaartenBodewes 我看到我有 1 个密钥为 32 个字节,另一个为 16 个字节。我回顾了文档,发现它们必须是 16 字节,所以我将它们都更改为 16 字节。但是,我仍然收到MAC check failed 错误
  • 最后,有时您必须在将所有组件输入密码之前将其打印为十六进制。如果它们不匹配,那就有问题了。
  • @MaartenBodewes 我已将所有组件打印为十六进制,并且没有任何值被更改。出于某种原因,每当我从文件中读回 salt 时,文件阅读器都会添加额外的 \s。例如,文件中的盐是'b'\xea\xee\xd8\x9aJ>\xbc\xa5$\xf8\x8c\x88R\xcf\x97N'',然后我会读取文件,然后它会说盐是'b\'\\xea\\xee\\xd8\\x9aJ>\\xbc\\xa5$\\xf8\\x8c\\x88R\\xcf\\x97N\'',它添加了额外的\s。
  • @MaartenBodewes 我修复了文件阅读器随机添加\s 的问题,方法是在写入文件之前将其编码为base64,然后再对其进行解码。 MAC 检查现在不会失败。感谢您的帮助:)

标签: python-3.x encryption pbkdf2 aes-gcm pycryptodome


【解决方案1】:

文件阅读器随机添加了额外的\s 到salt,所以我在将salt 写入文件之前使用base64 对其进行编码,然后在从文件中读取后对其进行解码以解密。 MAC 检查现在不会失败。

【讨论】:

    猜你喜欢
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-04
    • 2015-02-08
    • 2021-10-08
    • 1970-01-01
    相关资源
    最近更新 更多