如何:使用数字签名为 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 文档进行数字签名
创建 CspParameters 对象,并指定密钥容器的名称。
Dim cspParams As New CspParameters() cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"
CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";
使用 RSACryptoServiceProvider 类生成一个对称密钥。 当您将 CspParameters 对象传递给 RSACryptoServiceProvider 类的构造函数时,该密钥将自动保存到密钥容器中。 该密钥将被用来对 XML 文档签名。
Dim rsaKey As New RSACryptoServiceProvider(cspParams)
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
通过从磁盘加载 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");
创建一个新的 SignedXml 对象,并将 XmlDocument 对象传递给它。
Dim signedXml As New SignedXml(Doc)
SignedXml signedXml = new SignedXml(Doc);
将签名 RSA 密钥添加到 SignedXml 对象。
signedXml.SigningKey = Key
signedXml.SigningKey = Key;
创建说明签名内容的 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 = "";
将 XmlDsigEnvelopedSignatureTransform 对象添加到 Reference 对象中。 变换使验证工具可以使用与签名工具所用的相同方式表示 XML 数据。 XML 数据可以用不同方式表示,因此这一步对于验证来说至关重要。
Dim env As New XmlDsigEnvelopedSignatureTransform() reference.AddTransform(env)
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform(); reference.AddTransform(env);
将 Reference 对象添加到 SignedXml 对象中。
signedXml.AddReference(reference)
signedXml.AddReference(reference);
通过调用 ComputeSignature 方法计算签名。
signedXml.ComputeSignature()
signedXml.ComputeSignature();
检索签名(一个 <Signature> 元素)的 XML 表示形式,并将它保存到一个新的 XmlElement 对象中。
Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()
XmlElement xmlDigitalSignature = signedXml.GetXml();
将元素追加到 XmlDocument 对象中。
Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, True))
Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, true));
保存文档。
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>
编译代码
若要编译此示例,您需要包括对 System.Security.dll 的引用。
包括以下命名空间:System.Xml、System.Security.Cryptography 和 System.Security.Cryptography.Xml。
安全性
不要用纯文本存储或传输非对称密钥对的私钥。 有关对称和非对称加密密钥的更多信息,请参见 生成加密和解密的密钥。
不要将私钥直接嵌入到源代码中。 可以通过使用 MSIL 反汇编程序 (Ildasm.exe),或通过在诸如记事本的文本编辑器中打开程序集,从程序集轻松读取嵌入的密钥。
请参见
任务
参考
System.Security.Cryptography.Xml