SignedXml Класс
Определение
Важно!
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Предоставляет оболочку для основного объекта XML-подписи для упрощения создания XML-подписей.
public ref class SignedXml
public class SignedXml
type SignedXml = class
Public Class SignedXml
- Наследование
-
SignedXml
Примеры
В следующем примере кода показано, как подписать и проверить весь XML-документ с помощью конвертной подписи.
//
// This example signs an XML file using an
// envelope signature. It then verifies the
// signed XML.
//
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.Text;
using System.Xml;
public class SignVerifyEnvelope
{
public static void Main(String[] args)
{
try
{
// Generate a signing key.
RSA Key = RSA.Create();
// Create an XML file to sign.
CreateSomeXml("Example.xml");
Console.WriteLine("New XML file created.");
// Sign the XML that was just created and save it in a
// new file.
SignXmlFile("Example.xml", "signedExample.xml", Key);
Console.WriteLine("XML file signed.");
// Verify the signature of the signed XML.
Console.WriteLine("Verifying signature...");
bool result = VerifyXmlFile("SignedExample.xml", Key);
// Display the results of the signature verification to
// the console.
if(result)
{
Console.WriteLine("The XML signature is valid.");
}
else
{
Console.WriteLine("The XML signature is not valid.");
}
}
catch(CryptographicException e)
{
Console.WriteLine(e.Message);
}
}
// Sign an XML file and save the signature in a new file. This method does not
// save the public key within the XML file. This file cannot be verified unless
// the verifying code has the key with which it was signed.
public static void SignXmlFile(string FileName, string SignedFileName, RSA Key)
{
// Create a new XML document.
XmlDocument doc = new XmlDocument();
// Load the passed XML file using its name.
doc.Load(new XmlTextReader(FileName));
// 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));
if (doc.FirstChild is XmlDeclaration)
{
doc.RemoveChild(doc.FirstChild);
}
// Save the signed XML document to a file specified
// using the passed string.
XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false));
doc.WriteTo(xmltw);
xmltw.Close();
}
// Verify the signature of an XML file against an asymmetric
// algorithm and return the result.
public static Boolean VerifyXmlFile(String Name, RSA Key)
{
// Create a new XML document.
XmlDocument xmlDocument = new XmlDocument();
// Load the passed XML file into the document.
xmlDocument.Load(Name);
// Create a new SignedXml object and pass it
// the XML document class.
SignedXml signedXml = new SignedXml(xmlDocument);
// Find the "Signature" node and create a new
// XmlNodeList object.
XmlNodeList nodeList = xmlDocument.GetElementsByTagName("Signature");
// Load the signature node.
signedXml.LoadXml((XmlElement)nodeList[0]);
// Check the signature and return the result.
return signedXml.CheckSignature(Key);
}
// Create example data to sign.
public static void CreateSomeXml(string FileName)
{
// Create a new XmlDocument object.
XmlDocument document = new XmlDocument();
// Create a new XmlNode object.
XmlNode node = document.CreateNode(XmlNodeType.Element, "", "MyElement", "samples");
// Add some text to the node.
node.InnerText = "Example text to be signed.";
// Append the node to the document.
document.AppendChild(node);
// Save the XML document to the file name specified.
XmlTextWriter xmltw = new XmlTextWriter(FileName, new UTF8Encoding(false));
document.WriteTo(xmltw);
xmltw.Close();
}
}
'
' This example signs an XML file using an
' envelope signature. It then verifies the
' signed XML.
'
Imports System.Security.Cryptography
Imports System.Security.Cryptography.X509Certificates
Imports System.Security.Cryptography.Xml
Imports System.Text
Imports System.Xml
Public Class SignVerifyEnvelope
Overloads Public Shared Sub Main(args() As [String])
Try
' Generate a signing key.
Dim Key As RSA = RSA.Create()
' Create an XML file to sign.
CreateSomeXml("Example.xml")
Console.WriteLine("New XML file created.")
' Sign the XML that was just created and save it in a
' new file.
SignXmlFile("Example.xml", "signedExample.xml", Key)
Console.WriteLine("XML file signed.")
' Verify the signature of the signed XML.
Console.WriteLine("Verifying signature...")
Dim result As Boolean = VerifyXmlFile("SignedExample.xml", Key)
' Display the results of the signature verification to
' the console.
If result Then
Console.WriteLine("The XML signature is valid.")
Else
Console.WriteLine("The XML signature is not valid.")
End If
Catch e As CryptographicException
Console.WriteLine(e.Message)
End Try
End Sub
' Sign an XML file and save the signature in a new file. This method does not
' save the public key within the XML file. This file cannot be verified unless
' the verifying code has the key with which it was signed.
Public Shared Sub SignXmlFile(FileName As String, SignedFileName As String, Key As RSA)
' Create a new XML document.
Dim doc As New XmlDocument()
' Load the passed XML file using its name.
doc.Load(New XmlTextReader(FileName))
' 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))
If TypeOf doc.FirstChild Is XmlDeclaration Then
doc.RemoveChild(doc.FirstChild)
End If
' Save the signed XML document to a file specified
' using the passed string.
Dim xmltw As New XmlTextWriter(SignedFileName, New UTF8Encoding(False))
doc.WriteTo(xmltw)
xmltw.Close()
End Sub
' Verify the signature of an XML file against an asymmetric
' algorithm and return the result.
Public Shared Function VerifyXmlFile(Name As [String], Key As RSA) As [Boolean]
' Create a new XML document.
Dim xmlDocument As New XmlDocument()
' Load the passed XML file into the document.
xmlDocument.Load(Name)
' Create a new SignedXml object and pass it
' the XML document class.
Dim signedXml As New SignedXml(xmlDocument)
' Find the "Signature" node and create a new
' XmlNodeList object.
Dim nodeList As XmlNodeList = xmlDocument.GetElementsByTagName("Signature")
' Load the signature node.
signedXml.LoadXml(CType(nodeList(0), XmlElement))
' Check the signature and return the result.
Return signedXml.CheckSignature(Key)
End Function
' Create example data to sign.
Public Shared Sub CreateSomeXml(FileName As String)
' Create a new XmlDocument object.
Dim document As New XmlDocument()
' Create a new XmlNode object.
Dim node As XmlNode = document.CreateNode(XmlNodeType.Element, "", "MyElement", "samples")
' Add some text to the node.
node.InnerText = "Example text to be signed."
' Append the node to the document.
document.AppendChild(node)
' Save the XML document to the file name specified.
Dim xmltw As New XmlTextWriter(FileName, New UTF8Encoding(False))
document.WriteTo(xmltw)
xmltw.Close()
End Sub
End Class
В следующем примере кода показано, как подписывать и проверять один элемент XML-документа с помощью подписи, вращающейся.
//
// This example signs an XML file using an
// envelope signature. It then verifies the
// signed XML.
//
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Text;
using System.Xml;
public class SignVerifyEnvelope
{
public static void Main(String[] args)
{
// Generate a signing key.
RSA Key = RSA.Create();
try
{
// Specify an element to sign.
string[] elements = { "#tag1" };
// Sign an XML file and save the signature to a
// new file.
SignXmlFile("Test.xml", "SignedExample.xml", Key, elements);
Console.WriteLine("XML file signed.");
// Verify the signature of the signed XML.
Console.WriteLine("Verifying signature...");
bool result = VerifyXmlFile("SignedExample.xml");
// Display the results of the signature verification to
// the console.
if (result)
{
Console.WriteLine("The XML signature is valid.");
}
else
{
Console.WriteLine("The XML signature is not valid.");
}
}
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
}
finally
{
// Clear resources associated with the
// RSA instance.
Key.Clear();
}
}
// Sign an XML file and save the signature in a new file.
public static void SignXmlFile(string FileName, string SignedFileName, RSA Key, string[] ElementsToSign)
{
// Check the arguments.
if (FileName == null)
throw new ArgumentNullException("FileName");
if (SignedFileName == null)
throw new ArgumentNullException("SignedFileName");
if (Key == null)
throw new ArgumentNullException("Key");
if (ElementsToSign == null)
throw new ArgumentNullException("ElementsToSign");
// Create a new XML document.
XmlDocument doc = new XmlDocument();
// Format the document to ignore white spaces.
doc.PreserveWhitespace = false;
// Load the passed XML file using it's name.
doc.Load(new XmlTextReader(FileName));
// Create a SignedXml object.
SignedXml signedXml = new SignedXml(doc);
// Add the key to the SignedXml document.
signedXml.SigningKey = Key;
// Loop through each passed element to sign
// and create a reference.
foreach (string s in ElementsToSign)
{
// Create a reference to be signed.
Reference reference = new Reference();
reference.Uri = s;
// Add an enveloped transformation to the reference.
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
// Add the reference to the SignedXml object.
signedXml.AddReference(reference);
}
// Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new RSAKeyValue((RSA)Key));
signedXml.KeyInfo = keyInfo;
// 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));
if (doc.FirstChild is XmlDeclaration)
{
doc.RemoveChild(doc.FirstChild);
}
// Save the signed XML document to a file specified
// using the passed string.
XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false));
doc.WriteTo(xmltw);
xmltw.Close();
}
// Verify the signature of an XML file and return the result.
public static Boolean VerifyXmlFile(String Name)
{
// Check the arguments.
if (Name == null)
throw new ArgumentNullException("Name");
// Create a new XML document.
XmlDocument xmlDocument = new XmlDocument();
// Format using white spaces.
xmlDocument.PreserveWhitespace = true;
// Load the passed XML file into the document.
xmlDocument.Load(Name);
// Create a new SignedXml object and pass it
// the XML document class.
SignedXml signedXml = new SignedXml(xmlDocument);
// Find the "Signature" node and create a new
// XmlNodeList object.
XmlNodeList nodeList = xmlDocument.GetElementsByTagName("Signature");
// Load the signature node.
signedXml.LoadXml((XmlElement)nodeList[0]);
// Check the signature and return the result.
return signedXml.CheckSignature();
}
}
' This example signs an XML file using an
' envelope signature. It then verifies the
' signed XML.
'
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Text
Imports System.Xml
Module SignVerifyEnvelope
Sub Main(ByVal args() As String)
' Generate a signing key.
Dim Key As RSA = RSA.Create()
Try
' Specify an element to sign.
Dim elements As String() = New String() {"#tag1"}
' Sign an XML file and save the signature to a
' new file.
SignXmlFile("Test.xml", "SignedExample.xml", Key, elements)
Console.WriteLine("XML file signed.")
' Verify the signature of the signed XML.
Console.WriteLine("Verifying signature...")
Dim result As Boolean = VerifyXmlFile("SignedExample.xml")
' Display the results of the signature verification to \
' the console.
If result Then
Console.WriteLine("The XML signature is valid.")
Else
Console.WriteLine("The XML signature is not valid.")
End If
Catch e As CryptographicException
Console.WriteLine(e.Message)
Finally
' Clear resources associated with the
' RSA instance.
Key.Clear()
End Try
End Sub
' Sign an XML file and save the signature in a new file.
Sub SignXmlFile(ByVal FileName As String, ByVal SignedFileName As String, ByVal Key As RSA, ByVal ElementsToSign() As String)
' Check the arguments.
If FileName Is Nothing Then
Throw New ArgumentNullException("FileName")
End If
If SignedFileName Is Nothing Then
Throw New ArgumentNullException("SignedFileName")
End If
If Key Is Nothing Then
Throw New ArgumentNullException("Key")
End If
If ElementsToSign Is Nothing Then
Throw New ArgumentNullException("ElementsToSign")
End If
' Create a new XML document.
Dim doc As New XmlDocument()
' Format the document to ignore white spaces.
doc.PreserveWhitespace = False
' Load the passed XML file using it's name.
doc.Load(New XmlTextReader(FileName))
' Create a SignedXml object.
Dim signedXml As New SignedXml(doc)
' Add the key to the SignedXml document.
signedXml.SigningKey = Key
' Loop through each passed element to sign
' and create a reference.
Dim s As String
For Each s In ElementsToSign
' Create a reference to be signed.
Dim reference As New Reference()
reference.Uri = s
' 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)
Next s
' Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
Dim keyInfo As New KeyInfo()
keyInfo.AddClause(New RSAKeyValue(CType(Key, RSA)))
signedXml.KeyInfo = keyInfo
' 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))
If TypeOf doc.FirstChild Is XmlDeclaration Then
doc.RemoveChild(doc.FirstChild)
End If
' Save the signed XML document to a file specified
' using the passed string.
Dim xmltw As New XmlTextWriter(SignedFileName, New UTF8Encoding(False))
doc.WriteTo(xmltw)
xmltw.Close()
End Sub
' Verify the signature of an XML file and return the result.
Function VerifyXmlFile(ByVal Name As String) As [Boolean]
' Check the arguments.
If Name Is Nothing Then
Throw New ArgumentNullException("Name")
End If
' Create a new XML document.
Dim xmlDocument As New XmlDocument()
' Format using white spaces.
xmlDocument.PreserveWhitespace = True
' Load the passed XML file into the document.
xmlDocument.Load(Name)
' Create a new SignedXml object and pass it
' the XML document class.
Dim signedXml As New SignedXml(xmlDocument)
' Find the "Signature" node and create a new
' XmlNodeList object.
Dim nodeList As XmlNodeList = xmlDocument.GetElementsByTagName("Signature")
' Load the signature node.
signedXml.LoadXml(CType(nodeList(0), XmlElement))
' Check the signature and return the result.
Return signedXml.CheckSignature()
End Function
End Module
Комментарии
Класс SignedXml представляет собой реализацию .NET спецификации синтаксиса и обработки XML-подписи консорциума Всемирной паутины (W3C), также известную как XMLDSIG (Цифровая подпись XML). XMLDSIG — это стандартный, совместимый способ подписывать и проверять все или часть XML-документа или другие данные, которые можно адресовать из универсального идентификатора ресурса (URI).
Используйте класс всякий раз, когда необходимо совместно использовать подписанные SignedXml XML-данные между приложениями или организациями стандартным способом. Все данные, подписанные с помощью этого класса, можно проверить с помощью любой соответствующей реализации спецификации W3C для XMLDSIG.
Класс SignedXml позволяет создавать следующие три типа цифровых подписей XML:
| Тип подписи | Description |
|---|---|
| Обернутая подпись | Подпись содержится в подписанном XML-элементе. |
| Обрамляющая подпись | Подписанный XML содержится в элементе <Signature> . |
| Внутренняя отдельная подпись | Подпись и подписанный XML находятся в одном документе, но ни один элемент не содержит другого. |
Существует также четвертый тип подписи, называемый внешней отсоединенной подписью, которая заключается в том, что данные и подпись находятся в отдельных XML-документах. Внешние отсоединяемые подписи не поддерживаются классом SignedXml .
Структура XML-подписи
XMLDSIG создает <Signature> элемент, содержащий цифровую подпись XML-документа или других данных, которые можно адресовать из URI. Элемент <Signature> может дополнительно содержать сведения о том, где найти ключ, который проверяет подпись и какой алгоритм шифрования использовался для подписи. Базовая структура выглядит следующим образом:
<Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>Base64EncodedValue==</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>AnotherBase64EncodedValue===</SignatureValue>
</Signature>
Основными частями этой структуры являются:
элемент
<CanonicalizationMethod>;Задает правила перезаписи
Signatureэлемента из XML/text в байты для проверки подписи. Значением по умолчанию в .NET является http://www.w3.org/TR/2001/REC-xml-c14n-20010315, которое определяет надежный алгоритм. Этот элемент представлен свойством SignedInfo.CanonicalizationMethod .элемент
<SignatureMethod>;Задает алгоритм, используемый для создания и проверки подписей, который был применен к
<Signature>элементу для создания значения в<SignatureValue>. В предыдущем примере значение http://www.w3.org/2000/09/xmldsig#rsa-sha1 определяет подпись RSA PKCS1 SHA-1. Из-за проблем с столкновением с SHA-1 корпорация Майкрософт рекомендует модель безопасности на основе SHA-256 или более поздней версии. Этот элемент представлен свойством SignatureMethod .элемент
<SignatureValue>;Указывает криптографическую подпись для
<Signature>элемента. Если эта подпись не проверяется, некоторые части<Signature>блока были изменены, и документ считается недопустимым. Если<CanonicalizationMethod>значение является надежным, это значение очень устойчиво к изменению. Этот элемент представлен свойством SignatureValue .URIАтрибут<Reference>элементаУказывает объект данных с помощью ссылки на URI. Этот атрибут представлен свойством Reference.Uri .
Не указывая атрибут
URI, то есть установив свойство Reference.Uri в значениеnull, ожидается, что принимающее приложение должно знать идентификацию объекта. В большинстве случаев URInullможет привести к возникновению исключения. Не используйте универсальныйnullкод ресурса (URI), если приложение не взаимодействует с протоколом, который требует его.Установка атрибута
URIна пустую строку указывает, что подписывается корневой элемент документа, что является одной из форм закрытой подписи.Если значение атрибута
URIначинается с #, то значение должно соответствовать элементу в текущем документе. Эта форма может использоваться с любым из поддерживаемых типов подписей (охваченной подписи, вложенной подписи или внутренней отсоединённой подписи).Что-либо другое считается внешней отсоединенной подписью ресурса и не поддерживается классом SignedXml.
элемент
<Transforms>;Содержит упорядоченный список
<Transform>элементов, описывающих, как подписант обработал объект данных. Алгоритм преобразования аналогичен методу канонизации, но вместо перезаписи<Signature>элемента он перезаписывает содержимое, определяемое атрибутомURI<Reference>элемента. Элемент<Transforms>представлен классом TransformChain .Каждый алгоритм преобразования определяется как прием XML (набор узлов XPath) или байтов в качестве входных данных. Если формат текущих данных отличается от требований к входным данным преобразования, применяются правила преобразования.
Каждый алгоритм преобразования определяется как производящий либо XML, либо байты в качестве выходных данных.
Если выходные данные последнего алгоритма преобразования не определены в байтах (или не были указаны преобразования), метод канонизации используется в качестве неявного преобразования (даже если в элементе был указан
<CanonicalizationMethod>другой алгоритм).Значение http://www.w3.org/2000/09/xmldsig#enveloped-signature алгоритма преобразования кодирует правило, интерпретируемое как удаление
<Signature>элемента из документа. В противном случае средство проверки конвертной сигнатуры будет дайджестировать документ, включая подпись, но подписыватель бы дайджестировал документ до применения подписи, что привело к разным ответам.
элемент
<DigestMethod>;Определяет метод дайджеста (криптографического хэша), который будет применяться к преобразованном содержимому, определяемом атрибутом
URI<Reference>элемента. Это свойство представлено свойством Reference.DigestMethod .
Выбор метода канонизации
Если не выполняется взаимодействие со спецификацией, которая требует использования другого значения, рекомендуется использовать метод канонизации .NET по умолчанию, который является алгоритмом XML-C14N 1.0, значение которого равно http://www.w3.org/TR/2001/REC-xml-c14n-20010315. Алгоритм XML-C14N 1.0 должен поддерживаться всеми реализациями XMLDSIG, особенно так как это неявное окончательное преобразование для применения.
Существуют версии канонических алгоритмов, которые поддерживают сохранение комментариев. Не рекомендуется использовать методы канонизации с сохранением комментариев, так как они нарушают принцип "подписывать то, что видишь". То есть комментарии в элементе <Signature> не изменят логику обработки подписи, а только повлияют на значение сигнатуры. При использовании слабого алгоритма подписи, разрешение включать комментарии предоставляет злоумышленнику лишнюю свободу для создания коллизии хэша, что делает измененный документ внешне легитимным. В .NET Framework по умолчанию поддерживаются только встроенные канонизаторы. Чтобы поддерживать дополнительные или пользовательские канонизаторы, см. свойство SafeCanonicalizationMethods. Если в документе используется метод канонизации, который не находится в коллекции, представленной SafeCanonicalizationMethods свойством, CheckSignature метод вернет false.
Note
Чрезвычайно оборонительное приложение может удалить любые значения из коллекции SafeCanonicalizationMethods, которые, как оно предполагает, подписавшие не будут использовать.
Являются ли ссылочные значения безопасными от изменения?
Да, <Reference> значения безопасны от изменения. .NET проверяет вычисление <SignatureValue> перед обработкой любого из <Reference> значений и связанных с ними преобразований и прекратит выполнение на раннем этапе, чтобы избежать потенциально вредоносных инструкций по обработке.
Выберите элементы для подписывания
Рекомендуется использовать значение "" для URI атрибута (или задать Uri для свойства пустую строку), если это возможно. Это означает, что весь документ рассматривается при вычислении дайджеста, следовательно, весь документ защищен от изменений.
Очень часто встречаются URI значения в виде якорей, таких как #foo, ссылаясь на элемент, атрибут идентификатора которого равен «foo». К сожалению, это легко изменить, так как это включает только содержимое целевого элемента, а не контекста. Злоупотребление этим различием известно как метод оболочки подписи XML (XSW).
Если ваше приложение считает комментарии семантикой (что не распространено при работе с XML), тогда вам следует использовать "#xpointer(/)" вместо "", и "#xpointer(id('foo'))" вместо "#foo". Версии #xpointer интерпретируются с включением комментариев, а формы shortname исключают комментарии.
Если необходимо принять документы, которые защищены только частично, и вы хотите убедиться, что читаете именно то содержимое, которое защищено подписью, используйте указанный метод GetIdElement.
Рекомендации по безопасности элемента KeyInfo
Данные в необязательном <KeyInfo> элементе (то есть свойство KeyInfo), который содержит ключ для проверки подписи, не должны быть доверенными.
В частности, если KeyInfo значение представляет открытый ключ RSA, DSA или ECDSA, документ может быть изменён, несмотря на CheckSignature подпись является допустимой. Это может произойти, так как сущность, выполняющая изменение, просто должна создать новый ключ и повторно подписать документ с этим новым ключом. Таким образом, если приложение не проверяет, является ли открытый ключ ожидаемым значением, документ должен рассматриваться как будто он был изменен. Для этого приложение проверяет открытый ключ, внедренный в документ, и проверяет его в списке известных значений контекста документа. Например, если документ можно интерпретировать как выданный известным пользователем, нужно проверить ключ в списке известных ключей, используемых этим пользователем.
Из-за этого CheckSignature не предназначено для проверки подлинности документов из ненадежного источника самостоятельно. Рекомендуемый шаблон заключается в том, чтобы получить ожидаемый ключ проверки подписи или сертификат заранее из источника, не зависящего от подписанного документа, например из конфигурации приложения или из курированного списка разрешенных ключей или сертификатов подписывающего пользователя, и передать его явным образом в одну из перегрузок, которые принимают ключ:
- CheckSignature(AsymmetricAlgorithm)
- CheckSignature(KeyedHashAlgorithm)
- CheckSignature(X509Certificate2, Boolean)
Если необходимо проверить ключ, внедренный в документ, используйте CheckSignatureReturningKey метод и убедитесь, что возвращенный ключ соответствует ожидаемому значению, прежде чем рассматривать документ как аутентичный. Но для оптимальной безопасности проверьте ключ заранее с помощью одной из перегрузок, перечисленных выше; Перегрузка без CheckSignature() параметров не подходит для проверки ненадежных входных данных.
Кроме того, попробуйте использовать зарегистрированные открытые ключи пользователя, а не читать то, что находится в элементе <KeyInfo> .
Вопросы безопасности элемента X509Data
Элемент <X509Data> является необязательным дочерним элементом <KeyInfo> и содержит один или несколько сертификатов X509 или идентификаторов для сертификатов X509. Данные в элементе <X509Data> также не должны быть изначально доверенными.
При проверке документа с внедренным <X509Data> элементом .NET проверяет только разрешение данных на сертификат X509, открытый ключ которого можно успешно использовать для проверки подписи документа. В отличие от вызова метода с параметром CheckSignature установленным в verifySignatureOnly, проверка отзыва не выполняется, доверие цепочки не проверяется и срок действия не проверяется. Даже если приложение извлекает сам сертификат и передает его CheckSignature методу с verifySignatureOnly заданным параметром false, это всё равно недостаточно для проверки, чтобы предотвратить подделку документа. Сертификат по-прежнему должен быть проверен как подходящий для подписанного документа.
Использование внедренного сертификата подписи может предоставлять полезные стратегии смены ключей, будь то в <X509Data> разделе или в содержимом документа. При использовании этого подхода приложение должно извлечь сертификат вручную и выполнить проверку следующим образом:
Сертификат был выдан непосредственно или через цепочку центра сертификации (ЦС), открытый сертификат которого внедрен в приложение.
Использование списка доверия, предоставленного ОС, без дополнительных проверок, таких как известное имя субъекта, недостаточно, чтобы предотвратить изменение SignedXml.
Сертификат проверен, чтобы удостовериться, что срок его действия не истек во время подписания документа (или "сейчас" для обработки документов в режиме, близком к реальному времени).
Для сертификатов длительного действия, выданных ЦС, поддерживающих процесс отзыва, убедитесь, что сертификат не был отозван.
Проверяется, что субъект сертификата подходит для текущего документа.
Выбор алгоритма преобразования
Если вы взаимодействуете со спецификацией, которая диктует определенные значения (например, XrML), необходимо следовать спецификации. Если у вас есть вложенная подпись (например, при подписи всего документа), необходимо использовать http://www.w3.org/2000/09/xmldsig#enveloped-signature (представленную классом XmlDsigEnvelopedSignatureTransform ). Кроме того, можно указать неявное XML-C14N преобразование, но это не обязательно. Для оболоченной или отделённой подписи преобразования не требуются. Неявное преобразование XML-C14N берёт на себя всё.
В обновлении системы безопасности, представленном Microsoft Security бюллетене MS16-035, .NET ограничить, какие преобразования можно использовать в проверке документов по умолчанию. Ненадежные преобразования вызывают CheckSignature всегда возвращать false. В частности, преобразования, требующие дополнительных входных данных (указанных как дочерние элементы в XML), не допускаются из-за их подверженности злоупотреблений вредоносными пользователями. W3C рекомендует избежать преобразований XPath и XSLT, которые являются двумя основными преобразованиями, затронутыми этими ограничениями.
Проблема с внешними ссылками
Если приложение не проверяет, что внешние ссылки подходят для текущего контекста, они могут быть использованы в злоупотреблениях, приводящих к многим уязвимостям безопасности (включая отказ в обслуживании, распределенный отраженный отказ в обслуживании, раскрытие информации, обход подписей и удаленное выполнение кода). Даже если ваше приложение будет проверять внешний URI ссылки, проблема с повторной загрузкой ресурса останется: один раз, когда ваше приложение считывает его, и один раз при SignedXml чтении. Так как нет никакой гарантии того, что этапы чтения и проверки документов приложением имеют одинаковое содержимое, подпись не обеспечивает достоверность.
Учитывая риски внешних ссылок, SignedXml возникает исключение при обнаружении внешней ссылки. Дополнительные сведения об этой проблеме см. в разделе .NET приложениям возникают ошибки исключений.
Конструкторы
| Имя | Описание |
|---|---|
| SignedXml() |
Инициализирует новый экземпляр класса SignedXml. |
| SignedXml(XmlDocument) |
Инициализирует новый экземпляр класса из указанного SignedXml XML-документа. |
| SignedXml(XmlElement) |
Инициализирует новый экземпляр класса из указанного SignedXmlXmlElement объекта. |
Поля
| Имя | Описание |
|---|---|
| m_signature | |
| m_strSigningKeyName |
Представляет имя установленного ключа, используемого для подписи SignedXml объекта. |
| XmlDecryptionTransformUrl |
Представляет универсальный идентификатор ресурса (URI) для преобразования расшифровки в режиме XML. Это поле является константой. |
| XmlDsigBase64TransformUrl |
Представляет универсальный идентификатор ресурса (URI) для преобразования base 64. Это поле является константой. |
| XmlDsigC14NTransformUrl |
Представляет универсальный идентификатор ресурса (URI) для преобразования Канонического XML. Это поле является константой. |
| XmlDsigC14NWithCommentsTransformUrl |
Представляет универсальный идентификатор ресурса (URI) для преобразования Канонического XML с комментариями. Это поле является константой. |
| XmlDsigCanonicalizationUrl |
Представляет универсальный идентификатор ресурса (URI) для стандартного алгоритма канонизации для цифровых подписей XML. Это поле является константой. |
| XmlDsigCanonicalizationWithCommentsUrl |
Представляет универсальный идентификатор ресурса (URI) для стандартного алгоритма канонизации для цифровых подписей XML и содержит примечания. Это поле является константой. |
| XmlDsigDSAUrl |
Представляет универсальный идентификатор ресурса (URI) для стандартного DSA алгоритма для цифровых подписей XML. Это поле является константой. |
| XmlDsigEnvelopedSignatureTransformUrl |
Представляет универсальный идентификатор ресурса (URI) для преобразования конвертной подписи. Это поле является константой. |
| XmlDsigExcC14NTransformUrl |
Представляет универсальный идентификатор ресурса (URI) для эксклюзивной канонизации XML. Это поле является константой. |
| XmlDsigExcC14NWithCommentsTransformUrl |
Представляет универсальный идентификатор ресурса (URI) для эксклюзивной канонизации XML с комментариями. Это поле является константой. |
| XmlDsigHMACSHA1Url |
Представляет универсальный идентификатор ресурса (URI) для стандартного HMACSHA1 алгоритма для цифровых подписей XML. Это поле является константой. |
| XmlDsigMinimalCanonicalizationUrl |
Представляет универсальный идентификатор ресурса (URI) стандартного минимального алгоритма канонизации для цифровых подписей XML. Это поле является константой. |
| XmlDsigNamespaceUrl |
Представляет универсальный идентификатор ресурса (URI) для стандартного пространства имен для цифровых подписей XML. Это поле является константой. |
| XmlDsigRSASHA1Url |
Представляет универсальный идентификатор ресурса (URI) для стандартного RSA метода подписи для цифровых подписей XML. Это поле является константой. |
| XmlDsigRSASHA256Url |
Представляет универсальный идентификатор ресурса (URI) для варианта метода подписи SHA-256 для RSA цифровых подписей XML. Это поле является константой. |
| XmlDsigRSASHA384Url |
Представляет универсальный идентификатор ресурса (URI) для варианта метода подписи SHA-384 для RSA цифровых подписей XML. Это поле является константой. |
| XmlDsigRSASHA512Url |
Представляет универсальный идентификатор ресурса (URI) для RSA варианта метода подписи SHA-512 для цифровых подписей XML. Это поле является константой. |
| XmlDsigSHA1Url |
Представляет универсальный идентификатор ресурса (URI) для стандартного SHA1 метода дайджеста для цифровых подписей XML. Это поле является константой. |
| XmlDsigSHA256Url |
Представляет универсальный идентификатор ресурса (URI) для стандартного SHA256 метода дайджеста для цифровых подписей XML. Это поле является константой. |
| XmlDsigSHA384Url |
Представляет универсальный идентификатор ресурса (URI) для стандартного SHA384 метода дайджеста для цифровых подписей XML. Это поле является константой. |
| XmlDsigSHA512Url |
Представляет универсальный идентификатор ресурса (URI) для стандартного SHA512 метода дайджеста для цифровых подписей XML. Это поле является константой. |
| XmlDsigXPathTransformUrl |
Представляет универсальный идентификатор ресурса (URI) для языка XML-пути (XPath). Это поле является константой. |
| XmlDsigXsltTransformUrl |
Представляет универсальный идентификатор ресурса (URI) для преобразований XSLT. Это поле является константой. |
| XmlLicenseTransformUrl |
Представляет универсальный идентификатор ресурса (URI) для алгоритма преобразования лицензий, используемого для нормализации лицензий XrML для подписей. |
Свойства
| Имя | Описание |
|---|---|
| EncryptedXml |
Возвращает или задает объект, определяющий EncryptedXml правила обработки XML-шифрования. |
| KeyInfo |
Возвращает или задает KeyInfo объект текущего SignedXml объекта. |
| Resolver |
Задает текущий XmlResolver объект. |
| SafeCanonicalizationMethods |
Получает имена методов, канонические алгоритмы которых явно разрешены. |
| Signature | |
| SignatureFormatValidator |
Получает делегат, который будет вызываться для проверки формата (а не криптографической безопасности) xml-подписи. |
| SignatureLength |
Возвращает длину сигнатуры для текущего SignedXml объекта. |
| SignatureMethod |
Возвращает метод подписи текущего SignedXml объекта. |
| SignatureValue |
Возвращает значение сигнатуры текущего SignedXml объекта. |
| SignedInfo |
SignedInfo Возвращает объект текущего SignedXml объекта. |
| SigningKey |
Возвращает или задает асимметричный ключ алгоритма, используемый SignedXml для подписывания объекта. |
| SigningKeyName |
Возвращает или задает имя установленного ключа, используемого для подписи SignedXml объекта. |
Методы
| Имя | Описание |
|---|---|
| AddObject(DataObject) |
DataObject Добавляет объект в список объектов, подписанных. |
| AddReference(Reference) |
Reference Добавляет объект в SignedXml объект, описывающий метод дайджеста, значение дайджеста и преобразование для создания цифровой подписи XML. |
| CheckSignature() |
Определяет, проверяет ли Signature свойство использование открытого ключа в сигнатуре. |
| CheckSignature(AsymmetricAlgorithm) |
Определяет, проверяет ли Signature свойство указанный ключ. |
| CheckSignature(KeyedHashAlgorithm) |
Определяет, проверяет ли Signature свойство указанный алгоритм проверки подлинности сообщения (MAC). |
| CheckSignature(X509Certificate2, Boolean) |
Определяет, проверяет ли Signature свойство указанный X509Certificate2 объект и, при необходимости, является ли сертификат допустимым. |
| CheckSignatureReturningKey(AsymmetricAlgorithm) |
Определяет, проверяет ли Signature свойство использование открытого ключа в сигнатуре. |
| ComputeSignature() |
Вычисляет цифровую подпись XML. |
| ComputeSignature(KeyedHashAlgorithm) |
Вычисляет цифровую подпись XML с помощью указанного алгоритма проверки подлинности сообщений (MAC). |
| Equals(Object) |
Определяет, равен ли указанный объект текущему объекту. (Унаследовано от Object) |
| GetHashCode() |
Служит хэш-функцией по умолчанию. (Унаследовано от Object) |
| GetIdElement(XmlDocument, String) |
XmlElement Возвращает объект с указанным идентификатором из указанного XmlDocument объекта. |
| GetPublicKey() |
Возвращает открытый ключ подписи. |
| GetType() |
Возвращает Type текущего экземпляра. (Унаследовано от Object) |
| GetXml() |
Возвращает XML-представление SignedXml объекта. |
| LoadXml(XmlElement) |
SignedXml Загружает состояние из XML-элемента. |
| MemberwiseClone() |
Создает неглубокую копию текущей Object. (Унаследовано от Object) |
| ToString() |
Возвращает строку, представляющую текущий объект. (Унаследовано от Object) |