AES中的AES加密在Node.js解密.失败.

mur*_*lai 11 php encryption node.js

在node.js中,我使用build in函数来加密数据,如下所示:

var text = "Yes";
var password = "123456";
var encrypt = crypto.createCipher('aes-256-cbc', password);
var encryptOutput1 = encrypt.update(text, 'base64', 'base64');
var encryptOutput2 = encrypt.final('base64');
var encryptedText = encryptOutput1 + encryptOutput2;
Run Code Online (Sandbox Code Playgroud)

输出(加密文本)是:OnNINwXf6U8XmlgKJj48iA ==

然后我用PHP解密它:

$encrypted = 'OnNINwXf6U8XmlgKJj48iA==';
(or $encrypted = base64_decode('OnNINwXf6U8XmlgKJj48iA==')  );
$dtext2 = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_CBC);
echo "Decrypted: $dtext2";
Run Code Online (Sandbox Code Playgroud)

我会得到一些有趣的角色,我无法解密它.我尝试使用/不使用base64_decode或MCRYPT_RIJNDAEL_128 ..都失败了.

然后我检查PHP中的加密方式,它看起来与node.js的输出有很大的不同.

$text = "Yes";
    $key = "123456"; 


    $eText = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC);
    echo "Encrypted: $eText \n";
    echo "base64: " . base64_encode($eText) . " \n";

    $dtext1 = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $eText, MCRYPT_MODE_CBC);
    echo "Decrypted: $dtext1 \n\n";
Run Code Online (Sandbox Code Playgroud)

它可以加密和解密.加密数据为:njCE/fk3pLD1/JfiQuyVa6w5H + Qb/utBIT3m7LAcetM =

这与node.js的输出有很大不同,请告诉我如何在node.js和php之间加密和解密.谢谢.:)


@Mel这里是我在PHP中的东西:

$text = "Yes";

$key = "32BytesLongKey560123456789ABCDEF"; 
$iv =  "sixteenbyteslong";

/* Open the cipher */
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');

/* Intialize encryption */
mcrypt_generic_init($td, $key, $iv);

/* Encrypt data */
$eText = mcrypt_generic($td, $text);

echo "Encrypted Data: $eText \n";
echo "base64: " . base64_encode($eText) . " \n";

/* Terminate encryption handler */
mcrypt_generic_deinit($td);

/* Initialize encryption module for decryption */
mcrypt_generic_init($td, $key, $iv);

/* Decrypt encrypted string */
$dText = mdecrypt_generic($td, $eText);

/* Terminate decryption handle and close module */
mcrypt_generic_deinit($td);
mcrypt_module_close($td);

/* Show string */
echo trim($dText) . "\n";
Run Code Online (Sandbox Code Playgroud)

但是,它仍然无效.

PHP中的加密基数为64:80022AGM4/4qQtiGU5oJDQ == nodejs中 的加密基数64为:EoYRm5SCK7EPe847CwkffQ ==

因此,我无法在PHP中解密nodejs.

我想知道是不是因为nodejs不需要$ iv?

Mic*_*lus 18

七个月晚了,但我也在努力解决这个问题,并找到了解决方案.显然,PHP使用零字节填充输入,使其大小为块大小的倍数.例如,使用AES-128,14字节输入"contrabassists"将填充两个零字节,如下所示:

"contrabassists\0\0"
Run Code Online (Sandbox Code Playgroud)

AN*blocksize字节输入保持不变.

但是,标准节点加密功能使用称为PKCS5的不同填充方案.PKCS5不会添加零,但会增加填充的长度,因此再次使用AES-128,"contrabassists"将变为:

"contrabassists\2\2"
Run Code Online (Sandbox Code Playgroud)

甚至N*块大小的字节输入也会在PKCS5中填充.否则,解码后无法删除填充.输入"spectroheliogram"将变为:

"spectroheliogram\16\16\16\16\16\16\16\16\16\16\16\16\16\16\16\16"
Run Code Online (Sandbox Code Playgroud)

要使PHP m_crypt加密与Node解密兼容,您必须自己填充输入:

$pad = $blocksize - (strlen($input) % $blocksize);
$input = $input . str_repeat(chr($pad), $pad);
Run Code Online (Sandbox Code Playgroud)

反过来说,你必须读取解码数据的最后一个字节并自己切断填充.

示例功能:(已添加01-14-2012)

在PHP中,此函数将返回AES-128加密的十六进制编码数据,这些数据可由Node解密:

function nodeEncrypt($data, $key, $iv) {
    $blocksize = 16; // AES-128
    $pad = $blocksize - (strlen($data) % $blocksize);
    $data = $data . str_repeat(chr($pad), $pad);
    return bin2hex(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv));
}
Run Code Online (Sandbox Code Playgroud)

在Node中,以下内容将解密数据:

function nodeDecrypt(data, key, iv) {
    var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
    var chunks = []
    chunks.push(decipher.update(data.toString(),'hex','binary'))
    chunks.push(decipher.final('binary'))
    return chunks.join('')
}
Run Code Online (Sandbox Code Playgroud)

我还没有反过来,但是一旦你理解了填充方案,它应该是直截了当的.我没有对key/iv生成做出任何假设.


Mel*_*Mel 1

AES 是固定大小 16 字节 IV 的 rijndael。详细信息请参见此处 不能用于解密。更重要的是,我也无法使用 openssl 解密您的字符串:

% openssl aes-256-cbc -d -in dec.txt -a
enter aes-256-cbc decryption password:
bad magic number
Run Code Online (Sandbox Code Playgroud)

或者使用 php:

$encrypted = 'OnNINwXf6U8XmlgKJj48iA==';
$text = 'Yes';
$pw = '123456';
$decrypted = @openssl_decrypt($encrypted, 'aes-256-cbc', $pw);
var_dump($decrypted);
var_dump(@openssl_encrypt($text, 'aes-256-cbc', $pw, FALSE, $pw));
var_dump(@openssl_encrypt($text, 'aes-256-cbc', $pw));
Run Code Online (Sandbox Code Playgroud)

输出:

bool(false)
string(24) "xrYdu2UyJfxhhEHAKWv30g=="
string(24) "findrYaZVpZWVhEgOEVQwQ=="
Run Code Online (Sandbox Code Playgroud)

因此,node.js 似乎正在使用一些未记录的功能来创建 IV,并且我认为无法在 node.js 中提供 IV。