使用数字签名为 XML 文档签名

可以使用 System.Security.Cryptography.Xml 命名空间中的类通过数字签名对 XML 文档或 XML 文档的部分进行签名。使用 XML 数字签名 (XMLDSIG),您可以验证签名后的数据没有被更改。有关 XMLDSIG 标准的更多信息,请参见万维网联盟 (W3C) 建议 XML Signature Syntax and Processing(XML 签名语法和处理)。

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

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

对 XML 文档进行数字签名

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

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

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

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

    C#
    VB
     
    SignedXml signedXml = new SignedXml(xmlDoc);
    
    
    
  5. 将签名 RSA 密钥添加到 SignedXml 对象。

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

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

    C#
    VB
     
    XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
    reference.AddTransform(env);
    
    
    
  8. 将 Reference 对象添加到 SignedXml 对象中。

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

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

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

    C#
    VB
     
    xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
    
    
    
  12. 保存文档。

    C#
    VB
     
    xmlDoc.Save("test.xml");
    
    
    
示例
 

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

 
 
<root>
    <creditcard>
        <number>19834209</number>
        <expiry>02/02/2002</expiry>
    </creditcard>
</root>
C#
VB
 
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 xmlDoc, RSA Key)
    {
        // Check arguments.
        if (xmlDoc == null)
            throw new ArgumentException("xmlDoc");
        if (Key == null)
            throw new ArgumentException("Key");

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

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

        // 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.
        xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));

    }
}

posted on 2014-10-05 03:24  荣锋亮  阅读(1470)  评论(0编辑  收藏  举报

导航