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

C#中XAdES签名时间戳摘要计算错误,EU DSS验证不通过

XAdES签名时间戳嵌入摘要验证失败的问题排查

我们开发的XAdES签名应用,签名本身可通过EU DSS验证器的正确性校验,但添加时间戳时,验证器提示嵌入的摘要不正确。已确认XML中嵌入的摘要与代码计算结果一致,推测是摘要计算方式存在错误,相关代码如下:

XmlDocument d = new XmlDocument();
d.PreserveWhitespace=true;

// Left out code to load actual XML data

// Make sure we can find the signature in the right namespace 
XmlNamespaceManager nsm = new XmlNamespaceManager(d.NameTable);
nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);

// Find the SignatureValue node (we only have one, but selection could be done cleaner)
XmlNodeList n = d.SelectNodes("//ds:SignatureValue", nsm); 

// ETSI prescribes the use of C14N
XmlDsigExcC14NTransform t = new XmlDsigExcC14NTransform();
t.LoadInput(n);
// We use SHA256 hashing on the canonicalized data
byte[] digest = t.GetDigestedOutput(SHA256.Create());

// The value of the digest variable is being timestamped using BouncyCastle.netcore library
TimeStampRequest request = requestGenerator.Generate(a, digest, BigInteger.ValueOf(100));
using HttpClient client = _hcf.CreateClient();
ByteArrayContent content = new ByteArrayContent(request.GetEncoded());
HttpResponseMessage msg = await client.PostAsync(_config["AppSettings:TimeStampServer"], content);
TimeStampResponse response = new TimeStampResponse(await msg.Content.ReadAsByteArrayAsync());

byte[] dataToEmbed = response.TimeStampToken.GetEncoded();
string algorithmUrlToEmbed = t.Algorithm;
 
// the content of dataToEmbed is embedded into the XML           
// together with the url of the canonicalization (algorithmUrlToEmbed)

问题根源

核心错误是时间戳的摘要计算对象不符合XAdES规范:
ETSI的XAdES标准(如EN 319 132-1)规定,签名时间戳(SignatureTimeStamp)需要对完整的<ds:Signature>节点执行规范化后计算摘要,以此绑定整个签名的完整性。而当前代码仅对<ds:SignatureValue>节点计算摘要,时间戳只绑定了签名值本身,不符合验证器的校验逻辑,因此提示摘要错误。

修正方案

修改代码,将摘要计算对象从<ds:SignatureValue>改为完整的<ds:Signature>节点:

XmlDocument d = new XmlDocument();
d.PreserveWhitespace=true;

// 加载XML数据的代码(省略)

XmlNamespaceManager nsm = new XmlNamespaceManager(d.NameTable);
nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);

// 修正:选择完整的ds:Signature节点
XmlNode signatureNode = d.SelectSingleNode("//ds:Signature", nsm); 

XmlDsigExcC14NTransform t = new XmlDsigExcC14NTransform();
t.LoadInput(signatureNode); // 传入完整签名节点执行规范化
byte[] digest = t.GetDigestedOutput(SHA256.Create());

// 后续时间戳请求代码保持不变
TimeStampRequest request = requestGenerator.Generate(a, digest, BigInteger.ValueOf(100));
using HttpClient client = _hcf.CreateClient();
ByteArrayContent content = new ByteArrayContent(request.GetEncoded());
HttpResponseMessage msg = await client.PostAsync(_config["AppSettings:TimeStampServer"], content);
TimeStampResponse response = new TimeStampResponse(await msg.Content.ReadAsByteArrayAsync());

byte[] dataToEmbed = response.TimeStampToken.GetEncoded();
string algorithmUrlToEmbed = t.Algorithm;
 
// 将dataToEmbed和algorithmUrlToEmbed嵌入XML

额外检查点

  • 确认规范化算法:默认的XmlDsigExcC14NTransform是不带注释的规范化(URL:http://www.w3.org/2001/10/xml-exc-c14n#),如果XAdES配置要求带注释的规范化,需改用new XmlDsigExcC14NTransform(true)
  • 保留空白设置:确保d.PreserveWhitespace=true的配置正确,否则规范化结果会与验证器计算的不一致
  • 算法匹配:确认时间戳请求的摘要算法(此处为SHA256)与签名算法一致,且时间戳服务器支持该算法

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 19:13:17