Estoy intentando cifrar algo de contenido en Python y descifrarlo en una aplicación nodejs.Encriptación y descifrado con python y nodejs
Sin embargo, estoy luchando para que las dos implementaciones de AES funcionen juntas. Aquí es donde estoy.
En nodo:
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);
});
});
Esto produce la salida:
BXSGjDAYKeXlaRXVVJGuREKTPiiXeam8W9e96Nknt3E=
hello world
en 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)
Esto produce la salida
BXSGjDAYKeXlaRXVVJGuRA==
hello world
Claramente están muy cerca, pero el nodo parece estar rellenando la salida con algo. ¿Alguna idea de cómo puedo hacer que los dos interactúen?
1) ¿Usted realmente necesita encriptación basada en contraseña, en lugar de utilizar una clave aleatoria? 2) Si lo hace, no use funciones de hash de iteración única. Use una sal y funciones de derivación de tecla lenta, como PBKDF2, bcrypt o scrypt. – CodesInChaos
3) Tampoco usa el IV correctamente. Debería ser un nuevo valor aleatorio para cada mensaje. También debe tener el mismo tamaño que el tamaño del bloque, y no la mitad del tamaño del bloque, como en su ejemplo. – CodesInChaos
Gracias @CodeInChaos este es código de muestra, así que simplifiqué un poco. La contraseña se genera con PBKDF2 y la IV se asignará al azar en producción. – dave