解密来自PHP RIJNDAEL_128 CBC的node.js中的string

我试图解密一个string,以前在CBC模式下使用PHP RIJNDAEL_128使用node.jsencryption第三方软件。

以下是沙箱中以下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', 'user@email.com|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中的实现: NOT WORKING, 见下面的工作解决scheme

 var crypto = require('crypto'); var textToEncrypt = 'user@email.com|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和其他错误消息之间。 有一件事我不太明白的是,显然用于encryption数据的KEY是15个字符长的azertyuiolskzif ,而大多数脚本使用所需的32个string…也许PHP不需要32个string,但节点?

或者也许它与128和256之间的区别有关。或者是由于PHp和Node实现之间的填充差异?

我试图按照PHP中的Encryptstring给出的build议, 并在Node.js中解密,但即使如此,我还没有成功在节点中encryption我的数据。


编辑:

经过更多的挖掘(感谢答案中的解释),我终于在Node.js中进行了解密/解密工作。 但是我还没有成功解密由PHPencryption的东西。

 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 = 'user@email.com|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 "user@email.com|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 )); 

AES密钥必须是128,192或256位中的一个。 有些实现会以某种方式填充密钥,但是这不应该依赖。 把钥匙做成正确的尺寸。