
PHP 默认对字符串按 UTF-8 编码后哈希,而 Java Guava 的 hashUnencodedChars() 实际使用 UTF-16LE 编码(非 UTF-8),导致相同字符串产生不同 SHA256 结果;需在 PHP 中显式转为 UTF-16LE 字节序列再哈希。
php 默认对字符串按 utf-8 编码后哈希,而 java guava 的 hashunencodedchars() 实际使用 utf-16le 编码(非 utf-8),导致相同字符串产生不同 sha256 结果;需在 php 中显式转为 utf-16le 字节序列再哈希。
Guava 的 Hashing.sha256().hashUnencodedChars(str) 并非对原始字符串的 UTF-8 字节进行哈希,而是将 Java 字符串(内部以 UTF-16 表示)按 UTF-16LE 字节序直接编码后计算 SHA256。这与 PHP 的 hash('sha256', $str)(默认 UTF-8 编码)存在根本性差异。
要使 PHP 生成与 Guava 完全一致的哈希值,必须模拟 Guava 的编码行为:将字符串先转换为 UTF-16LE 字节流,再对该字节流进行 SHA256 运算。
以下是兼容 Guava 的 PHP 实现:
function guavaSha256($input) {
// 将字符串按 UTF-16LE 编码(含 BOM?Guava 不加 BOM,故使用 'UTF-16LE' 而非 'UTF-16')
$utf16leBytes = mb_convert_encoding($input, 'UTF-16LE', 'UTF-8');
return hash('sha256', $utf16leBytes);
}
$salt = "0123456789012345";
$password = "password";
$combined = $salt . "|" . $password;
echo guavaSha256($combined);
// 输出:818112d34d341ace8b9325fce61e676a125f733e25c28c9ed172c1f7d2c3aa6c ✅
⚠️ 注意事项:
-
mb_convert_encoding()必须启用mbstring扩展(PHP 默认常开启); - 编码目标必须严格为
'UTF-16LE'(小端序),不可用'UTF-16'(可能添加 BOM 或使用平台默认端序); - 输入字符串本身应为合法 UTF-8(与 Java 源数据一致),避免二次编码污染;
- 若字符串含 ASCII 以外字符(如中文),该方案仍准确,因
mb_convert_encoding会正确映射 Unicode 码点到 UTF-16LE 字节。
✅ 验证方式:可借助 Python 快速比对——string.encode('utf-16-le').hex() 的输出应与 PHP 中 $utf16leBytes 的十六进制表示完全一致,再经 hash('sha256', ...) 即得匹配结果。
总结:哈希一致性本质是字节一致性。当跨语言验证哈希时,绝不能假设“字符串相同 = 字节相同”;务必确认双方使用的字符编码、字节序及是否添加 BOM。本例中,修正 PHP 的编码环节即可无缝对接 Guava 的 hashUnencodedChars 行为。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











