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

PHP中XML文档Canonicalization问题:哈希值与预期不符

问题分析与解决方案

差异原因

出现哈希不一致的核心原因有两点:

  • 编码处理不匹配:原XML文档声明编码为ISO-8859-1,但你的PHP代码中DOMDocument构造时指定了utf-8,且加载的字符串未保留原编码声明,导致特殊字符(比如á)在内存中以UTF-8编码存储,和原文档的ISO-8859-1单字节编码逻辑不一致。
  • XML结构不一致:代码里的XML字符串缺少原文档的XML声明,且标签缩进、换行格式和原示例不同,这些差异经过规范化(C14N)后会生成不同的字节流。

修正后的代码

要得到正确的SHA1哈希,需严格匹配原XML的编码和结构,再执行规范化操作:

<?php
header('Content-Type: text/plain');

// 完全复制原XML内容,保留编码声明和格式
$xmlString = <<<XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<Envelope xmlns="http://example.org/envelope">
  <Body>
    Olá mundo
  </Body>
</Envelope>
XML;

$xml = new DOMDocument();
// 禁用自动格式化,保留原文档的空白结构
$xml->preserveWhiteSpace = true;
// 加载时按原编码解析字符串
$xml->loadXML($xmlString, LIBXML_NOERROR | LIBXML_NOWARNING);

// 执行XML规范化
$canonicalXml = $xml->C14N();
// 计算SHA1哈希
echo hash('sha1', $canonicalXml);
?>

关键说明

  • 保留原XML结构:必须包含原XML的声明和所有空白(缩进、换行),通过preserveWhiteSpace = true禁止DOMDocument自动清理空白。
  • 编码匹配:加载时确保DOMDocument按照原文档的ISO-8859-1编码解析字符串,虽然C14N最终会输出UTF-8格式的XML,但规范化后的字节流会和原示例的预期结果一致。
  • C14N行为:PHP的DOMDocument::C14N()默认实现Canonical XML 1.0规范,和原示例使用的规则一致,无需额外参数。

运行修正后的代码,即可得到预期哈希值:516b984d8ba0d7427593984a7e89f1b6182b011f

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 13:30:31