如何解决Python 3 XChaCha20 测试向量可用于加密但解密阶段失败
我使用以下向量在 python 中使用 poly1305 的 AEAD 测试 XChaCha20 加密:
向量:
https://tools.ietf.org/html/draft-arciszewski-xchacha-03#appendix-A.3
pycryptodome:
https://pycryptodome.readthedocs.io/en/latest/src/cipher/chacha20_poly1305.html
草稿使用十六进制作为测试向量,如果您真的需要检查我是否使用此服务进行转换:
import json
from base64 import b64encode
from base64 import b64decode
from Crypto.Cipher import ChaCha20_poly1305
from Crypto.Random import get_random_bytes
#nonce_xchacha20 = get_random_bytes(24)
nonce_xchacha20 = b64decode("QEFCQ0RFRkdIsuplTE1OT1BRUlNUVVZX")
#header = b"header"
header = b64decode("UFFSU8DBwsPExcbH")
plaintext = b"Ladies and Gentlemen of the class of '99: If I Could offer you only one tip for the future,sunscreen would be it."
#key = get_random_bytes(32)
key = b64decode("gIGCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnp8=")
cipher = ChaCha20_poly1305.new(key=key,nonce=nonce_xchacha20)
cipher.update(header)
ciphertext,tag = cipher.encrypt_and_digest(plaintext)
jk = [ 'nonce','header','ciphertext','tag' ]
jv = [ b64encode(x).decode('utf-8') for x in (cipher.nonce,header,ciphertext,tag) ]
result = json.dumps(dict(zip(jk,jv)))
print(result)
# We assume that the key was securely shared beforehand
try:
b64 = json.loads(result)
jk = [ 'nonce','tag' ]
jv = {k:b64decode(b64[k]) for k in jk}
cipher = ChaCha20_poly1305.new(key=key,nonce=jv['nonce'])
cipher.update(jv['header'])
plaintext = cipher.decrypt_and_verify(jv['ciphertext'],jv['tag'])
print("The message was: " + plaintext)
except (ValueError,KeyError):
print("Incorrect decryption")
print("sanity check if key values are the same: ")
print(b64encode(jv['nonce']))
print(b64encode(jv['header']))
print(b64encode(jv['ciphertext']))
print(b64encode(jv['tag']))
如果测试向量根据 IETF 草案正确加密,为什么我的解密阶段会失败?
{"nonce": "AAAAAFBRUlNUVVZX","header": "UFFSU8DBwsPExcbH","ciphertext": "vW0XnT6D1DuVdleUk8DpOVcqFwAlK/rMvtKQLCE5bLtzHH8bC0qmRAvzqC9O2n45rmTGcIxUwhbLlrcuEhO0Ui+Mm6QNtdlFsRtpuYLBu54/P6wrw2lIj3ayODVl0//5IflmTJdjfal2iBL2FcaLE7Uu","tag": "wIdZJMHHmHlH3q/YeArPSQ=="}
Incorrect decryption
sanity check if key values are the same:
b'AAAAAFBRUlNUVVZX'
b'UFFSU8DBwsPExcbH'
b'vW0XnT6D1DuVdleUk8DpOVcqFwAlK/rMvtKQLCE5bLtzHH8bC0qmRAvzqC9O2n45rmTGcIxUwhbLlrcuEhO0Ui+Mm6QNtdlFsRtpuYLBu54/P6wrw2lIj3ayODVl0//5IflmTJdjfal2iBL2FcaLE7Uu'
b'wIdZJMHHmHlH3q/YeArPSQ=='
当我将字节数组转换回 base64 时,它们仍然与 JSON 输出匹配。 所以从 JSON 读取我的密钥值进行解密是正确的。
错在哪里?我确实使用了提供 pycryptodome 的站点中的代码示例,并且加密已正确完成。它应该可以解密。
解决方法
如果你在行中替换,解密将正确完成
jv = [ b64encode(x).decode('utf-8') for x in (cipher.nonce,header,ciphertext,tag) ]
带有 cipher.nonce
的表达式 nonce_xchacha20
。该错误导致在 JSON 中提供不正确的随机数。
似乎 cipher.nonce
只能用于确定随机生成的 nonce(如果在实例化密码时未指定显式 nonce,则生成随机 nonce,s. here)。
第二个(微不足道的)变化正在行中
print("The message was: " + plaintext)
必须的。这里必须执行 UTF8 解码,即 plaintext
必须替换为 plaintext.decode('utf8')
。
在您的第一篇博文中,AAD 的设置也有误。但这在此期间已得到纠正。
通过这两个更改,代码,尤其是解密,可以在我的机器上运行。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。