用python和nodejsencryption和解密

我试图encryptionPython中的一些内容,并在nodejs应用程序中对其进行解密。

我努力让两个AES实现协同工作。 这是我在哪里。

在节点中:

var crypto = require('crypto'); var password = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; var input = 'hello world'; var encrypt = function (input, password, callback) { var m = crypto.createHash('md5'); m.update(password) var key = m.digest('hex'); m = crypto.createHash('md5'); m.update(password + key) var iv = m.digest('hex'); // add padding while (input.length % 16 !== 0) { input += ' '; } var data = new Buffer(input, 'utf8').toString('binary'); var cipher = crypto.createCipheriv('aes-256-cbc', key, iv.slice(0,16)); var encrypted = cipher.update(data, 'binary') + cipher.final('binary'); var encoded = new Buffer(encrypted, 'binary').toString('base64'); callback(encoded); }; var decrypt = function (input, password, callback) { // Convert urlsafe base64 to normal base64 var input = input.replace('-', '+').replace('/', '_'); // Convert from base64 to binary string var edata = new Buffer(input, 'base64').toString('binary') // Create key from password var m = crypto.createHash('md5'); m.update(password) var key = m.digest('hex'); // Create iv from password and key m = crypto.createHash('md5'); m.update(password + key) var iv = m.digest('hex'); // Decipher encrypted data var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv.slice(0,16)); var decrypted = decipher.update(edata, 'binary') + decipher.final('binary'); var plaintext = new Buffer(decrypted, 'binary').toString('utf8'); callback(plaintext); }; encrypt(input, password, function (encoded) { console.log(encoded); decrypt(encoded, password, function (output) { console.log(output); }); }); 

这产生输出:

 BXSGjDAYKeXlaRXVVJGuREKTPiiXeam8W9e96Nknt3E= hello world 

在python中

 from Crypto.Cipher import AES from hashlib import md5 import base64 password = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' input = 'hello world' def _encrypt(data, nonce, password): m = md5() m.update(password) key = m.hexdigest() m = md5() m.update(password + key) iv = m.hexdigest() # pad to 16 bytes data = data + " " * (16 - len(data) % 16) aes = AES.new(key, AES.MODE_CBC, iv[:16]) encrypted = aes.encrypt(data) return base64.urlsafe_b64encode(encrypted) def _decrypt(edata, nonce, password): edata = base64.urlsafe_b64decode(edata) m = md5() m.update(password) key = m.hexdigest() m = md5() m.update(password + key) iv = m.hexdigest() aes = AES.new(key, AES.MODE_CBC, iv[:16]) return aes.decrypt(edata) output = _encrypt(input, "", password) print(output) plaintext = _decrypt(output, "", password) print(plaintext) 

这产生输出

 BXSGjDAYKeXlaRXVVJGuRA== hello world 

显然他们非常接近,但节点似乎正在用输出填充输出。 任何想法,我可以让这两个互操作?

好吧,我已经知道了,节点使用OpenSSL,它使用PKCS5做填充。 PyCrypto不处理填充,所以我自己只是在两者中添加“'。

如果我在python代码中添加PKCS5填充,并删除节点代码中的填充,它将起作用。

所以更新的工作代码。 节点:

 var crypto = require('crypto'); var password = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; var input = 'hello world'; var encrypt = function (input, password, callback) { var m = crypto.createHash('md5'); m.update(password) var key = m.digest('hex'); m = crypto.createHash('md5'); m.update(password + key) var iv = m.digest('hex'); var data = new Buffer(input, 'utf8').toString('binary'); var cipher = crypto.createCipheriv('aes-256-cbc', key, iv.slice(0,16)); // UPDATE: crypto changed in v0.10 // https://github.com/joyent/node/wiki/Api-changes-between-v0.8-and-v0.10 var nodev = process.version.match(/^v(\d+)\.(\d+)/); var encrypted; if( nodev[1] === '0' && parseInt(nodev[2]) < 10) { encrypted = cipher.update(data, 'binary') + cipher.final('binary'); } else { encrypted = cipher.update(data, 'utf8', 'binary') + cipher.final('binary'); } var encoded = new Buffer(encrypted, 'binary').toString('base64'); callback(encoded); }; var decrypt = function (input, password, callback) { // Convert urlsafe base64 to normal base64 var input = input.replace(/\-/g, '+').replace(/_/g, '/'); // Convert from base64 to binary string var edata = new Buffer(input, 'base64').toString('binary') // Create key from password var m = crypto.createHash('md5'); m.update(password) var key = m.digest('hex'); // Create iv from password and key m = crypto.createHash('md5'); m.update(password + key) var iv = m.digest('hex'); // Decipher encrypted data var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv.slice(0,16)); // UPDATE: crypto changed in v0.10 // https://github.com/joyent/node/wiki/Api-changes-between-v0.8-and-v0.10 var nodev = process.version.match(/^v(\d+)\.(\d+)/); var decrypted, plaintext; if( nodev[1] === '0' && parseInt(nodev[2]) < 10) { decrypted = decipher.update(edata, 'binary') + decipher.final('binary'); plaintext = new Buffer(decrypted, 'binary').toString('utf8'); } else { plaintext = (decipher.update(edata, 'binary', 'utf8') + decipher.final('utf8')); } callback(plaintext); }; encrypt(input, password, function (encoded) { console.log(encoded); decrypt(encoded, password, function (output) { console.log(output); }); }); 

python:

 from Crypto.Cipher import AES from hashlib import md5 import base64 password = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' input = 'hello world' BLOCK_SIZE = 16 def pad (data): pad = BLOCK_SIZE - len(data) % BLOCK_SIZE return data + pad * chr(pad) def unpad (padded): pad = ord(padded[-1]) return padded[:-pad] def _encrypt(data, nonce, password): m = md5() m.update(password) key = m.hexdigest() m = md5() m.update(password + key) iv = m.hexdigest() data = pad(data) aes = AES.new(key, AES.MODE_CBC, iv[:16]) encrypted = aes.encrypt(data) return base64.urlsafe_b64encode(encrypted) def _decrypt(edata, nonce, password): edata = base64.urlsafe_b64decode(edata) m = md5() m.update(password) key = m.hexdigest() m = md5() m.update(password + key) iv = m.hexdigest() aes = AES.new(key, AES.MODE_CBC, iv[:16]) return unpad(aes.decrypt(edata)) output = _encrypt(input, "", password) print(output) plaintext = _decrypt(output, "", password) print("'" + plaintext + "'")