You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS通过crypto加密的字符串如何在PHP中解密 AES-128-ECB结果不一致

问题根因排查

导致两端加密结果不一致的核心原因有4个:

  • 输出格式不匹配:JS侧指定输出hex编码,PHP侧openssl_encrypt默认返回base64编码,二者编码规则不同直接导致结果看起来完全不同。
  • 密钥长度不符合AES规范:AES-128要求密钥必须为16字节,你使用的密钥aeda94ad8azd仅12字节,Node.js和PHP对长度不足的密钥默认处理逻辑不同,加密核心参数不一致。
  • 填充逻辑冲突:你手动给p2补空格到16字节倍数,但Node.jscrypto和PHPopenssl默认都会自动添加PKCS7填充,相当于额外多了一轮填充,逻辑不统一。
  • JS加密逻辑不完整:Node.js的cipher.update()仅返回当前处理块的加密结果,缺少cipher.final()调用会导致最终结果丢失部分加密内容。

修复方案

方案1:保留原有手动补空格的逻辑,两端统一规则

修正后的JS代码:

const crypto = require('crypto');
const p1 = ['abc', 1, 'def', 'hij'].join('a');
let p2 = crypto.createHash('md5').update(p1, 'ascii').digest('hex') + 'a' + p1 + 'a';
// 原有手动补空格逻辑保留
while (p2.length % 16 > 0) p2 += ' ';

// 密钥补到16字节,和PHP统一用\0填充
const key = Buffer.from('aeda94ad8azd'.padEnd(16, '\0'));
const cipher = crypto.createCipheriv('aes-128-ecb', key, null);
// 关闭默认PKCS7填充,使用手动补的空格
cipher.setAutoPadding(false);
// 拼接update和final的结果,输出hex
let result = cipher.update(p2, 'ascii', 'hex') + cipher.final('hex');
console.log(result);

对应PHP代码:

$p1 = implode('a', ['abc', 1, 'def', 'hij']);
$p2 = hash('md5', $p1, false) . 'a' . $p1 . 'a';
// 原有手动补空格逻辑保留
while (strlen($p2) % 16 > 0) $p2 .= ' ';

// 密钥补到16字节,和JS统一用\0填充
$key = str_pad('aeda94ad8azd', 16, "\0");
// 关闭自动填充,返回原始二进制后转hex和JS输出对齐
$result = bin2hex(openssl_encrypt($p2, 'aes-128-ecb', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING));
echo $result;

方案2:删除手动补空格逻辑,使用默认PKCS7填充(更规范)

修正后的JS代码:

const crypto = require('crypto');
const p1 = ['abc', 1, 'def', 'hij'].join('a');
let p2 = crypto.createHash('md5').update(p1, 'ascii').digest('hex') + 'a' + p1 + 'a';

const key = Buffer.from('aeda94ad8azd'.padEnd(16, '\0'));
const cipher = crypto.createCipheriv('aes-128-ecb', key, null);
let result = cipher.update(p2, 'ascii', 'hex') + cipher.final('hex');
console.log(result);

对应PHP代码:

$p1 = implode('a', ['abc', 1, 'def', 'hij']);
$p2 = hash('md5', $p1, false) . 'a' . $p1 . 'a';

$key = str_pad('aeda94ad8azd', 16, "\0");
$result = bin2hex(openssl_encrypt($p2, 'aes-128-ecb', $key, OPENSSL_RAW_DATA));
echo $result;

注意

AES-ECB模式安全性较低,生产环境建议使用CBC、GCM等更安全的加密模式。

内容的提问来源于stack exchange,提问作者Théo Dulieu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 01:36:03