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 关于#java#的问题,请各位专家解答!
  • ¥15 急matlab编程仿真二阶震荡系统
  • ¥20 TEC-9的数据通路实验
  • ¥15 ue5 .3之前好好的现在只要是激活关卡就会崩溃
  • ¥50 MATLAB实现圆柱体容器内球形颗粒堆积
  • ¥15 python如何将动态的多个子列表,拼接后进行集合的交集
  • ¥20 vitis-ai量化基于pytorch框架下的yolov5模型
  • ¥15 如何实现H5在QQ平台上的二次分享卡片效果?
  • ¥30 求解达问题(有红包)
  • ¥15 请解包一个pak文件