不使用tag\mac解密Chacha20-Poly1305字符串

问题描述 投票:0回答:1

我能够在 python 中使用 Chacha20-Poly1305 成功加密和解密字符串,而无需使用标签(或 mac),如下所示(使用 pycryptodome 库):

from Crypto.Cipher import ChaCha20_Poly1305

key = '20d821e770a6d3e4fc171fd3a437c7841d58463cb1bc7f7cce6b4225ae1dd900' #random generated key
nonce = '18c02beda4f8b22aa782444a' #random generated nonce

def decode(ciphertext):
    cipher = ChaCha20_Poly1305.new(key=bytes.fromhex(key), nonce=bytes.fromhex(nonce))
    plaintext = cipher.decrypt(bytes.fromhex(ciphertext))
    return plaintext.decode('utf-8')


def encode(plaintext):
    cipher = ChaCha20_Poly1305.new(key=bytes.fromhex(key), nonce=bytes.fromhex(nonce))
    ciphertext = cipher.encrypt(plaintext.encode('utf-8'))
    return ciphertext.hex()

encrypted = encode('abcdefg123')
print(encrypted)

# will print: ab6cf9f9e0cf73833194

print(decode(encrypted))

# will print: abcdefg123

但是,将其应用于 Javascript,我找不到无需 mac 即可解密的库(如果我使用 encrypt_and_digest(),我就会得到)。

我几乎尝试了我能找到的所有库(Npm,因为这将在 React 应用程序中使用),它们都需要 mac 部分进行解密。 例如:libsodium-wrappers、js-chacha20 等

我该如何克服这个问题?

附注 我知道不使用 mac 部分不太安全,这是出于教育目的。

===编辑===

  1. 该字符串已使用 Chacha20-Poly1305 加密,并且已给出其加密输出。它无法使用不同的算法重新加密。

  2. 我无法使用 Chacha20-Poly1305 加密并使用 Chacha20 解密,反之亦然,因为仅使用 Chacha20(而不是 Chacha20-Poly1305)使用相同的密钥和随机数进行加密会给我不同的加密输出,这没有帮助。

javascript python encryption cryptography encryption-symmetric
1个回答
0
投票

这可能是由于所应用的库之间的初始计数器值不一致造成的。

对于 ChaCha20-Poly1305,计数器 0 用于确定身份验证标签,因此计数器 1 是用于加密的第一个值 s。 这里
PyCryptodome 也遵循

encrypt()
的逻辑,大概因此
encrypt()
digest()
给出与
encrypt_and_digest()
相同的结果。
相反,js-chacha20 默认情况下应用计数器 0,s。 这里。因此,为了与 PyCryptodome 兼容,您必须显式地将初始计数器设置为 1:

const key = hex2ab("20d821e770a6d3e4fc171fd3a437c7841d58463cb1bc7f7cce6b4225ae1dd900"); // 32 bytes key
const nonce = hex2ab("18c02beda4f8b22aa782444a"); // 12 bytes nonce
const ciphertext = hex2ab("ab6cf9f9e0cf73833194"); // ciphertext from PyCryptodome

const decryptor = new JSChaCha20(key, nonce, 1); // Fix: set initial counter = 1 in the 3rd parameter
const plaintext = decryptor.decrypt(ciphertext);
console.log(new TextDecoder().decode(plaintext)); // abcdefg123

function hex2ab(hex){
    return new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function (h) {return parseInt(h, 16)}));
}
<script src=" https://cdn.jsdelivr.net/npm/[email protected]/src/jschacha20.min.js "></script>

通过此更改,密文可以正确解密。

© www.soinside.com 2019 - 2024. All rights reserved.