如何:使用数字签名为 XML 文档签名

更新:2007 年 11 月

可以使用 System.Security.Cryptography.Xml 命名空间中的类通过数字签名对 XML 文档或 XML 文档的部分进行签名。 使用 XML 数字签名 (XMLDSIG),您可以验证签名后的数据没有被更改。 有关 XMLDSIG 标准的更多信息,请参见位于 http://www.w3.org/TR/xmldsig-core/ 上的 WWW 联合会 (W3C) 规范。

此过程中的代码示例演示了如何对整个 XML 文档进行数字签名,以及如何将签名附加到文档中的 <Signature> 元素中。 该示例创建一个 RSA 签名密钥,将该密钥添加到安全密钥容器中,然后使用该密钥对 XML 文档进行数字签名。 然后可以检索该密钥来验证 XML 数字签名,或对另一个 XML 文档进行签名。

有关如何验证使用此过程创建的 XML 数字签名的信息,请参见 如何:验证 XML 文档的数字签名

对 XML 文档进行数字签名

  1. 创建 CspParameters 对象,并指定密钥容器的名称。

    Dim cspParams As New CspParameters()
    cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"
    
    CspParameters cspParams = new CspParameters();
    cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";
    
  2. 使用 RSACryptoServiceProvider 类生成一个对称密钥。 当您将 CspParameters 对象传递给 RSACryptoServiceProvider 类的构造函数时,该密钥将自动保存到密钥容器中。 该密钥将被用来对 XML 文档签名。

    Dim rsaKey As New RSACryptoServiceProvider(cspParams)
    
    RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
    
  3. 通过从磁盘加载 XML 文件创建 XmlDocument 对象。 XmlDocument 对象包含要加密的 XML 元素。

    Dim xmlDoc As New XmlDocument()
    
    ' Load an XML file into the XmlDocument object.
    xmlDoc.PreserveWhitespace = True
    xmlDoc.Load("test.xml")
    
    XmlDocument xmlDoc = new XmlDocument();
    
    // Load an XML file into the XmlDocument object.
    xmlDoc.PreserveWhitespace = true;
    xmlDoc.Load("test.xml");
    
  4. 创建一个新的 SignedXml 对象,并将 XmlDocument 对象传递给它。

    Dim signedXml As New SignedXml(Doc)
    
    SignedXml signedXml = new SignedXml(Doc);
    
  5. 将签名 RSA 密钥添加到 SignedXml 对象。

    signedXml.SigningKey = Key
    
    signedXml.SigningKey = Key;
    
  6. 创建说明签名内容的 Reference 对象。 若要对整个文档进行签名,请将 Uri 属性设置为 ""。

    ' Create a reference to be signed.
    Dim reference As New Reference()
    reference.Uri = ""
    
    // Create a reference to be signed.
    Reference reference = new Reference();
    reference.Uri = "";
    
  7. XmlDsigEnvelopedSignatureTransform 对象添加到 Reference 对象中。 变换使验证工具可以使用与签名工具所用的相同方式表示 XML 数据。 XML 数据可以用不同方式表示,因此这一步对于验证来说至关重要。

    Dim env As New XmlDsigEnvelopedSignatureTransform()
    reference.AddTransform(env)
    
    XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
    reference.AddTransform(env);
    
  8. Reference 对象添加到 SignedXml 对象中。

    signedXml.AddReference(reference)
    
    signedXml.AddReference(reference);
    
  9. 通过调用 ComputeSignature 方法计算签名。

    signedXml.ComputeSignature()
    
    signedXml.ComputeSignature();
    
  10. 检索签名(一个 <Signature> 元素)的 XML 表示形式,并将它保存到一个新的 XmlElement 对象中。

    Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()
    
    XmlElement xmlDigitalSignature = signedXml.GetXml();
    
  11. 将元素追加到 XmlDocument 对象中。

    Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, True))
    
    Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, true));
    
  12. 保存文档。

    xmlDoc.Save("test.xml")
    
    xmlDoc.Save("test.xml");
    

示例

Imports System
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Xml



