Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Node.js AES-256-CBC加密问题_Php_Node.js_Openssl_Cryptography - Fatal编程技术网

Php Node.js AES-256-CBC加密问题

Php Node.js AES-256-CBC加密问题,php,node.js,openssl,cryptography,Php,Node.js,Openssl,Cryptography,我试图根据PHP中给出的一个示例代码创建一个加密字符串,我的主要问题是Node.jscrypto模块不接受长度超过32字节的密钥,但PHPopenssl\u encrypt接受,这似乎就是我得到无效密钥大小错误的原因 以下是我的js代码: let iv = sha1(await HelpersService.makeRandomNumber(null, null, 16)); iv = iv.substr(0, 16); const text = bundledData;

我试图根据PHP中给出的一个示例代码创建一个加密字符串,我的主要问题是Node.js
crypto
模块不接受长度超过32字节的密钥,但PHP
openssl\u encrypt
接受,这似乎就是我得到
无效密钥大小错误的原因

以下是我的js代码:

    let iv = sha1(await HelpersService.makeRandomNumber(null, null, 16));
    iv = iv.substr(0, 16);
    const text = bundledData;
    const password = sha1(this.credentials.appSecret);
    let salt = sha1(await HelpersService.makeRandomNumber(null, null, 4));
    salt = salt.substr(0, 4);
    const key = crypto.createHash('sha256').update(password + salt).digest('hex');
    const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
    let encoded = cipher.update(text, 'utf8', 'hex');
    encoded += cipher.final('hex');
这是PHP示例:

   function generateCashOutAPIHashKey($app_secret ){
      //remove plus(+) sign from gsm number.
      $data = 'text';
      $iv = substr(sha1(mt_rand()), 0, 16);
      $password = sha1($app_secret);
      $salt = substr(sha1(mt_rand()), 0, 4);
      $saltWithPassword = hash('sha256', $password . $salt);
      $encrypted = openssl_encrypt("$data", 'aes-256-cbc', "$saltWithPassword", null, $iv    );
      return $encrypted;
    }

PHP和NodeJS代码中生成的密钥长度为64字节。使用的加密AES-256需要一个32字节的密钥。在PHP代码中,隐式地将64字节键缩短为32字节。在NodeJS代码中,必须明确执行以下操作:

另外,
openssl\u encrypt()
返回默认编码的密文Base64。在NodeJS代码中,结果返回十六进制编码。在这里,您必须在
update()
final()
调用中将输出编码从
'hex'
更改为
'base64'

let encoded = cipher.update(text, 'utf8', 'base64');  
encoded += cipher.final('base64');                    
请注意,PHP参考代码有许多漏洞:

  • 不是加密安全的伪随机数生成器(CSPRNG)。PHP提供加密安全的方法来派生随机IV/salt,例如or
  • 使用SHA-256推断密钥。使用可靠的密钥派生函数(例如)更安全。4字节通常太小
  • 在大多数情况下被认为是不安全的,不能再使用

    • 有人对以下问题有疑问吗

      crypto.createHash('sha256')。更新(密码+ 盐)。消化('hex')。substr(0,32)

      我理解需要由sha256生成的32字节值的意图,但如果您对字符串进行十六进制编码,然后获取字符串的前32个字符,则会显著降低该值。现在有一个32个字符长的字符串,每个字符只有16个可能的值(0-9a-f)。您确实需要一个32字节的值,每个字节有256个可能的值。您已将加密密钥的密钥安全性从预期的256^32(1.1E77)更改为16^32(3.4E38)

      crypto.createHash('sha256')。update('')。digest('hex')
      “e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855”
      crypto.createHash('sha256')。update('')。digest('hex')。substr(0,32)
      ‘e3b0c44298fc1c149afbf4c8996fb924’


      找到一种使用SHA256生成的字节值的方法。

      小的可能不相关的点当作为参数传递时,例如
      openssl\u encrypt($data“,
      a simple
      openssl\u encrypt),您不需要将变量放在引号中($data,
      就足够了HP根据指定的算法隐式截断密钥长度,即AES-256为32字节。NodeJS代码的加密模块不会自动执行此操作,因此必须使用
      substr(0,32)显式截断密钥
      。此外,PHP代码返回加密文本Base64编码,即在NodeJS代码中,必须在
      update()
      final()中更改输出编码
      'hex'
      打电话到
      'base64'
      @Topaco非常感谢!现在一切都好了。你能发布它吗?我会将它标记为回答不客气。我将它作为回答发布。@Gray非常感谢,实际上我明白你的意思,但我只是第三方服务的消费者,他们打算创建这样的密钥,我只是模拟代码,但如果我想在未来做同样的加密,我肯定会考虑你的观点。
      let encoded = cipher.update(text, 'utf8', 'base64');  
      encoded += cipher.final('base64');