[英]How to Verify a RSA-SHA512 XML Signature in .NET?
在MSDN站點的幫助下,我可以輕松驗證XML DSig是否正確。 如果使用簽名方法sha1,它可以完美地工作。
但是,當我收到SignatureMethod RSA-SHA512 ( http://www.w3.org/2001/04/xmldsig-more#rsa-sha512 )時, CheckSignature()會因CryptograhicException而中斷: 無法為簽名創建SignatureDescription算法提供。
似乎CheckSignature()無法驗證RSA-SHA512簽名。
有誰知道如何檢查這些簽名?
從MSDN站點獲取的代碼是:
public static bool VerifyXml(XmlDocument doc, bool removeSignatureElement = false)
{
// Check arguments.
if (doc == null)
throw new ArgumentException("doc");
// Create a new SignedXml object and pass it the XML document class.
SignedXml signedXml = new SignedXml(doc);
// Find the "Signature" node and create a new XmlNodeList object.
XmlNodeList nodeList = doc.GetElementsByTagName("Signature", Constants.NamespaceDSig);
// Throw an exception if no signature was found.
if (nodeList.Count < 1)
{
throw new CryptographicException("Verification failed: No Signature was found in the document.");
}
// This example only supports one signature for the entire XML document. Throw an exception if more than one signature was found.
if (nodeList.Count > 1)
{
throw new CryptographicException("Verification failed: More that one signature was found for the document.");
}
// Load the first <signature> node.
signedXml.LoadXml((XmlElement)nodeList[0]);
// Check the signature and return the result.
bool signedCorrectly = signedXml.CheckSignature(); // throws the Exception!!!
return signedCorrectly;
}
簽名的XML是:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Notification xmlns="http://www.xxxxxxxxxxx.xx/xxxxx">
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Content"> ... </xenc:EncryptedData>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"/>
<ds:Reference URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>WsHcyNL7Jh8HSzR9ArzTqomBkHs=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
pWDatSEbypIUVQR9NFmLkB9kKWjMb6rKWGFFvGqT5tOUILeDhMHUqjCRB9v/g6yYdogC9TRWouhz
...VoZAIBs7EqCbLt7RgpB4GHWc9E3qp65NaCgluw==
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIIG+zCCBOOgAwIBAgIHAe2+sRfTfDANBgkqhkiG9w0BAQUFADCBkTELMAkGA1UEBhMCQVQxDTAL
...tvawqBjOfkw1yeDzsDMJHfMuAcpYfrEL
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
</Notification>
您可以驗證RSA SHA512簽名,但您必須自己實現並注冊簽名描述。
簽名說明:
public sealed class RSAPKCS1SHA512SignatureDescription : SignatureDescription
{
public RSAPKCS1SHA512SignatureDescription()
{
KeyAlgorithm = typeof( RSACryptoServiceProvider ).FullName;
DigestAlgorithm = typeof( SHA512Managed ).FullName;
FormatterAlgorithm = typeof( RSAPKCS1SignatureFormatter ).FullName;
DeformatterAlgorithm = typeof( RSAPKCS1SignatureDeformatter ).FullName;
}
public override AsymmetricSignatureDeformatter CreateDeformatter( AsymmetricAlgorithm key )
{
if( key == null )
{
throw new ArgumentNullException( "key" );
}
var deformatter = new RSAPKCS1SignatureDeformatter( key );
deformatter.SetHashAlgorithm( "SHA512" );
return deformatter;
}
public override AsymmetricSignatureFormatter CreateFormatter( AsymmetricAlgorithm key )
{
if( key == null )
{
throw new ArgumentNullException( "key" );
}
var formatter = new RSAPKCS1SignatureFormatter( key );
formatter.SetHashAlgorithm( "SHA512" );
return formatter;
}
}
在您的代碼中,您必須使用CryptoConfig注冊此描述:
const string XmlDsigRsaSha512 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512";
CryptoConfig.AddAlgorithm( typeof( RSAPKCS1SHA512SignatureDescription ), XmlDsigRsaSha512 );
我在Windows 7 64 Bit上使用.Net 4.0進行了測試。
根據我的研究, SignedXml
實現只支持以下簽名方法:
http://www.w3.org/2000/09/xmldsig#hmac-sha1
http://www.w3.org/2001/04/xmldsig-more#hmac-sha256
http://www.w3.org/2001/04/xmldsig-more#hmac-sha384
http://www.w3.org/2001/04/xmldsig-more#hmac-sha512
http://www.w3.org/2001/04/xmldsig-more#hmac-md5
http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160
這些可用於簽名和驗證。 不幸的是,
http://www.w3.org/2001/04/xmldsig-more#rsa-sha512
用作您的簽名算法不受支持。
最終,所有加密方法都歸結為CryptoConfig.CreateFromName
,其中rsa-sha512
返回null。
編輯 :我可能剛剛找到了讓它工作的方法。 以下代碼片段適用於我:
Dictionary<string, object> ht =
(Dictionary<string, object>)typeof( CryptoConfig ).InvokeMember(
"DefaultNameHT", System.Reflection.BindingFlags.GetProperty |
System.Reflection.BindingFlags.Static |
System.Reflection.BindingFlags.NonPublic, null, typeof( CryptoConfig ),
null );
var o = ht["http://www.w3.org/2000/09/xmldsig#rsa-sha1"];
ht["http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"] = o;
應在簽署/驗證之前調用此方法。
這是基於以下觀察:實際的哈希驗證來自證書,算法名稱僅用作保護。 如果你欺騙配置認為,RSA-SHA512 支持 (通過指向未使用相同的RSA-SHA1格式),事情開始工作。
編輯2 :經過進一步調查涉及咨詢來源
我認為上述解決方案不起作用 。 它的作用只會改變簽名文檔中的簽名名稱,但不幸的是,簽名仍然是使用RSA-SHA1計算的。
使其工作的唯一方法是將RSA-SHA512實現為KeyedHashAlgoritm
因為簽名和驗證似乎都支持重載版本:
signedXml.ComputeSignature( KeyedHashAlgorithm hash );
signedXml.CheckSignature( KeyedHashAlgorithm hash );
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.