Encrypt with Node.js AES CTR and decrypt with PyCrypto

末鹿安然 提交于 2019-12-10 11:46:30

问题


Okay, so basically I am having issues decrypting with Python.

I've managed to encrypt/decrypt data with Node.js - using "aes-128-ctr", the same goes for PyCrypto, but when I try to encrypt with Node.js and decrypt with Python I get invalid deciphered text.

Node.js code:

var key = "1234567890123456";
var cipher = crypto.createCipher("aes-128-ctr",key)
var ctext = cipher.update('asasasa','utf8','hex') +  cipher.final('hex')
console.log(ctext) // outputs: "f2cf6ecd8f"

Python code:

counter = Counter.new(128)
cipher = AES.new("1234567890123456", AES.MODE_CTR, counter=counter)
cipher.decrypt("f2cf6ecd8f") // outputs: weird encoding characters

By the way, I don't care about the level of security of this encryption, I care about performance more.


回答1:


crypto.createCipher takes a password and EVP_BytesToKey to derive a key and IV from that, but pycrypto directly expects a key and IV. You need to use exactly the same procedure.

crypto.createCipher must never be used with CTR-mode, because the key and IV generation are not randomized. Since the CTR-mode is a streaming mode, it will always produce the same key stream which might enable an attacker who only observes multiple ciphertexts that are encrypted with the same password to deduce the plaintext. This is possible because of the resulting many-time pad issue.

If you must use CTR-mode, then you have to use crypto.createCipheriv. If you use the same key, you have to use a different IV every time. This is why this is actually called a nonce for CTR-mode. For AES-CTR, a nonce of 96 bit is a good compromise between security and size of possibly encryptable plaintexts.

var key = "1234567890123456"
var iv = Buffer.concat([crypto.randomBytes(12), Buffer.alloc(4, 0)])
var cipher = crypto.createCipheriv("aes-128-ctr", key, iv)
var ctext = iv.toString('hex') + cipher.update('asasasa','utf8','hex') +  cipher.final('hex')
console.log(ctext)

Example output:

5b88aeb265712b6c8bfa8dbd0000000063012d1e52eb42

The IV is not secret and you have to use the exact same IV during decryption. Usually, it is sent along with the ciphertext by being prefixed to it. It is then sliced off before decryption:

ct = codecs.decode('5b88aeb265712b6c8bfa8dbd0000000063012d1e52eb42', 'hex') # I'm using Python 3
counter = Counter.new(32, prefix=ct[:12], initial_value=0)
cipher = AES.new("1234567890123456", AES.MODE_CTR, counter=counter)
cipher.decrypt(ct[16:])

Output:

b'asasasa'

Keep in mind that a key needs to be randomly chosen. You can generate a random key and keep it in an encoded form in the source code (i.e. as Hex). If you do that, you must not give the source code or the bytecode to anyone that you wouldn't trust the key with.



来源:https://stackoverflow.com/questions/44996742/encrypt-with-node-js-aes-ctr-and-decrypt-with-pycrypto

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!