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

PHP与Shell通过OpenSSL加密字符串的结果差异及问题排查

PHP与Shell AES-256-CBC加密结果不一致的排查与修复

核心问题分析

两段代码的核心差异在于密钥/IV的格式处理逻辑不匹配,以及哈希值提取方式错误:

  1. 参数格式差异:
    • PHP的openssl_encrypt接收$key和$iv为原始二进制字节串,但原代码错误地使用了sha256哈希的十六进制字符串片段,而非原始二进制哈希。
    • Shell的openssl enc -K/-iv参数要求传入原始二进制数据的十六进制表示:AES-256需要32字节密钥(对应64位十六进制),CBC模式IV需要16字节(对应32位十六进制)。原Shell代码只取了32位/16位十六进制片段,openssl自动补0到要求长度,导致实际密钥/IV与PHP完全不符。
  2. 哈希提取逻辑错误:
    原代码试图生成32字节密钥、16字节IV,但实际取的是十六进制字符串的片段,而非对应长度的原始二进制哈希。

修复方案

修复PHP代码

修改哈希提取逻辑,获取原始二进制哈希值:

<?php
$encrypt_method = "AES-256-CBC";
$secret_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$secret_iv = 'YYYYYYYYY';

// 获取32字节原始二进制密钥(完整sha256哈希)
$key = hash('sha256', $secret_key, true);
// 获取16字节原始二进制IV(sha256哈希的前16字节)
$iv = substr(hash('sha256', $secret_iv, true), 0, 16);

$string = file_get_contents('plaintext.txt');
$output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
file_put_contents('ciphertext.base64', $output);
?>

说明:hash函数第三个参数设为true时,返回原始二进制哈希,而非十六进制字符串,符合openssl_encrypt的参数要求。

修复Shell代码

修改哈希提取逻辑,取符合长度要求的十六进制字符串:

key='XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
secret_iv='YYYYYYYYY'

# 取完整64位十六进制sha256哈希(对应32字节密钥)
keyhash=$(echo -n "$key" | sha256sum | cut -c 1-64)
# 取前32位十六进制sha256哈希(对应16字节IV)
ivhash=$(echo -n "$secret_iv" | sha256sum | cut -c 1-32)

openssl enc -aes-256-cbc -e -K "$keyhash" -iv "$ivhash" -in plaintext.txt -out ciphertext.base64 -base64

说明:此时密钥和IV的十六进制长度完全符合openssl要求,不会触发“hex string is too short”的补0警告。

验证一致性

修复后,两段代码使用的密钥和IV完全匹配:

  • 密钥:$secret_key的完整sha256原始哈希(32字节),PHP直接用二进制,Shell用对应的64位十六进制表示
  • IV:$secret_iv的sha256哈希前16字节原始数据,PHP直接用二进制,Shell用对应的32位十六进制表示
    执行后生成的ciphertext.base64内容完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 18:52:45