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

PHP如何实现带盐PBKDF2withHmacSHA1的AES/CBC/PKCS5Padding解密

PHP AES-256-CBC 基于PBKDF2派生密钥解密失败修复方案

已知加密规则

  • 密钥长度:256位
  • 加密模式:AES/CBC/PKCS5Padding
  • 密钥派生算法:PBKDF2withHmacSHA1
  • 密钥派生迭代次数:5000
  • 返回数据格式:iv(初始化向量)、salt(密钥派生盐)、encrypted_data(密文)三个字段均为base64编码

原有代码问题说明

  1. 填充参数配置错误:代码中使用OPENSSL_ZERO_PADDING强制零填充,和加密方使用的PKCS5Padding规则不匹配,直接触发「data not multiple of block length」块长度不匹配错误。AES块大小固定为16字节,PKCS5Padding与OpenSSL默认支持的PKCS7Padding逻辑完全兼容,无需手动指定零填充。
  2. 密文格式参数缺失:代码中已手动将密文做base64解码传入,但未添加OPENSSL_RAW_DATA参数,OpenSSL会默认将传入值再次做base64解码,导致密文格式损坏。
  3. 密钥使用逻辑错误:跳过PBKDF2密钥派生步骤、直接将原始密码作为密钥传入的方式完全不符合加密规则,原始密码长度为49字符,和256位(32字节)要求的密钥长度不匹配,必然输出乱码。

正确实现代码

// 持有的原始解密密码
$password = "supersecretkey";

// 所有base64字段解码为原始二进制
$salt = base64_decode($data['salt']);
$iv = base64_decode($data['iv']);
$ciphertext = base64_decode($data['encrypted_data']);

// 按规则派生256位密钥:SHA1算法、5000次迭代、输出32字节原始二进制结果
$key = hash_pbkdf2(
    "sha1",
    $password,
    $salt,
    5000,
    32,
    true
);

// 解密:传入原始二进制密文,使用默认PKCS填充处理
$plaintext = openssl_decrypt(
    $ciphertext,
    "AES-256-CBC",
    $key,
    OPENSSL_RAW_DATA,
    $iv
);

// 结果校验
if ($plaintext === false) {
    echo "解密失败,错误:" . openssl_error_string();
} else {
    echo "解密结果:" . $plaintext;
}

异常排查点

如果上述代码运行仍失败,逐一校验以下项:

  • 校验iv解码后长度:AES-CBC模式初始化向量固定为16字节,长度不符说明拿到的iv字段存在截断或编码错误
  • 校验派生密钥长度:通过strlen($key)输出长度,必须为32字节才能匹配256位密钥要求
  • 确认密文完整性:encrypted_data字段无截断、无转义导致的字符变更,base64解码后长度必须为16的整数倍

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 23:27:18