使用 Sha256 RSA 验证 SignatureValue 和 DigestValue
Verify SignatureValue And DigestValue Using Sha256 RSA
我正在尝试验证我收到的用于 C# 验证的数据。
这是XML我有,
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Response xmlns="http://www.site.ae/abc">
<Message xml:id="message">
<Header>
<SomeDate>SomValue</SomeDate>
</Header>
<Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="SomeDataType">
<SomeStatus>Success</SomeStatus>
</Body>
</Message>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<Reference URI="#message">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<DigestValue>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</Response>
我正在使用下面的 C# 代码来验证上面的代码,
var signature = @"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var data = @"
<Header>
<SomeDate>SomValue</SomeDate>
</Header>
<Body xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""SomeDataType"">
<SomeStatus>Success</SomeStatus>
</Body>";
var digest = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var x509Data = @"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX";
byte[] SignatureValueBytes = Convert.FromBase64String(signature);
byte[] x509DataBytes = Convert.FromBase64String(x509Data);
byte[] DigestValueBytes = Convert.FromBase64String(digest);
var cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(x509DataBytes);
using (var rsa = System.Security.Cryptography.X509Certificates.RSACertificateExtensions.GetRSAPublicKey(cert))
{
bool a = rsa.VerifyHash(DigestValueBytes, SignatureValueBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
但是上面的代码验证失败。我缺少什么?这是空白问题吗?
创建 XML 签名,即签署 XML 文档 (XMLDSig), is more complex than the creation of an ordinary signature, since one and the same XML can be serialized differently, i.e. the different serializations are logically identical. Therefore, the XML must be normalized beforehand, i.e. converted into a unique format (Canonicalization)。同样,验证也是如此。
.NET 很大程度上封装了这些过程。因此,签名比验证更复杂,因为对于后者,参数(例如规范化变体)包含在已签名的 XML.
中
在问题中发布的签名 XML 中,已经嵌入了用于验证的密钥(即证书)。在这种情况下,一种可能的验证实现是:
using System;
using System.Xml;
using System.Security.Cryptography.Xml;
public class VerifyTest
{
private static String signedXml =
@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""no""?>
<Response xmlns=""http://www.site.ae/abc"">
<Message id=""message"">
<Header>
<SomeDate>SomValue</SomeDate>
</Header>
<Body xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""SomeDataType"">
<SomeStatus>Success</SomeStatus>
</Body>
</Message>
<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#"">
<SignedInfo>
<CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments""/>
<SignatureMethod Algorithm=""http://www.w3.org/2001/04/xmldsig-more#rsa-sha256""/>
<Reference URI=""#message"">
<Transforms>
<Transform Algorithm=""http://www.w3.org/2000/09/xmldsig#enveloped-signature""/>
</Transforms>
<DigestMethod Algorithm=""http://www.w3.org/2001/04/xmlenc#sha256""/>
<DigestValue>hXuAfCAwKQIH1lGErMom2yO//25Pbyn1eXEmcEL1Rtk=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>izFP8eyDkG+9mDF2mAFl66174gpYbBzbcPPc/kDMjRm4TFnZdMAITLe60EPqdQAKK61A6FW8ZQrCkbbiBk/PRd8WaAxgAxjnMU8/U6gYUI6pk2LAANMquguYs7NQjURf7QFr1M1s7F1OrDDVlJiy2ZK3f0yLPoJstA+tnSbjYTQNlYP2qqzGARDkuEXZELSeCjXfA6M2gcGv7EsAv3GtgC2wR3GaVnnfLcieC+8bB9PJwkUtS3P/nmZuvezq/nBvZ/VsIgVjD/rLZX3rAxtVmhRj4d2ykGomnTBU0UJJtcIJyL3UJaQssr1U8YpSA5yWMfJ1uYUCZrGfh7OsHst/qrxeNwO0tGWAdsbD5MWYIwJzHAFcBTrNB0c6g1ehZwihBJWST2YJZvo3xV4UEO4++MhgsP0NHI8fPeBTZRx/vIN7quiJ21YxumUSwA5o8t4Rg9SSOthpnEbfyrSRntlSe8U28EdT0aNVL5gG/N5Qf3eW7XYHjJ2gxv8llMG6UcTY3ck48sW7f+ODatJ5Uk6GALFRjGgrdDlIBgImEormswDmwXSF46XoQVnEH2bR89Yd7g5GlzWQC+Fr5Q2vgVJ/ufS/85URVDr/KFYiJCzzmCEFdZWPR0zrOF/1GDbdAx0s8Zu3Sbq1ERMbdEQqxHs3N0NhdtVtYu96AXXnj5Azg3Y=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>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</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</Response>";
public static void Main(String[] args)
{
// Print XML document
Console.WriteLine(VerifyTest.signedXml);
// Load signed XML document
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(VerifyTest.signedXml);
// Verify
SignedXml signedXml = new SignedXml(xmlDoc);
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);
bool verified = signedXml.CheckSignature();
Console.WriteLine(new string('-', 100) + "\nVerified: " + verified);
}
}
代码中包含的签名 XML 基于您发布的示例,我使用私人测试密钥对其进行了签名。嵌入验证所需并与私钥相关联的证书。代码可以在 .NET Fiddel 上在线 运行:https://dotnetfiddle.net/xpjAz4.
请注意 XmlDocument
class 有一个 PreserveWhitespace
属性,默认为 false
并控制在加载或保存时是否保留空格。签名时,XML文档的格式必须与此一致,兼顾PreserveWhitespace
标志。在发布的代码中,使用默认值。
可以找到有关使用嵌入式密钥签名的更多详细信息here. Verification is described here。
编辑:
为了使用带有xml
前缀的id
属性,必须派生SignedXml
class并且必须覆盖GetIdElement()
方法.此解决方案来自this post, where the prefix and namespace need to be adjusted. The prefix xml
is by definition bound to the namespace http://www.w3.org/XML/1998/namespace
, s. W3C Recommendation, 3 Declaring Namespaces, Namespace constraint: Reserved Prefixes and Namespace Names.
另外,当然,由于对xml:id
的修改,示例签名发生了变化,因此也需要替换,所以上面的代码片段整体变为:
using System;
using System.Xml;
using System.Security.Cryptography.Xml;
public class VerifyTest
{
private static String signedXml =
@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""no""?>
<Response xmlns=""http://www.site.ae/abc"">
<Message xml:id=""message"">
<Header>
<SomeDate>SomValue</SomeDate>
</Header>
<Body xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""SomeDataType"">
<SomeStatus>Success</SomeStatus>
</Body>
</Message>
<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#"">
<SignedInfo>
<CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments""/>
<SignatureMethod Algorithm=""http://www.w3.org/2001/04/xmldsig-more#rsa-sha256""/>
<Reference URI=""#message"">
<Transforms>
<Transform Algorithm=""http://www.w3.org/2000/09/xmldsig#enveloped-signature""/>
</Transforms>
<DigestMethod Algorithm=""http://www.w3.org/2001/04/xmlenc#sha256""/>
<DigestValue>8anSzrELTpH8X6qq9rzTr6+T79EsRVhMLZ0ws3nYOTA=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>IAxXS6JBw/DGI4BdAKBSuUWYD7vX8zA5yWnez6/D2B7o2DhpGLuZVVA6gqIf9cr0omk+5kwyQMStKoYm9JWhFU136XtMgx19WC/ZCvGa59LBpIUsVpr3IKm0cQasp4jMIyeQCbAi0R/fYCY3fdH6GWdMcPuh47oOM63mBUYarokUv0ypuPykZsH010VvS9Af42BPRjnSpFRLoY4E9YtkWNpNoEgIMFRCCC6xsH+mLjMVFAmldAAGHiYn1v847NmHR3qmjRd+tfn8YtxEeLLJNgNgg8+lE1C2wsCpBTowXi/LKngEEwL+pckaSxCFa6qLIDC8aOJHM9BN30lrvSAYFGfaNZ0SHECga6aQ05UgZrlMpCg56d65qqNBz0+kDEgFhCzr8CqftHfGcVGXm95k27qNrDsrPac8s16/LBzzhONAhEwMJ7Rlef27/xSl87RSOQWTJWLF6unsJBqWvpKJY+CP0mmezqCcN/Q28oETOrR8q4QaW7ByLLv5FH1O8nneJyfd2QmhDJ3XDBSWeTGlJEGPYztVWzz2qcq9jpKmzpYxMFOJS24SKQlKcKWAdGeRJVillTyANeDnSt1YOS/z2lQoWPzrNY1XCkBUdEA+pe0aFtX2X1JCKEqvS3AtRui8fZzQ+frhcC/Y/hYDO1mD3NliUH9zkcEm8PdGNBJaLIY=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>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</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</Response>";
public static void Main(String[] args)
{
// Print XML document
Console.WriteLine(VerifyTest.signedXml);
// Load signed XML document
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(VerifyTest.signedXml);
// Verify
SignedXmlWithId signedXml = new SignedXmlWithId(xmlDoc);
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);
bool verified = signedXml.CheckSignature();
Console.WriteLine(new string('-', 100) + "\nVerified: " + verified);
}
class SignedXmlWithId : SignedXml
{
public SignedXmlWithId(XmlDocument xml) : base(xml) { }
public SignedXmlWithId(XmlElement xmlElement) : base(xmlElement) { }
public override XmlElement GetIdElement(XmlDocument doc, string id)
{
XmlElement idElem = base.GetIdElement(doc, id);
if (idElem == null)
{
XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
nsManager.AddNamespace("xml", "http://www.w3.org/XML/1998/namespace");
idElem = doc.SelectSingleNode("//*[@xml:id=\"" + id + "\"]", nsManager) as XmlElement;
}
return idElem;
}
}
}
现在 XML 示例与您发布的示例 完全匹配 ,包括 xml:id
属性。代码片段可以成功执行,例如在 .NET Fiddel 上在线:https://dotnetfiddle.net/nqNhu3.
我正在尝试验证我收到的用于 C# 验证的数据。
这是XML我有,
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Response xmlns="http://www.site.ae/abc">
<Message xml:id="message">
<Header>
<SomeDate>SomValue</SomeDate>
</Header>
<Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="SomeDataType">
<SomeStatus>Success</SomeStatus>
</Body>
</Message>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<Reference URI="#message">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<DigestValue>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</Response>
我正在使用下面的 C# 代码来验证上面的代码,
var signature = @"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var data = @"
<Header>
<SomeDate>SomValue</SomeDate>
</Header>
<Body xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""SomeDataType"">
<SomeStatus>Success</SomeStatus>
</Body>";
var digest = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var x509Data = @"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX";
byte[] SignatureValueBytes = Convert.FromBase64String(signature);
byte[] x509DataBytes = Convert.FromBase64String(x509Data);
byte[] DigestValueBytes = Convert.FromBase64String(digest);
var cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(x509DataBytes);
using (var rsa = System.Security.Cryptography.X509Certificates.RSACertificateExtensions.GetRSAPublicKey(cert))
{
bool a = rsa.VerifyHash(DigestValueBytes, SignatureValueBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
但是上面的代码验证失败。我缺少什么?这是空白问题吗?
创建 XML 签名,即签署 XML 文档 (XMLDSig), is more complex than the creation of an ordinary signature, since one and the same XML can be serialized differently, i.e. the different serializations are logically identical. Therefore, the XML must be normalized beforehand, i.e. converted into a unique format (Canonicalization)。同样,验证也是如此。
.NET 很大程度上封装了这些过程。因此,签名比验证更复杂,因为对于后者,参数(例如规范化变体)包含在已签名的 XML.
中
在问题中发布的签名 XML 中,已经嵌入了用于验证的密钥(即证书)。在这种情况下,一种可能的验证实现是:
using System;
using System.Xml;
using System.Security.Cryptography.Xml;
public class VerifyTest
{
private static String signedXml =
@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""no""?>
<Response xmlns=""http://www.site.ae/abc"">
<Message id=""message"">
<Header>
<SomeDate>SomValue</SomeDate>
</Header>
<Body xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""SomeDataType"">
<SomeStatus>Success</SomeStatus>
</Body>
</Message>
<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#"">
<SignedInfo>
<CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments""/>
<SignatureMethod Algorithm=""http://www.w3.org/2001/04/xmldsig-more#rsa-sha256""/>
<Reference URI=""#message"">
<Transforms>
<Transform Algorithm=""http://www.w3.org/2000/09/xmldsig#enveloped-signature""/>
</Transforms>
<DigestMethod Algorithm=""http://www.w3.org/2001/04/xmlenc#sha256""/>
<DigestValue>hXuAfCAwKQIH1lGErMom2yO//25Pbyn1eXEmcEL1Rtk=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>izFP8eyDkG+9mDF2mAFl66174gpYbBzbcPPc/kDMjRm4TFnZdMAITLe60EPqdQAKK61A6FW8ZQrCkbbiBk/PRd8WaAxgAxjnMU8/U6gYUI6pk2LAANMquguYs7NQjURf7QFr1M1s7F1OrDDVlJiy2ZK3f0yLPoJstA+tnSbjYTQNlYP2qqzGARDkuEXZELSeCjXfA6M2gcGv7EsAv3GtgC2wR3GaVnnfLcieC+8bB9PJwkUtS3P/nmZuvezq/nBvZ/VsIgVjD/rLZX3rAxtVmhRj4d2ykGomnTBU0UJJtcIJyL3UJaQssr1U8YpSA5yWMfJ1uYUCZrGfh7OsHst/qrxeNwO0tGWAdsbD5MWYIwJzHAFcBTrNB0c6g1ehZwihBJWST2YJZvo3xV4UEO4++MhgsP0NHI8fPeBTZRx/vIN7quiJ21YxumUSwA5o8t4Rg9SSOthpnEbfyrSRntlSe8U28EdT0aNVL5gG/N5Qf3eW7XYHjJ2gxv8llMG6UcTY3ck48sW7f+ODatJ5Uk6GALFRjGgrdDlIBgImEormswDmwXSF46XoQVnEH2bR89Yd7g5GlzWQC+Fr5Q2vgVJ/ufS/85URVDr/KFYiJCzzmCEFdZWPR0zrOF/1GDbdAx0s8Zu3Sbq1ERMbdEQqxHs3N0NhdtVtYu96AXXnj5Azg3Y=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>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</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</Response>";
public static void Main(String[] args)
{
// Print XML document
Console.WriteLine(VerifyTest.signedXml);
// Load signed XML document
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(VerifyTest.signedXml);
// Verify
SignedXml signedXml = new SignedXml(xmlDoc);
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);
bool verified = signedXml.CheckSignature();
Console.WriteLine(new string('-', 100) + "\nVerified: " + verified);
}
}
代码中包含的签名 XML 基于您发布的示例,我使用私人测试密钥对其进行了签名。嵌入验证所需并与私钥相关联的证书。代码可以在 .NET Fiddel 上在线 运行:https://dotnetfiddle.net/xpjAz4.
请注意 XmlDocument
class 有一个 PreserveWhitespace
属性,默认为 false
并控制在加载或保存时是否保留空格。签名时,XML文档的格式必须与此一致,兼顾PreserveWhitespace
标志。在发布的代码中,使用默认值。
可以找到有关使用嵌入式密钥签名的更多详细信息here. Verification is described here。
编辑:
为了使用带有xml
前缀的id
属性,必须派生SignedXml
class并且必须覆盖GetIdElement()
方法.此解决方案来自this post, where the prefix and namespace need to be adjusted. The prefix xml
is by definition bound to the namespace http://www.w3.org/XML/1998/namespace
, s. W3C Recommendation, 3 Declaring Namespaces, Namespace constraint: Reserved Prefixes and Namespace Names.
另外,当然,由于对xml:id
的修改,示例签名发生了变化,因此也需要替换,所以上面的代码片段整体变为:
using System;
using System.Xml;
using System.Security.Cryptography.Xml;
public class VerifyTest
{
private static String signedXml =
@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""no""?>
<Response xmlns=""http://www.site.ae/abc"">
<Message xml:id=""message"">
<Header>
<SomeDate>SomValue</SomeDate>
</Header>
<Body xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""SomeDataType"">
<SomeStatus>Success</SomeStatus>
</Body>
</Message>
<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#"">
<SignedInfo>
<CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments""/>
<SignatureMethod Algorithm=""http://www.w3.org/2001/04/xmldsig-more#rsa-sha256""/>
<Reference URI=""#message"">
<Transforms>
<Transform Algorithm=""http://www.w3.org/2000/09/xmldsig#enveloped-signature""/>
</Transforms>
<DigestMethod Algorithm=""http://www.w3.org/2001/04/xmlenc#sha256""/>
<DigestValue>8anSzrELTpH8X6qq9rzTr6+T79EsRVhMLZ0ws3nYOTA=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>IAxXS6JBw/DGI4BdAKBSuUWYD7vX8zA5yWnez6/D2B7o2DhpGLuZVVA6gqIf9cr0omk+5kwyQMStKoYm9JWhFU136XtMgx19WC/ZCvGa59LBpIUsVpr3IKm0cQasp4jMIyeQCbAi0R/fYCY3fdH6GWdMcPuh47oOM63mBUYarokUv0ypuPykZsH010VvS9Af42BPRjnSpFRLoY4E9YtkWNpNoEgIMFRCCC6xsH+mLjMVFAmldAAGHiYn1v847NmHR3qmjRd+tfn8YtxEeLLJNgNgg8+lE1C2wsCpBTowXi/LKngEEwL+pckaSxCFa6qLIDC8aOJHM9BN30lrvSAYFGfaNZ0SHECga6aQ05UgZrlMpCg56d65qqNBz0+kDEgFhCzr8CqftHfGcVGXm95k27qNrDsrPac8s16/LBzzhONAhEwMJ7Rlef27/xSl87RSOQWTJWLF6unsJBqWvpKJY+CP0mmezqCcN/Q28oETOrR8q4QaW7ByLLv5FH1O8nneJyfd2QmhDJ3XDBSWeTGlJEGPYztVWzz2qcq9jpKmzpYxMFOJS24SKQlKcKWAdGeRJVillTyANeDnSt1YOS/z2lQoWPzrNY1XCkBUdEA+pe0aFtX2X1JCKEqvS3AtRui8fZzQ+frhcC/Y/hYDO1mD3NliUH9zkcEm8PdGNBJaLIY=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>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</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</Response>";
public static void Main(String[] args)
{
// Print XML document
Console.WriteLine(VerifyTest.signedXml);
// Load signed XML document
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(VerifyTest.signedXml);
// Verify
SignedXmlWithId signedXml = new SignedXmlWithId(xmlDoc);
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);
bool verified = signedXml.CheckSignature();
Console.WriteLine(new string('-', 100) + "\nVerified: " + verified);
}
class SignedXmlWithId : SignedXml
{
public SignedXmlWithId(XmlDocument xml) : base(xml) { }
public SignedXmlWithId(XmlElement xmlElement) : base(xmlElement) { }
public override XmlElement GetIdElement(XmlDocument doc, string id)
{
XmlElement idElem = base.GetIdElement(doc, id);
if (idElem == null)
{
XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
nsManager.AddNamespace("xml", "http://www.w3.org/XML/1998/namespace");
idElem = doc.SelectSingleNode("//*[@xml:id=\"" + id + "\"]", nsManager) as XmlElement;
}
return idElem;
}
}
}
现在 XML 示例与您发布的示例 完全匹配 ,包括 xml:id
属性。代码片段可以成功执行,例如在 .NET Fiddel 上在线:https://dotnetfiddle.net/nqNhu3.