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

C#生成XML的SHA256 HMAC与PHP验证结果不一致求助

问题排查与解决方案

哈希不一致的核心原因是C#和PHP处理的XML原始内容不匹配,以下是具体排查点和解决办法:

核心差异点分析

  1. XML内容输出不一致
    C#中XDocument.ToString()与document.Save()的输出存在本质区别:

    • ToString()默认不输出XML声明(如<?xml version="1.0" encoding="utf-8"?>),且输出的是无缩进的紧凑格式
    • Save()默认会输出XML声明,同时自动格式化XML(添加缩进、换行符)
      而PHP读取的是Save()写入的文件内容,和C#哈希用的ToString()内容完全不同。
  2. 编码与BOM问题

    • XDocument.Save()默认使用带BOM的UTF-8编码写入文件,PHP读取时会包含BOM字节(EF BB BF)
    • C#中Encoding.UTF8.GetBytes()生成的是无BOM的字节数组,哈希时不会包含BOM内容

解决方案

方案一:C#使用文件内容计算哈希

直接读取保存后的文件内容进行哈希,确保和PHP读取的是同一份数据:

// 先保存XML文件
document.Save(this.XMLFile);

// 读取保存后的文件内容(指定UTF-8编码兼容带BOM的情况)
string xmlContent = File.ReadAllText(this.XMLFile, Encoding.UTF8);

// 计算HMACSHA256哈希
StringBuilder sha256_Sb = new StringBuilder();
var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes("SERVERHASH-SHA256"));
byte[] hashBytes = hmacsha256.ComputeHash(Encoding.UTF8.GetBytes(xmlContent));
foreach(byte hash256 in hashBytes)
{
    sha256_Sb.Append(hash256.ToString("x2"));
}

MessageBox.Show(sha256_Sb.ToString());

方案二:让C#生成与Save一致的XML字符串

如果不想读取文件,可配置XmlWriterSettings让ToString()输出和Save()完全一致的内容:

XmlWriterSettings settings = new XmlWriterSettings
{
    OmitXmlDeclaration = false, // 强制输出XML声明
    Indent = true, // 开启缩进匹配Save的格式化
    Encoding = Encoding.UTF8
};

StringWriter sw = new StringWriter();
using (XmlWriter writer = XmlWriter.Create(sw, settings))
{
    document.WriteTo(writer);
}
string xmlContent = sw.ToString();

// 计算哈希(逻辑同方案一)
StringBuilder sha256_Sb = new StringBuilder();
var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes("SERVERHASH-SHA256"));
byte[] hashBytes = hmacsha256.ComputeHash(Encoding.UTF8.GetBytes(xmlContent));
foreach(byte hash256 in hashBytes)
{
    sha256_Sb.Append(hash256.ToString("x2"));
}

MessageBox.Show(sha256_Sb.ToString());

PHP端简化调整

无需额外转码,直接读取原始文件内容即可:

$xml = file_get_contents('../files/workorders/y50onuv1_1702700056.xml');
$hash = hash_hmac("SHA256", $xml, "SERVERHASH-SHA256");
echo $hash;

验证步骤

  1. 分别在C#和PHP端输出处理内容的字节长度,确认长度一致
  2. 输出内容的十六进制表示,逐字节对比找到差异位置(若仍不一致)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 02:50:18