简体   繁体   English

Node.js aes128加密/解密端口到PHP

[英]Node.js aes128 encryption/decryption port to PHP

So in node.js I have an encryption scheme using aes128 and without passing IV. 所以在node.js中,我有一个使用aes128且没有通过IV的加密方案。 An example being the following 一个例子如下

 var cipher = require('crypto').createCipher('aes128','password');
 cipher.update('test','utf8','base64')+cipher.final('base64');

which outputs CjZ3R/tW8jiyLvg+/TE6bA== . 输出CjZ3R/tW8jiyLvg+/TE6bA== The issue is that I can't reproduce this in PHP even though I've tried a bunch of implementations and variations. 问题是,即使我尝试了许多实现和变体,也无法在PHP中重现此问题。

When I then try running this through openssl, I run the following: 然后,当我尝试通过openssl运行它时,我运行以下命令:

 echo "test" | openssl enc -e -aes128 -a -k password

which outputs U2FsdGVkX19Ccfv3SWvuzuZWeov9GDuwx1RMK2HWa/s= which also doesn't match either. 输出U2FsdGVkX19Ccfv3SWvuzuZWeov9GDuwx1RMK2HWa / s =也不匹配。 I have also tried using the -md with all possible options and that didn't match either (they aren't even the same block size). 我还尝试将-md与所有可能的选项一起使用,但都不匹配(它们甚至都不是相同的块大小)。 When running in PHP I've tried hashing the key/not hashing, using padding, using the computed padding on the input where the padded character is the number of padded characters needed (saw something online saying this is what nodejs uses). 在PHP中运行时,我尝试使用填充对键/非哈希进行哈希处理,对输入使用计算出的填充,其中填充字符是所需的填充字符数(在网上看到了一些东西,这就是nodejs所使用的)。 And I have tried setting the IV to the password and also to null bytes but still I can't get a match. 而且我尝试将IV设置为密码并设置为空字节,但仍然无法找到匹配项。

Any suggestions/ideas here? 这里有什么建议/想法吗?

edit: 编辑:

So I just discovered the function openssl_encrypt in php and tried the same test through that and once again got a completely different output (this one now takes exactly the same args as node.js and supposedly they both use openssl): 因此,我刚刚在php中发现了函数openssl_encrypt,并通过该函数尝试了相同的测试,并再次获得了完全不同的输出(此输出现在与node.js完全一样,并且应该都使用openssl):

 openssl_encrypt ( "test" , 'aes128' , "password")

which outputs (already in base64) JleA91MvYHdEdnj3KYHmog== which is at least now matching in block count but still not the same ciphertext. 它输出(已经在base64中) JleA91MvYHdEdnj3KYHmog==至少现在在块计数上匹配,但仍然不是相同的密文。

I should also mention that yes passing an IV to nodejs is an option and might resolve the discrepancy but this scheme in php will be replacing the old one in nodejs which is already live so it must be able to decrypt already created ciphertexts 我还应该提到,是的,可以将IV传递给nodejs是一种选择,并且可以解决该差异,但是php中的此方案将替换已启用的nodejs中的旧方案,因此它必须能够解密已创建的密文

So I figured out the solution. 所以我想出了解决方案。 After looking through the c++ source code of node.js I found that the key and iv are generated using the openssl function EVP_BytesToKey. 浏览完node.js的c ++源代码后,我发现密钥和iv是使用openssl函数EVP_BytesToKey生成的。 After searching for an implementation of this function I found this stack overflow post Encrypting data in Cocoa, decoding in PHP (and vice versa) which contains a version of this function. 搜索此函数的实现后,我发现此堆栈溢出其中包含在Cocoa中加密数据,在PHP中解码(反之亦然) ,其中包含该函数的版本。 Modifying that and adding the fact that the openssl version pads the data with the ascii character equal to the number of bytes needed for padding I came up with the following function which fully matched the nodejs encryption scheme: 进行修改,并添加一个事实,即openssl版本使用等于填充所需字节数的ascii字符填充数据,我想到了以下功能,该功能与nodejs加密方案完全匹配:

function aes128Encrypt($key, $data) {
    $padding = 16 - (strlen($data) % 16);
    $data .= str_repeat(chr($padding), $padding);

    $keySize   = 16;
    $ivSize    = 16;

    $rawKey = $key;
    $genKeyData = '';
    do
    {
        $genKeyData = $genKeyData.md5( $genKeyData.$rawKey, true );
    } while( strlen( $genKeyData ) < ($keySize + $ivSize) );

    $generatedKey = substr( $genKeyData, 0, $keySize );
    $generatedIV  = substr( $genKeyData, $keySize, $ivSize );

    print($generatedIV);
    print($generatedKey);

    return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $generatedKey, $data, MCRYPT_MODE_CBC, $generatedIV);
}

which matches exactly with the node.js function: 与node.js函数完全匹配:

 function aes128Encrypt(key,data) {
      var cipher = require('crypto').createCipher('aes128',key);
      return cipher.update(data,'utf8','binary')+cipher.final('binary');
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM