duanmuybrtg1231 2012-11-15 07:49
浏览 146
已采纳

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

So in node.js I have an encryption scheme using aes128 and without passing 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==. The issue is that I can't reproduce this in PHP even though I've tried a bunch of implementations and variations.

When I then try running this through openssl, I run the following:

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

which outputs U2FsdGVkX19Ccfv3SWvuzuZWeov9GDuwx1RMK2HWa/s= which also doesn't match either. 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). 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). And I have tried setting the IV to the password and also to null bytes but still I can't get a match.

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):

 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.

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

  • 写回答

1条回答 默认 最新

  • doulvyi2172 2012-11-15 20:08
    关注

    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. 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. 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:

    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:

     function aes128Encrypt(key,data) {
          var cipher = require('crypto').createCipher('aes128',key);
          return cipher.update(data,'utf8','binary')+cipher.final('binary');
     }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 SPSS分类模型实训题步骤
  • ¥15 求解决扩散模型代码问题
  • ¥15 工创大赛太阳能电动车项目零基础要学什么
  • ¥20 limma多组间分析最终p值只有一个
  • ¥15 nopCommerce开发问题
  • ¥15 torch.multiprocessing.spawn.ProcessExitedException: process 1 terminated with signal SIGKILL
  • ¥15 QuartusⅡ15.0编译项目后,output_files中的.jdi、.sld、.sof不更新怎么解决
  • ¥15 pycharm输出和导师的一样,但是标红
  • ¥15 想问问富文本拿到的html怎么转成docx的
  • ¥15 我看了您的文章,遇到了个问题。