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

OpenSSL库:aes-256-cbc与aes-256-cbc-hmac-sha256使用差异疑问

AES-256-CBC与AES-256-CBC-HMAC-SHA256加密无差异的原因分析

问题场景

openssl_get_cipher_methods()返回的算法列表同时包含aes-256-cbc和aes-256-cbc-hmac-sha256,但调用openssl_encrypt()测试时,两者输出完全一致,测试代码如下:

php > echo openssl_encrypt('hello world!', 'aes-256-cbc', '5823r4s5b36f45f333c7be91e6819b91', 0, base64_decode('7urdW9TS74FKFgHFSb2sqA=='), $tag);
JmeNeIeK2yU3pVUMGX5VsQ==
php > echo $tag;

php > echo openssl_encrypt('hello world!', 'aes-256-cbc-hmac-sha256', '5823r4s5b36f45f333c7be91e6819b91', 0, base64_decode('7urdW9TS74FKFgHFSb2sqA=='), $tag);
JmeNeIeK2yU3pVUMGX5VsQ==
php > echo $tag;

核心原因

你忽略了aes-256-cbc-hmac-sha256算法的两个关键特性,导致它没有启用自带的HMAC校验逻辑,最终和普通aes-256-cbc表现一致:

1. 密钥长度要求不同

aes-256-cbc-hmac-sha256是加密+签名一体化的算法,它要求密钥总长度为64字节:

  • 前32字节:用于AES-256-CBC加密
  • 后32字节:用于HMAC-SHA256签名

而你当前使用的密钥是32字节(字符串5823r4s5b36f45f333c7be91e6819b91共32个字符),长度不满足算法要求,PHP会自动将密钥补全或截断,此时算法会降级为普通AES-256-CBC逻辑运行。

2. 未启用认证加密模式

你调用openssl_encrypt()时使用的options参数为0(默认值),这个选项不会触发算法的HMAC校验功能。要启用aes-256-cbc-hmac-sha256的完整特性,需要传递OPENSSL_RAW_DATA选项,同时确保$tag参数被正确填充,解密时也需要传入该tag来验证数据完整性。

正确使用示例

// 生成64字节的密钥(32字节AES密钥 + 32字节HMAC密钥)
$key = random_bytes(64);
$iv = base64_decode('7urdW9TS74FKFgHFSb2sqA==');
$data = 'hello world!';

// 使用aes-256-cbc-hmac-sha256加密,启用RAW模式
$encrypted = openssl_encrypt($data, 'aes-256-cbc-hmac-sha256', $key, OPENSSL_RAW_DATA, $iv, $tag);
// 加密结果是原始二进制,通常需要base64编码存储
$encryptedBase64 = base64_encode($encrypted);
$tagBase64 = base64_encode($tag);

// 解密时需要传入tag验证
$decrypted = openssl_decrypt(base64_decode($encryptedBase64), 'aes-256-cbc-hmac-sha256', $key, OPENSSL_RAW_DATA, $iv, base64_decode($tagBase64));
echo $decrypted; // 输出hello world!

此时aes-256-cbc-hmac-sha256会同时完成加密和HMAC签名,生成的$tag用于解密时验证数据是否被篡改,而普通aes-256-cbc不会生成这个校验tag。

内容的提问来源于stack exchange,提问作者zer0uno

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 20:18:24