Я пытаюсь расшифровать строку, ранее зашифрованную сторонним программным обеспечением, используя PHP RIJNDAEL_128 в режиме CBC, используя node.js.
Вот интерактивная ссылка следующего кода PHP в песочнице, чтобы вы могли скомпилировать и убедиться в этом сами. http://sandbox.onlinephpfunctions.com/code/504a7d052c5b123fac8103a073c05c2ff5f80571>
Исходный код PHP:
<?php
class CryptClass{
private $key;
public function __construct($key){
$this->key = $key;
}
public function cryptage($message){
$key = base64_decode($this->key);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $message, MCRYPT_MODE_CBC, $iv);
$ciphertext = $iv . $ciphertext;
return base64_encode($ciphertext);
}
public function decryptage($message){
$key = base64_decode($this->key);
$iv_size2 = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$ciphertext_dec = base64_decode($message);
$iv_dec = substr($ciphertext_dec, 0, $iv_size2);
$ciphertext_dec = substr($ciphertext_dec, $iv_size2);
$message_decrypt = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key,$ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);
return str_replace("\0", "", $message_decrypt);
}
}
// Secret key and data
define('KEY', 'azertyuiolskzif');
define('DATA', '[email protected]|1477576941|origin.com');
// Crypt
$Crypt = new CryptClass(base64_encode(KEY));
$encodedData = base64_encode($Crypt->cryptage(DATA));
// Decrypt
$decodedData = $Crypt->decryptage(base64_decode($encodedData));
echo 'base64_encode: '.base64_encode(KEY);
echo "\nDATA: ".DATA;
echo "\nDATA length: ".strlen(DATA);
echo "\n\nencodedData: ".$encodedData;
echo "\n\ndata: ".$decodedData;
echo "\n\ndata length: ".strlen($decodedData);
echo "\n\ncrypt/decrypt match?: ".(DATA == $decodedData ? 'yes':'no');
Вот моя реализация в node.js: НЕ РАБОТАЕТ, см. рабочее решение ниже
var crypto = require('crypto');
var textToEncrypt = '[email protected]|1477576941|origin.com';
var encryptionMethod = 'AES-128-CBC';
var secret = "azertyuiolskzif";
var iv = 'aaaabbbbccccdddd';
var encrypt = function (plain_text, encryptionMethod, secret, iv) {
var encryptor = crypto.createCipheriv(encryptionMethod, secret, iv);
return encryptor.update(plain_text, 'utf8', 'base64') + encryptor.final('base64');
};
var decrypt = function (encryptedMessage, encryptionMethod, secret, iv) {
var decryptor = crypto.createDecipheriv(encryptionMethod, secret, iv);
return decryptor.update(encryptedMessage, 'base64', 'utf8') + decryptor.final('utf8');
};
var encryptedMessage = encrypt(textToEncrypt, encryptionMethod, secret, iv);
var decryptedMessage = decrypt(encryptedMessage, encryptionMethod, secret, iv);
console.log(decrypt());
console.log(encryptedMessage);
console.log(decryptedMessage);
Я пробовал много вещей, и я теряюсь здесь между Invalid key length
и другими сообщениями об ошибках. Одна вещь, которую я не совсем понимаю, это то, что KEY
, по-видимому, используемый для шифрования данных, - это azertyuiolskzif
длиной 15 символов, в то время как большинство скриптов используют требуемую строку из 32 символов... Возможно, PHP не нужна строка из 32 символов, но Node делает ?
Или, может быть, это связано с разницей между 128 и 256. Или это связано с разницей заполнения между реализацией PHP и Node?
Я попытался следовать советам, данным в Шифровать строку в PHP и расшифровать в Node.js, но даже при этом мне пока не удалось зашифровать мои данные в узле.
Изменить:
Еще немного покопавшись (и спасибо за объяснения в ответах), я, наконец, заставил шифрование/дешифрование работать в Node.js. Но мне пока не удалось расшифровать что-то, зашифрованное PHP.
var crypto = require('crypto');
var AES = {};
AES.encrypt = function(dataToEncrypt, encryptionMethod, secret, iv, padding) {
var encipher = crypto.createCipheriv(encryptionMethod, secret, iv);
encipher.setAutoPadding(padding || 0); // "true" or "128" would work with aes-128-cbc
var encryptedData = encipher.update(dataToEncrypt, 'utf8', 'base64');
encryptedData += encipher.final('base64');
return encryptedData;
};
AES.decrypt = function(encryptedData, encryptionMethod, secret, iv, padding) {
var decipher = crypto.createDecipheriv(encryptionMethod, secret, iv);
decipher.setAutoPadding(padding || 0); // "true" or "128" would work with aes-128-cbc
var decoded = decipher.update(encryptedData, 'base64', 'utf8');
decoded += decipher.final('utf8');
return decoded;
};
// ----
var textToEncrypt = '[email protected]|1477576941|origin.com';
var secret = "aaaabbbbccccdddd"; // Must be 16 chars
var iv = crypto.randomBytes(16); // Must be 16 chars
var encryptionMethod = 'AES-128-CBC';
// Testing crypt/decrypt using Node.js algorithm.
var encryptedMessage = AES.encrypt(textToEncrypt, encryptionMethod, secret, iv, 128);
var decryptedMessage = AES.decrypt(encryptedMessage, encryptionMethod, secret, iv, 128);
console.log('encryptedMessage', encryptedMessage); // Displays "GWpMWORNKkqlrHJDPuNgSmTKr1vJhaAApHP+ssK3SH5EALTkdWneUZRp9PXNpVQ2"
console.log('decryptedMessage', decryptedMessage); // Displays "[email protected]|1477576941|origin.com"
// Testing decrypt from a string generated by PHP algorithm.
// XXX Doesn't work "Error: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length"
// XXX Probably due to wrong padding between PHP/Node implementation?
var stringToDecode = 'RlM3Wkl3N3JRM0dnaEh4SkdoZWFDRy9mZGRoTnkxNlZUL2IvcHl4TkdzUUlRSXQwSWNwWUZ5OFpaRENZQys3S2t0bFZIUWoweUVsZGxUU21sYU9tS0E9PQ==';
console.log('stringToDecode', stringToDecode);
console.log(AES.decrypt(
stringToDecode,
encryptionMethod, secret, iv, 128
));