C#如何使用SignedXml类签名XML文档

来源:站长站作者:USDT程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《C#如何使用SignedXml类签名XML文档》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#如何使用SignedXml类签名XML文档》有用,将其分享出去将是对创作者最好的鼓励。

在C#开发中,处理XML文档的数字签名时,SignedXml类是最常用的工具,它封装了XML数字签名规范的大部分实现,能够方便地完成签名生成和验证工作。下面我们一步步讲解如何使用这个类对XML文档进行签名。

C#如何使用SignedXml类签名XML文档

签名前的准备工作

使用SignedXml类签名XML文档,首先需要准备非对称加密的密钥对,通常我们使用RSA算法生成密钥,也可以使用已有的证书。同时需要明确要签名的XML文档内容,以及签名要覆盖的节点范围。

生成RSA密钥对

我们可以通过RSACryptoServiceProvider类生成RSA密钥,示例代码如下:

using System.Security.Cryptography;

// 生成RSA密钥对,密钥长度2048位
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048))
{
    // 导出公钥,用于验证签名
    string publicKey = rsa.ToXmlString(false);
    // 导出私钥,用于生成签名
    string privateKey = rsa.ToXmlString(true);
    Console.WriteLine("公钥已生成");
    Console.WriteLine("私钥已生成");
}

使用SignedXml签名XML文档

签名的核心步骤包括加载XML文档、创建SignedXml实例、配置签名引用、计算签名并将签名节点插入到XML文档中。

完整签名示例

以下是完整的XML签名实现代码:

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

public class XmlSigner
{
    /// <summary>
    /// 使用RSA私钥签名XML文档
    /// </summary>
    /// <param name="xmlContent">原始XML字符串</param>
    /// <param name="privateKeyXml">RSA私钥的XML字符串</param>
    /// <returns>签名后的XML字符串</returns>
    public static string SignXml(string xmlContent, string privateKeyXml)
    {
        // 加载原始XML文档
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.PreserveWhitespace = true;
        xmlDoc.LoadXml(xmlContent);

        // 创建SignedXml实例,关联要签名的XML文档
        SignedXml signedXml = new SignedXml(xmlDoc);
        // 设置签名的密钥,使用RSA私钥
        using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
        {
            rsa.FromXmlString(privateKeyXml);
            signedXml.SigningKey = rsa;
        }

        // 创建签名引用,指定签名覆盖整个XML文档
        Reference reference = new Reference();
        reference.Uri = ""; // 空字符串表示签名整个文档

        // 添加XML规范化转换,确保签名的一致性
        XmlDsigEnvelopedSignatureTransform envTransform = new XmlDsigEnvelopedSignatureTransform();
        reference.AddTransform(envTransform);
        XmlDsigC14NTransform c14nTransform = new XmlDsigC14NTransform();
        reference.AddTransform(c14nTransform);

        // 将引用添加到SignedXml实例
        signedXml.AddReference(reference);

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

        // 获取签名节点并插入到XML文档中
        XmlElement signatureElement = signedXml.GetXml();
        // 将签名节点添加到文档的根节点下
        xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(signatureElement, true));

        return xmlDoc.OuterXml;
    }
}

调用签名方法

我们可以构造一个简单的XML文档,调用上面的签名方法进行测试:

class Program
{
    static void Main(string[] args)
    {
        // 原始XML内容
        string originalXml = @"<?xml version=""1.0"" encoding=""utf-8""?>
<user>
  <id>1001</id>
  <name>张三</name>
  <age>25</age>
</user>";

        // 生成RSA密钥对
        using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048))
        {
            string privateKey = rsa.ToXmlString(true);
            // 调用签名方法
            string signedXml = XmlSigner.SignXml(originalXml, privateKey);
            Console.WriteLine("签名后的XML内容:");
            Console.WriteLine(signedXml);
        }
    }
}

验证XML签名

签名完成后,我们还需要验证签名的有效性,确保XML文档没有被篡改,并且签名是由对应的私钥生成的。

签名验证实现

验证签名的代码示例如下:

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

public class XmlVerifier
{
    /// <summary>
    /// 验证XML文档的签名
    /// </summary>
    /// <param name="signedXmlContent">签名后的XML字符串</param>
    /// <param name="publicKeyXml">RSA公钥的XML字符串</param>
    /// <returns>签名是否有效</returns>
    public static bool VerifyXml(string signedXmlContent, string publicKeyXml)
    {
        // 加载签名后的XML文档
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.PreserveWhitespace = true;
        xmlDoc.LoadXml(signedXmlContent);

        // 创建SignedXml实例,关联要验证的XML文档
        SignedXml signedXml = new SignedXml(xmlDoc);
        // 获取XML中的签名节点
        XmlNodeList signatureNodeList = xmlDoc.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#");
        if (signatureNodeList.Count == 0)
        {
            throw new Exception("XML文档中未找到签名节点");
        }
        // 加载签名节点
        signedXml.LoadXml((XmlElement)signatureNodeList[0]);

        // 设置验证用的公钥
        using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
        {
            rsa.FromXmlString(publicKeyXml);
            signedXml.CheckSignature(rsa);
        }

        // 验证签名
        return signedXml.CheckSignature();
    }
}

调用验证方法

使用之前生成的公钥验证签名:

class Program
{
    static void Main(string[] args)
    {
        // 假设signedXml是之前签名得到的XML字符串,publicKey是之前生成的公钥
        string signedXml = "签名后的XML内容";
        string publicKey = "生成的RSA公钥XML字符串";

        bool isValid = XmlVerifier.VerifyXml(signedXml, publicKey);
        if (isValid)
        {
            Console.WriteLine("XML签名验证通过,文档未被篡改");
        }
        else
        {
            Console.WriteLine("XML签名验证失败,文档可能被篡改");
        }
    }
}

注意事项

  • 签名前需要设置XmlDocumentPreserveWhitespace属性为true,避免空白字符变化导致签名验证失败。
  • 如果使用证书进行签名,可以将证书的私钥赋值给SignedXml.SigningKey,验证时使用证书的公钥即可。
  • 签名引用的Uri属性可以根据需求调整,比如指定某个节点的ID来只签名特定节点。
  • 生产环境中私钥需要妥善保存,避免泄露导致签名被伪造。

C#SignedXmlXML签名数字签名修改时间:2026-06-23 19:15:28

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。