Module SignXML


    Sub Main(ByVal args() As String)
        Try
            ' Create a new CspParameters object to specify
            ' a key container.
            Dim cspParams As New CspParameters()
            cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"
            ' Create a new RSA signing key and save it in the container. 
            Dim rsaKey As New RSACryptoServiceProvider(cspParams)
            ' Create a new XML document.
            Dim xmlDoc As New XmlDocument()

            ' Load an XML file into the XmlDocument object.
            xmlDoc.PreserveWhitespace = True
            xmlDoc.Load("test.xml")
            ' Sign the XML document. 
            SignXml(xmlDoc, rsaKey)

            Console.WriteLine("XML file signed.")

            ' Save the document.
            xmlDoc.Save("test.xml")


        Catch e As Exception
            Console.WriteLine(e.Message)
        End Try

    End Sub



    ' Sign an XML file. 
    ' This document cannot be verified unless the verifying 
    ' code has the key with which it was signed.
    Sub SignXml(ByVal Doc As XmlDocument, ByVal Key As RSA)
        ' Check arguments.
        If Doc Is Nothing Then
            Throw New ArgumentException("Doc")
        End If
        If Key Is Nothing Then
            Throw New ArgumentException("Key")
        End If
        ' Create a SignedXml object.
        Dim signedXml As New SignedXml(Doc)
        ' Add the key to the SignedXml document.
        signedXml.SigningKey = Key
        ' Create a reference to be signed.
        Dim reference As New Reference()
        reference.Uri = ""
        ' Add an enveloped transformation to the reference.
        Dim env As New XmlDsigEnvelopedSignatureTransform()
        reference.AddTransform(env)
        ' Add the reference to the SignedXml object.
        signedXml.AddReference(reference)
        ' Compute the signature.
        signedXml.ComputeSignature()
        ' Get the XML representation of the signature and save
        ' it to an XmlElement object.
        Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()
        ' Append the element to the XML document.
        Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, True))
    End Sub
End Module
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Xml;

public class SignXML
{

    public static void Main(String[] args)
    {
        try
        {
            // Create a new CspParameters object to specify
            // a key container.
            CspParameters cspParams = new CspParameters();
            cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";

            // Create a new RSA signing key and save it in the container. 
            RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);

            // Create a new XML document.
            XmlDocument xmlDoc = new XmlDocument();

            // Load an XML file into the XmlDocument object.
            xmlDoc.PreserveWhitespace = true;
            xmlDoc.Load("test.xml");

            // Sign the XML document. 
            SignXml(xmlDoc, rsaKey);

            Console.WriteLine("XML file signed.");

            // Save the document.
            xmlDoc.Save("test.xml");



        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }


    // Sign an XML file. 
    // This document cannot be verified unless the verifying 
    // code has the key with which it was signed.
    public static void SignXml(XmlDocument Doc, RSA Key)
    {
        // Check arguments.
        if (Doc == null)
            throw new ArgumentException("Doc");
        if (Key == null)
            throw new ArgumentException("Key");

        // Create a SignedXml object.
        SignedXml signedXml = new SignedXml(Doc);

        // Add the key to the SignedXml document.
        signedXml.SigningKey = Key;

        // Create a reference to be signed.
        Reference reference = new Reference();
        reference.Uri = "";

        // Add an enveloped transformation to the reference.
        XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
        reference.AddTransform(env);

        // Add the reference to the SignedXml object.
        signedXml.AddReference(reference);

        // Compute the signature.
        signedXml.ComputeSignature();

        // Get the XML representation of the signature and save
        // it to an XmlElement object.
        XmlElement xmlDigitalSignature = signedXml.GetXml();

        // Append the element to the XML document.
        Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, true));

    }
}

此示例假定一个名为 "test.xml" 的文件与编译的程序在同一目录中。 您可以将以下 XML 放入名为 test.xml 的文件中,并将它和此示例一起使用。

<root>
    <creditcard>
        <number>19834209</number>
        <expiry>02/02/2002</expiry>
    </creditcard>
</root>

编译代码

安全性

不要用纯文本存储或传输非对称密钥对的私钥。 有关对称和非对称加密密钥的更多信息,请参见 生成加密和解密的密钥

不要将私钥直接嵌入到源代码中。 可以通过使用 MSIL 反汇编程序 (Ildasm.exe),或通过在诸如记事本的文本编辑器中打开程序集,从程序集轻松读取嵌入的密钥。

请参见

任务

如何:验证 XML 文档的数字签名

参考

System.Security.Cryptography.Xml

其他资源

XML 加密和数字签名