【问题标题】:openssl_decrypt PHP to CryptoJSopenssl_decrypt PHP 到 CryptoJS
【发布时间】:2021-03-18 14:44:27
【问题描述】:

在 PHP 中,我使用 openssl_decrypt($encryptData,'AES128',$key, OPENSSL_ZERO_PADDING|OPENSSL_RAW_DATA),我需要在 JS 上使用相同选项的完全相同的东西,所以我使用 CryptoJS 和这个函数 cryptoJS.AES.decrypt(encryptData, key, {padding: cryptoJS.pad.ZeroPadding}).toString()。 使用 PHP,我的解码消息以 C7 开头,并带有其他十六进制字符。但在 JS 中只有十进制值。

这里的 encryptDatakey 在 PHP 和 JS 上的值完全相同。但是 cryptoJS 返回的东西与 PHP 不同。 我不知道可能是什么问题。我尝试使用 UTF8 或 Base64 更改我的值的基础。但没有任何效果。

如何将此功能转换为加密并使其正常工作? 谢谢!

PHP 示例:

$encryptData = hex2bin("D5F630E93F36C21293012D78E5A384F1");
$key = hex2bin("A254FE00A791AA74386E8DEF3712B256");

var_dump(bin2hex(openssl_decrypt($encryptData,'AES128', $key, OPENSSL_ZERO_PADDING|OPENSSL_RAW_DATA)));
//result : c704469332aa61804601008a92dc10e5

JS 示例:(当然 hex2bin 返回与 PHP 相同的输出)

let encData = hex2bin("D5F630E93F36C21293012D78E5A384F1");
let key = hex2bin("A254FE00A791AA74386E8DEF3712B256");
let data = bin2hex(cryptoJS.AES.decrypt(encData, key, {padding: cryptoJS.pad.ZeroPadding}).toString());
console.log(data);
//result : 326638346632336661323135353832343236376139343564 

每次我在 JS 上重新加载时结果都会发生变化。

【问题讨论】:

  • 给一个完整的数据集(明文、密钥和密文)和两个最小的例子来重现这些例子怎么样?

标签: javascript php openssl cryptography cryptojs


【解决方案1】:

CryptoJS 使用WordArray 类型并提供encoders 用于转换,例如Hex 编码器。

在 PHP 代码中,应用了aes128,它是aes-128-cbc 的别名,需要一个IV。如果没有指定,PHP 会隐式使用零向量,必须在 CryptoJS 代码中明确指定。 CBC模式本身不需要明确指定,因为它是default

此外,PHP 代码禁用填充,必须在 CryptoJS 代码中明确指定,因为 PKCS7 填充是 default。请注意,OPENSSL_ZERO_PADDING 不启用零填充,但禁用填充,即 CryptoJS 对应物是 NoPadding

您的 CryptoJS 代码必须进行如下更改才能在功能上等同于 PHP 代码:

let encData = CryptoJS.enc.Hex.parse("D5F630E93F36C21293012D78E5A384F1");
let key = CryptoJS.enc.Hex.parse("A254FE00A791AA74386E8DEF3712B256");
let iv = CryptoJS.enc.Hex.parse("00000000000000000000000000000000");
let data = CryptoJS.AES.decrypt(
    {ciphertext: encData}, 
    key, 
    {iv: iv, padding: CryptoJS.pad.NoPadding}
).toString(CryptoJS.enc.Hex);
console.log(data); // c704469332aa61804601008a92dc10e5
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>

另请注意,静态 IV 是不安全的。通常,每次加密都会生成一个随机 IV,它不是秘密的,并与密文(通常是连接的)一起传递给接收者,接收者在解密之前将两者分开。

【讨论】:

  • 太棒了!你拯救了我的一天。我在想 PHP 的默认模式是 CBC 而不是 ECB。
  • @Develogg - 你是对的 aes128aes-128-cbc 的别名。由于缺少IV,我感到困惑。但是 PHP 隐式地应用了一个零向量。这给出了与 ECB 模式相同的结果第一个块,因此解密在这里也可以工作(因为只有一个块)。我已经相应地修改了我的答案。
猜你喜欢
  • 2017-10-19
  • 1970-01-01
  • 1970-01-01
  • 2017-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多