douwei7203 2017-08-18 12:23
浏览 729
已采纳

在PHP中将PHP openssl_encrypt与空白IV匹配

How can I match the output of openssl_encrypt in JavaScript, when no IV is declared in PHP and a non-compliant key length is used?

PHP

php -r '$value = openssl_encrypt("test", "AES-128-CBC", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); echo $value;'

/u+5lB/VwbMX9U1YY4cnCQ==

JavaScript

iv  = CryptoJS.enc.Utf8.parse("");
var encrypted = CryptoJS.AES.encrypt("test", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa", {iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7});
console.log(encrypted.toString());

U2FsdGVkX19Cn1f6x8C/rJdfwzsZk5m5WWCUrR4z3U4=

console.log(CryptoJS.enc.Base64.stringify(encrypted.ciphertext));

l1/DOxmTmblZYJStHjPdTg==

I can only modify the Javascript code and I need a way to encrypt a string so that it can be decrypted by PHP's openssl_decrypt. It works fine obviously if the string it's encrypted from PHP.

I understand that by not declaring a IV renders the code less secure, but in my particular case it's not a big issue.

I've read in other topics that PHP defaults the padding to Pkcs7, which is why I added it to the JS method.

My current theory is that either the default IV of PHP is the issue or the output of the JS function needs to be further processed. As you can see I tried the Base64.stringify method, but the results are still different.

The sample key I'm using here is of the same length of the actual key.

I'm using https://github.com/sytelus/CryptoJS/blob/master/rollups/aes.js (whatever I use in JS, it needs to be easily distributed like a standalone file, with a relatively small footprint)

  • 写回答

1条回答 默认 最新

  • douzongmu2543 2017-08-18 19:58
    关注

    There are some issues with your code:

    • If you want to use an existing key, then you need to provide a WordArray object to CryptoJS.<cipher>.encrypt. That means it has to be parsed in some way. If you simply provide a string as a "key", then CryptoJS will assume that it is a password, generate a random salt and use EVP_BytesToKey to derive the key and IV from password and salt.
    • Your "key" is 29 characters long. AES only supports three key sizes: 16, 24 and 32 bytes. Since you've used AES-128 in PHP, you need to provide a 16 byte key in CryptoJS so that AES-128 is automatically selected. Remember: a key is supposed to be randomly chosen and be indistinguishable from random noise so that it has some kind of security. If you must print the key in some way, use Hex or Base64 encoding.

    Full example:

    var iv  = CryptoJS.enc.Utf8.parse("");
    var key = CryptoJS.enc.Utf8.parse("aaaaaaaaaaaaaaaa");
    var encrypted = CryptoJS.AES.encrypt("test", key, {
        iv: iv, 
        mode: CryptoJS.mode.CBC, 
        padding: CryptoJS.pad.Pkcs7
    });
    
    console.log(CryptoJS.enc.Base64.stringify(encrypted.ciphertext));
    <script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script>

    </div>
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程
  • ¥15 redis-full-check比较 两个集群的数据出错
  • ¥15 Matlab编程问题
  • ¥15 训练的多模态特征融合模型准确度很低怎么办
  • ¥15 kylin启动报错log4j类冲突
  • ¥15 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大
  • ¥15 import arcpy出现importing _arcgisscripting 找不到相关程序