Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/37.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
为什么在node.js中解密使用PHP加密的值时decipherIv.final()失败?_Php_Node.js_Encryption_Openssl_Cryptography - Fatal编程技术网

为什么在node.js中解密使用PHP加密的值时decipherIv.final()失败?

为什么在node.js中解密使用PHP加密的值时decipherIv.final()失败?,php,node.js,encryption,openssl,cryptography,Php,Node.js,Encryption,Openssl,Cryptography,PHP版本:5.6.39 Node.js版本:10.9.0 目标:使用PHP加密,使用Node.js解密 难点:我目前假设到OpenSSL的PHP和Node.js绑定都使用PKCS7填充PHP和Node.js是否使用与OpenSSL不兼容的绑定? PHP加密/解密代码示例: class SymmetricEncryption { public static function simpleEncrypt($key, $plaintext) { $iv = openssl_ran

PHP版本:5.6.39

Node.js版本:10.9.0

目标:使用PHP加密,使用Node.js解密

难点:我目前假设到OpenSSL的PHP和Node.js绑定都使用PKCS7填充PHP和Node.js是否使用与OpenSSL不兼容的绑定?

PHP加密/解密代码示例:

class SymmetricEncryption {

   public static function simpleEncrypt($key, $plaintext) {
      $iv = openssl_random_pseudo_bytes(16);
      $ciphertext = openssl_encrypt($plaintext, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv)

      return base64_encode($iv) . "." . base64_encode($ciphertext);
   }

   public static function simpleDecrypt($key, $token) {
       list($iv, $ciphertext) = explode(".", $token);

        return openssl_decrypt(
           base64_decode($ciphertext),
           "aes-256-cbc",
           $key,
           OPENSSL_RAW_DATA,
           base64_decode($iv)
        );
   }
}
class SymmetricEncryption {

    static simpleEncrypt(key: Buffer, plaintext: string): string {
        const iv = randomBytes(16)
        const cipher = createCipheriv('aes-256-cbc', key, iv)
        const encrypted = cipher.update(plaintext)
        const token = Buffer.concat([encrypted, cipher.final()])

        return iv.toString('base64') + "." + token.toString('base64')
    }

    static simpleDecrypt(key: Buffer, token: string): string {
        const [iv, ciphertext] = token.split(".").map(piece => Buffer.from(piece, 'base64'))
        const decipher = createDecipheriv('aes-256-cbc', key, iv)
        const output = decipher.update(ciphertext)
        return Buffer.concat([output, decipher.final()]).toString('utf8')
    }
}
示例Node.js加密/解密代码:

class SymmetricEncryption {

   public static function simpleEncrypt($key, $plaintext) {
      $iv = openssl_random_pseudo_bytes(16);
      $ciphertext = openssl_encrypt($plaintext, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv)

      return base64_encode($iv) . "." . base64_encode($ciphertext);
   }

   public static function simpleDecrypt($key, $token) {
       list($iv, $ciphertext) = explode(".", $token);

        return openssl_decrypt(
           base64_decode($ciphertext),
           "aes-256-cbc",
           $key,
           OPENSSL_RAW_DATA,
           base64_decode($iv)
        );
   }
}
class SymmetricEncryption {

    static simpleEncrypt(key: Buffer, plaintext: string): string {
        const iv = randomBytes(16)
        const cipher = createCipheriv('aes-256-cbc', key, iv)
        const encrypted = cipher.update(plaintext)
        const token = Buffer.concat([encrypted, cipher.final()])

        return iv.toString('base64') + "." + token.toString('base64')
    }

    static simpleDecrypt(key: Buffer, token: string): string {
        const [iv, ciphertext] = token.split(".").map(piece => Buffer.from(piece, 'base64'))
        const decipher = createDecipheriv('aes-256-cbc', key, iv)
        const output = decipher.update(ciphertext)
        return Buffer.concat([output, decipher.final()]).toString('utf8')
    }
}
我已经成功地独立测试了每个实现,但在PHP中加密并在node.js中解密时,我得到以下错误:

Error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
堆栈跟踪将我指向有问题的行,即
simpledcrypt
方法中的
decipher.final()

我正在使用以下(失败的)单元测试来验证我的实现

it('should be able to decrypt values from php', () => {
    const testAesKey = Buffer.from('9E9CEB8356ED0212C37B4D8CEA7C04B6239175420203AF7A345527AF9ADB0EB8', 'hex')
    const phpToken = 'oMhL/oIPAGQdMvphMyWdJw==.bELyRSIwy+nQGIyLj+aN8A=='
    const decrypted = SymmetricEncryption.simpleDecrypt(testAesKey, phpToken)
    expect(decrypted).toBe('hello world')
})
我在这里使用的
phpToken
变量是使用以下代码创建的:

$testAesKey = "9E9CEB8356ED0212C37B4D8CEA7C04B6239175420203AF7A345527AF9ADB0EB8";

echo SymmetricEncryption::simpleEncrypt($testAesKey, "hello world");

我怀疑您的问题是由如何在PHP中传递密钥引起的。的文档没有指定将键解释为十六进制的任何位置。但是,它确实会截断过长的键

这里可能发生的情况是,PHP将64个字符的十六进制字符串截断为32个字节,并使用这些字节作为键。在使用PHP键之前,尝试使用
hex2bin
——这应该可以解决您的问题

$testAesKey = hex2bin("9E9CEB8356ED0212C37B4D8CEA7C04B6239175420203AF7A345527AF9ADB0EB8");

您能否确认如何将密钥传递给
openssl\u encrypt
?例如,在您的PHP测试中,将什么值
$key
传递给
simpleEncrypt
?@Lukejoshuai更新了问题,以显示我如何在PHP中生成令牌。谢谢你看!我认为你的问题可能与此有关。请看下面我的答案。嘿@LukeJoshuaPark,我昨晚试着发表评论,但看起来好像没有保存。你说得对,我想说声谢谢!