Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/231.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从PHP RIJNDAEL_128 CBC解密node.js中的字符串_Php_Node.js_Encryption_Aes_Cbc Mode - Fatal编程技术网

从PHP RIJNDAEL_128 CBC解密node.js中的字符串

从PHP RIJNDAEL_128 CBC解密node.js中的字符串,php,node.js,encryption,aes,cbc-mode,Php,Node.js,Encryption,Aes,Cbc Mode,我正在尝试解密一个字符串,该字符串以前由第三方软件在CBC模式下使用PHP RIJNDAEL_128加密,使用node.js 这里是一个沙箱中以下PHP代码的交互式链接,您可以自己编译和查看 PHP源代码: <?php class CryptClass{ private $key; public function __construct($key){ $this->key = $key; } public function cry

我正在尝试解密一个字符串,该字符串以前由第三方软件在CBC模式下使用PHP RIJNDAEL_128加密,使用node.js

这里是一个沙箱中以下PHP代码的交互式链接,您可以自己编译和查看

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');
我尝试了很多方法,但在
无效密钥长度
和其他错误消息之间迷失了方向。有一件事我不太明白,显然用来加密数据的
密钥是
azertyuiolskzif
,它有15个字符长,而大多数脚本使用所需的32个字符字符串。。。也许PHP不需要32个字符的字符串,但Node需要

或者可能与128和256之间的差异有关。还是因为PHp和节点实现之间的填充差异

我试图遵循在上给出的建议,但即使这样,我也没有成功地加密节点中的数据


编辑:

经过进一步的挖掘(感谢答案中的解释),我终于在Node.js中实现了crypt/decrypt。但我还没有成功解密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 = '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位中的一位。有些实现会以某种方式填充键,但不应依赖于此。将密钥设置为正确的大小。

我在最初的实现中没有发言权,我怀疑他们会更改它。。。(这是一个客户)但感谢您提供的信息:)MCRYPT_RIJNDAEL_128中的128是块大小,密钥大小由实际密钥参数的大小决定。这是mcrypt常见且令人困惑的方面。Rijndael支持多个块大小,版本为128,但为AES选择了块大小。见和。
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
));