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

.NET 8中为XPath转换添加XML命名空间以解决签名异常

问题

使用.NET 8的SignedXml对XML文件签名时,调用ComputeSignature()抛出以下异常:

Unhandled exception. System.Xml.XPath.XPathException: Namespace prefix 'ext' is not defined.
   at MS.Internal.Xml.XPath.CompiledXpathExpr.UndefinedXsltContext.LookupNamespace(String prefix)
   at MS.Internal.Xml.XPath.BaseAxisQuery.SetXsltContext(XsltContext context)
   at MS.Internal.Xml.XPath.CompiledXpathExpr.SetContext(IXmlNamespaceResolver nsResolver)
   at System.Security.Cryptography.Xml.XmlDsigXPathTransform.GetOutput()
   at System.Security.Cryptography.Xml.TransformChain.TransformToOctetStream(Object inputObject, XmlResolver resolver, String baseUri)
   at System.Security.Cryptography.Xml.Reference.CalculateHashValue(XmlDocument document, CanonicalXmlNodeList refList)
   at System.Security.Cryptography.Xml.Reference.UpdateHashValue(XmlDocument document, CanonicalXmlNodeList refList)
   at System.Security.Cryptography.Xml.SignedXml.BuildDigestedReferences()
   at System.Security.Cryptography.Xml.SignedXml.ComputeSignature()

对应的XPath转换片段如下:

<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
    xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
    xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
    xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2">
    <ext:UBLExtensions>
        <ext:UBLExtension>
            <ext:ExtensionURI>urn:oasis:names:specification:ubl:dsig:enveloped:xades</ext:ExtensionURI>
            <ext:ExtensionContent>
                <sig:UBLDocumentSignatures xmlns:sig="urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2"
                    xmlns:sac="urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2"
                    xmlns:sbc="urn:oasis:names:specification:ubl:schema:xsd:SignatureBasicComponents-2">
                    <sac:SignatureInformation>
                        <cbc:ID>urn:oasis:names:specification:ubl:signature:1</cbc:ID>
                        <sbc:ReferencedSignatureID>urn:oasis:names:specification:ubl:signature:Invoice</sbc:ReferencedSignatureID>
                        <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="signature">
                            <ds:SignedInfo>
                                <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
                                <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"/>
                                <ds:Reference Id="invoiceSignedData" URI="">
                                    <ds:Transforms>
                                        <ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
                                            <ds:XPath>not(//ancestor-or-self::ext:UBLExtensions)</ds:XPath>
                                        </ds:Transform>
                                        <ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
                                            <ds:XPath>not(//ancestor-or-self::cac:Signature)</ds:XPath>
                                         </ds:Transform>
                                         <ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
                                            <ds:XPath>not(//ancestor-or-self::cac:AdditionalDocumentReference[cbc:ID='QR'])</ds:XPath>
                                         </ds:Transform>
                                            <ds:Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
                                     </ds:Transforms>
                                     <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
                                     <ds:DigestValue>f+0WCqnPkInI+eL9G3LAry12fTPf+toC9UX07F4fI+s=</ds:DigestValue>
                               </ds:Reference>

原本以为SignedXml会自动识别XPath表达式中的命名空间,但实际需要手动添加,请问如何操作?


解决方案

SignedXml不会自动将XML文档中的命名空间继承到XPath转换的上下文,必须显式为每个XPath转换提供包含所需前缀的命名空间解析器,步骤如下:

  1. 创建命名空间管理器并添加前缀映射
    基于XML文档的NameTable创建XmlNamespaceManager,添加XPath中用到的所有前缀和对应的URI:

    XmlDocument doc = new XmlDocument();
    doc.Load("你的XML文件路径");
    
    var nsManager = new XmlNamespaceManager(doc.NameTable);
    nsManager.AddNamespace("ext", "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2");
    nsManager.AddNamespace("cac", "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2");
    nsManager.AddNamespace("cbc", "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2");
    
  2. 为XPath转换设置上下文
    遍历SignedXml中所有Reference的转换集合,找到XmlDsigXPathTransform类型的实例,将其Context属性设置为刚才创建的命名空间管理器:

    SignedXml signedXml = new SignedXml(doc);
    // 此处省略设置签名密钥、Reference等初始化代码
    
    foreach (Reference reference in signedXml.SignedInfo.References)
    {
        foreach (Transform transform in reference.Transforms)
        {
            if (transform is XmlDsigXPathTransform xpathTransform)
            {
                xpathTransform.Context = nsManager;
            }
        }
    }
    
  3. 执行签名操作
    确保在调用ComputeSignature()之前完成上述上下文设置,之后即可正常执行签名:

    signedXml.ComputeSignature();
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 10:15:53