我正在尝试使用AES-256
加密一些JSON
数据,使用以pbkdf2_sha256
作为密钥哈希的密码。我想将数据存储在文件中,能够加载它,解密它,更改它,加密它,存储它,然后重复。
我正在使用带有python 3.8
的passlib
和pycryptodome
库。以下测试发生在 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
研究:
查看了这个答案,但我相信我的
verify()
电话在 正确的地方我注意到在python文档中,它说:
loads(dumps(x(( != x 如果 x 有非字符串键。
但是,当我用
dictTest['test'] = 'a'
重新运行测试时,我遇到了同样的错误。我怀疑问题是 json 格式,所以我用字符串做了同样的测试,没有进行
json.loads
和json.dumps
调用,但我有同样的错误
这里的问题是key = pbkdf2_sha256.hash(password)[-16:]
每次调用都用新的盐对密钥进行哈希处理。因此,用于加密和解密密文的密码将有所不同,产生不同的数据,从而无法通过完整性检查。
我将密钥派生函数更改为以下内容:
h = SHA3_256.new()
h.update(password.encode("utf-8"))
key = h.digest()