aar*_*nk6 3 javascript python encryption aes sjcl
我\xe2\x80\x99d喜欢在Python 3中解密AES加密的字符串(CCM模式)。
\n以下 JavaScript 代码使用sjcl库的 JavaScript 代码可以正常工作:
\nconst sjcl = require(\'sjcl\');\n\nconst key = "ef530e1d82c154170296467bfe40cdb47b9ad77e685bbf8336b145dfa0e85640";\nconst keyArray = sjcl.codec.hex.toBits(key);\nconst iv = sjcl.codec.base64.fromBits(sjcl.codec.hex.toBits(key.substr(0,16))); \nconst params = {\n "iv": iv,\n "v": 1,\n "iter": 1000,\n "ks": 256,\n "ts": 128,\n "mode": "ccm",\n "adata": "",\n "cipher": "aes",\n "salt": "",\n};\n\nfunction encrypt(data) {\n const ct = JSON.parse(sjcl.encrypt(keyArray, data, params)).ct;\n return sjcl.codec.hex.fromBits(sjcl.codec.base64.toBits(ct));\n}\n\nfunction decrypt(data) {\n const ct = sjcl.codec.base64.fromBits(sjcl.codec.hex.toBits(data));\n const paramsWithCt = JSON.stringify({ ...params, ...{ "ct": ct } });\n return sjcl.decrypt(keyArray, paramsWithCt);\n}\n\nlet ct = encrypt("my secret string");\nconsole.log("Cipher Text: " + ct);\n\nlet plain = decrypt(ct);\nconsole.log("Plain Text: " + plain);\n\nRun Code Online (Sandbox Code Playgroud)\n输出:
\n$ npm i sjcl\n$ node index.js\nCipher Text: fa90bcdedbfe7ba89b69216e352a90fa57a63871fc4da7e69ab7f897f427f8e3\nPlain Text: my secret string\nRun Code Online (Sandbox Code Playgroud)\n我可以使用哪个库在 Python 中执行相同的操作?
\n我尝试使用pycryptodome 库,但它接受一组不同的参数:
\nsjcl对 4 字节字的数组进行操作。用sjcl.codec.hex.toBits()十六进制编码的密钥被转换成这样的数组。密钥的前 8 个字节(16 个十六进制数字)用作随机数。
密钥大小、标签大小、算法和模式由对象确定params。该params对象还包含用于密钥派生的参数,例如iter、salt等),但此处将忽略这些参数,因为密钥作为数组而不是字符串传递。
Nonce 和密文在对象内以 Base64 编码传递params。
密文是实际密文和标签按此顺序串联而成,也必须以这种格式传递到解密。sjcl处理连接的密文和标签,
而PyCryptodome分别处理两者。除此之外,Python 中的加密和解密使用PyCryptodome非常简单:
from Crypto.Cipher import AES
data = b'my secret string'
key = bytes.fromhex('ef530e1d82c154170296467bfe40cdb47b9ad77e685bbf8336b145dfa0e85640')
nonce = bytes.fromhex('ef530e1d82c154170296467bfe40cdb47b9ad77e685bbf8336b145dfa0e85640')[:8]
# Encryption
cipher = AES.new(key, AES.MODE_CCM, nonce)
ciphertext, tag = cipher.encrypt_and_digest(data)
ciphertextTagHex = ciphertext.hex() + tag.hex()
print(ciphertextTagHex) # fa90bcdedbfe7ba89b69216e352a90fa57a63871fc4da7e69ab7f897f427f8e3
# Decryption
ciphertextTag = bytes.fromhex(ciphertextTagHex)
ciphertext = ciphertextTag[:-16]
tag = ciphertextTag[-16:]
cipher = AES.new(key, AES.MODE_CCM, nonce)
try:
decrypted = cipher.decrypt_and_verify(ciphertext, tag)
print(decrypted.decode('utf-8')) # my secret string
except ValueError:
print('Decryption failed')
Run Code Online (Sandbox Code Playgroud)
请注意,从密钥导出随机数是不安全的。对于 CCM、seg RFC4309、p.1来说尤其如此。3、最后一节:
AES CCM 采用计数器模式进行加密。与任何流密码一样,使用相同的密钥重复使用相同的 IV 值是灾难性的。
相反,应该为每次加密随机生成随机数。随机数不是秘密的,通常与字节级别的密文连接起来,通常是nonce|ciphertext|tag。