Node.js 中的 AES 加密 PHP 中的解密.失败.
在 node.js 中,我使用内置函数来加密数据:
In node.js, I use the build in function to encrypt data like that:
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;
输出(加密文本)为:OnNINwXf6U8XmlgKJj48iA==
the output (encrypted text) is: OnNINwXf6U8XmlgKJj48iA==
然后我在 PHP 中使用解密:
Then I use decrypt it in PHP:
$encrypted = 'OnNINwXf6U8XmlgKJj48iA==';
(or $encrypted = base64_decode('OnNINwXf6U8XmlgKJj48iA==') );
$dtext2 = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_CBC);
echo "Decrypted: $dtext2";
我会得到一些我无法解密的有趣字符.我尝试使用/不使用 base64_decode 或 MCRYPT_RIJNDAEL_128 .. 都失败了.
I will get some funny characters, which I can't decrypted it. I tried with/without base64_decode or MCRYPT_RIJNDAEL_128.. all fail.
然后我检查了PHP中的加密方式,它看起来与node.js的输出非常不同.
Then I check how the encryption in PHP, it looks very different from the output from node.js.
$text = "Yes";
$key = "123456";
$eText = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC);
echo "Encrypted: $eText
";
echo "base64: " . base64_encode($eText) . "
";
$dtext1 = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $eText, MCRYPT_MODE_CBC);
echo "Decrypted: $dtext1
";
它可以加密和解密.加密数据为:njCE/fk3pLD1/JfiQuyVa6w5H+Qb/utBIT3m7LAcetM=
It can encrypt and decrypt. and the encrypted data is : njCE/fk3pLD1/JfiQuyVa6w5H+Qb/utBIT3m7LAcetM=
这与 node.js 的输出非常不同,请告知我如何在 node.js & 之间进行加密和解密.php.ini谢谢.:)
which is very different from the output from node.js please advise how I can encrypt and decrypt between node.js & php. thanks. :)
@Mel 这是我在 PHP 中所拥有的:
@Mel here is what I have in 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
";
echo "base64: " . base64_encode($eText) . "
";
/* 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) . "
";
然而,它仍然不起作用.
However, it still doesn't work.
PHP 中加密的 base 64 为:80022AGM4/4qQtiGU5oJDQ==nodejs中加密的base 64为:EoYRm5SCK7EPe847CwkffQ==
The encrypted base 64 in PHP is: 80022AGM4/4qQtiGU5oJDQ== The encrypted base 64 in nodejs is: EoYRm5SCK7EPe847CwkffQ==
因此,我无法在 PHP 中解密 nodejs 之一.
thus, i can't decrypt the nodejs one in PHP.
不知道是不是因为nodejs不需要$iv?
I wonder if it is because nodejs doesn't require $iv?
推荐答案
晚了七个月,但我也在为此苦苦挣扎,并找到了解决方案.显然,PHP 用零字节填充输入以使其大小成为块大小的倍数.例如,使用 AES-128,14 字节输入contrabassists"将填充两个零字节,如下所示:
Seven months late, but I was struggling with this as well, and found a solution. Apparently, PHP pads the input with zero bytes to make its size a multiple of the block size. For example, using AES-128, the 14 byte input "contrabassists" will be padded with two zero bytes, like this:
"contrabassists"
一个 N*blocksize 字节的输入被单独留下.
A N*blocksize byte input is left alone.
然而,标准的 Node 加密函数使用一种不同的填充方案,称为 PKCS5.PKCS5 不添加零,但会添加填充的长度,因此再次使用 AES-128,低音提琴手"将变为:
The standard Node crypto functions, however, use a different padding scheme called PKCS5. PKCS5 doesn't add zeros, but adds the length of the padding, so again using AES-128, "contrabassists" would become:
"contrabassists22"
即使是 N*blocksize 字节输入也会在 PKCS5 中填充.否则,解码后无法去除填充.输入的光谱日光图"将变为:
Even a N*blocksize byte input gets padded in PKCS5. Otherwise, it's impossible to remove the padding after decoding. The input "spectroheliogram" would then become:
"spectroheliogram16161616161616161616161616161616"
要使 PHP m_crypt 加密与 Node 解密兼容,您必须自己填充输入:
To make PHP m_crypt encryption compatible with Node decryption, you'll have to pad the input yourself:
$pad = $blocksize - (strlen($input) % $blocksize);
$input = $input . str_repeat(chr($pad), $pad);
反之,您必须读取解码数据的最后一个字节并自行切断填充.
The other way around, you'll have to read the last byte of the decoded data and cut off the padding yourself.
示例函数:(2012 年 1 月 14 日添加)
Example functions: (added 01-14-2012)
在 PHP 中,此函数将返回 AES-128 加密的十六进制编码数据,节点可以解密:
In PHP, this function would return AES-128 encrypted, hex encoded data that can be decrypted by 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));
}
在 Node 中,以下将解密数据:
In Node, the following would decrypt the data:
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('')
}
我还没有做过相反的事情,但是一旦你理解了填充方案,它应该很简单.我没有对 key/iv 生成做任何假设.
I haven't done the reverse yet, but it should be straightforward once you understand the padding scheme. I haven't made any assumptions about key/iv generation.
相关文章