You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在C#中对XML元素进行签名?附依赖命名空间与示例XML

在C#中对XML元素进行数字签名的完整指南

嘿,我来给你一步步拆解怎么用C#完成XML元素的数字签名,正好用上你指定的那几个命名空间。咱们直接从实操入手,从准备工作到完整代码都给你理得明明白白。

首先,先把必须的命名空间列出来——除了你指定的三个,处理XML文档还得加上System.Xml

using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography.X509Certificates;
using System.Xml;

第一步:搞定签名用的X509证书

数字签名离不开带私钥的X509证书,你可以从PFX文件加载,或者从本地证书存储里取。这里给你举个最常见的PFX加载例子:

// 替换成你的证书路径和密码,确保证书带私钥!
var cert = new X509Certificate2("your-cert.pfx", "your-pfx-password", X509KeyStorageFlags.Exportable);

⚠️ 注意:X509KeyStorageFlags.Exportable是为了让程序能访问证书里的私钥,没有这个的话签名会失败哦。

第二步:加载要处理的XML文档

假设我们要签名的是你提供的那个XML模板,我给它补了个根节点和要签名的数据元素(你可以根据自己的需求调整):

var xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = true; // 这个一定要开!不然XML空白变化会导致签名验证失败

// 加载XML字符串,或者用xmlDoc.Load("your-input.xml")从文件加载
xmlDoc.LoadXml(@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>
<Root>
    <CriticalData Id=""DataToSign"">
        <Content>这是需要保护的敏感数据</Content>
    </CriticalData>
    <Signature Id=""SignatureIdValue"" xmlns=""http://www.w3.org/2000/09/xmldsig#"">
        <!-- 我们会在这里生成签名内容 -->
    </Signature>
</Root>");

第三步:核心签名逻辑

接下来就是生成签名的关键步骤了,我给你逐行注释清楚:

// 初始化SignedXml对象,关联我们的XML文档
var signedXml = new SignedXml(xmlDoc);
// 把证书的私钥绑定到签名对象上——私钥用来生成签名
signedXml.SigningKey = cert.PrivateKey;

// 创建Reference,指定要签名的目标元素(这里用Id定位)
var reference = new Reference();
reference.Uri = "#DataToSign"; // 对应上面CriticalData元素的Id

// 添加规范化转换:确保XML格式统一,避免空白、标签顺序影响签名结果
var c14nTransform = new XmlDsigC14NTransform();
reference.AddTransform(c14nTransform);

// 把Reference加入到SignedInfo里
signedXml.AddReference(reference);

// 添加密钥信息:把证书公钥嵌入签名,方便后续验证签名时用
var keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(cert));
signedXml.KeyInfo = keyInfo;

// 计算签名!
signedXml.ComputeSignature();

如果要签名整个XML文档,只需要把reference.Uri设为空字符串就行。

第四步:把签名插入到XML中

签名生成好后,我们把它替换到原来的Signature节点里:

// 获取生成的签名XML节点
var signatureElement = signedXml.GetXml();

// 用命名空间管理器找到原来的Signature节点(因为XMLDSIG有自己的命名空间)
var nsManager = new XmlNamespaceManager(xmlDoc.NameTable);
nsManager.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");
var existingSignatureNode = xmlDoc.SelectSingleNode("//ds:Signature[@Id='SignatureIdValue']", nsManager);

// 替换节点,或者如果原来没有就直接添加
if (existingSignatureNode != null)
{
    existingSignatureNode.ParentNode.ReplaceChild(xmlDoc.ImportNode(signatureElement, true), existingSignatureNode);
}
else
{
    xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(signatureElement, true));
}

// 保存签名后的XML到文件,或者直接输出
xmlDoc.Save("signed-result.xml");
Console.WriteLine(xmlDoc.OuterXml);

可选:验证签名有效性

签完之后,肯定要确认签名是不是有效的,给你一段验证代码:

var verifySignedXml = new SignedXml(xmlDoc);
var signatureNode = xmlDoc.SelectSingleNode("//ds:Signature", nsManager);
verifySignedXml.LoadXml((XmlElement)signatureNode);

// 验证签名——不需要私钥,用嵌入的公钥就行
bool isValid = verifySignedXml.CheckSignature();
Console.WriteLine($"签名是否有效:{isValid}");

这样一套流程下来,你就能完成XML元素的签名和验证了,完全符合XMLDSIG的标准。

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

火山引擎 最新活动