在加密和解密JSON文件时,为什么Pycryptodome MAC检查失败?

时间:2019-12-15 05:48:59

标签: json python-3.x pycryptodome passlib

我正在尝试使用以JSON散列的密码作为密钥,用AES-256加密一些pbkdf2_sha256数据。我想将数据存储在文件中,能够将其加载,解密,更改,加密,存储并重复。

我正在将passlibpycryptodome库与python 3.8一起使用。以下测试在docker容器内进行,并引发我无法纠正的错误

有人对我如何改善代码(和知识)有任何线索吗?

Test.py:

import os, json
from Crypto.PublicKey import RSA
from Crypto.Cipher import AES
from passlib.hash import pbkdf2_sha256

def setJsonData(jsonData, jsonFileName):
    with open(jsonFileName, 'wb') as jsonFile:
        password = 'd'
        key = pbkdf2_sha256.hash(password)[-16:]

        data = json.dumps(jsonData).encode("utf8")
        cipher = AES.new(key.encode("utf8"), AES.MODE_EAX)
        ciphertext, tag = cipher.encrypt_and_digest(data)

        [ jsonFile.write(x) for x in (cipher.nonce, tag, ciphertext) ]

def getJsonData(jsonFileName):
   with open(jsonFileName, 'rb') as jsonFile:
        password = 'd'
        key = pbkdf2_sha256.hash(password)[-16:]

        nonce, tag, ciphertext = [ jsonFile.read(x) for x in (16, 16, -1) ]
        cipher = AES.new(key.encode("utf8"), AES.MODE_EAX, nonce)
        data = cipher.decrypt_and_verify(ciphertext, tag)

        return json.loads(data)


dictTest = {}
dictTest['test'] = 1

print(str(dictTest))
setJsonData(dictTest, "test")

dictTest = getJsonData("test")
print(str(dictTest))

输出:

{'test': 1}
Traceback (most recent call last):
  File "test.py", line 37, in <module>
    dictTest = getJsonData("test")
  File "test.py", line 24, in getJsonData
    data = cipher.decrypt_and_verify(ciphertext, tag)
  File "/usr/local/lib/python3.8/site-packages/Crypto/Cipher/_mode_eax.py", line 368, in decrypt_and_verify
    self.verify(received_mac_tag)
  File "/usr/local/lib/python3.8/site-packages/Crypto/Cipher/_mode_eax.py", line 309, in verify
    raise ValueError("MAC check failed")
ValueError: MAC check failed

研究:

  • 已调查this的答案,但我相信我的verify()通话正在 正确的地方

  • 我注意到在python文档中,它说:

      

    loads(dumps(x))!= x,如果x具有非字符串键。

    但是,当我用dictTest['test'] = 'a'重新运行测试时,我遇到了相同的错误。

  • 我怀疑问题是json格式,所以我对字符串进行了相同的测试,但没有进行json.loadsjson.dumps调用,但是我遇到了相同的错误< / p>

1 个答案:

答案 0 :(得分:0)

这里的问题是key = pbkdf2_sha256.hash(password)[-16:]在每次调用时用新的盐对密钥进行哈希处理。因此,用于加密和解密密文的密码将有所不同,从而产生不同的数据,从而导致完整性检查失败。

我将密钥派生函数更改为以下内容:

h = SHA3_256.new()
h.update(password.encode("utf-8"))
key = h.digest()