How to Verify a RSA-SHA512 XML Signature in .NET?
在有关signedxml的msdn站点的帮助下,我可以轻松地验证XML DSIG是否正确。如果使用签名方法sha1,它就可以完美地工作。
但是,当我收到signaturemethod rsa-sha512(http://www.w3.org/2001/04/xmldsig more rsa-sha512)时,checkSignature()中断,出现一个加密异常:无法为提供的签名算法创建signatureDescription。
似乎checkSignature()无法验证RSA-SHA512签名。
有人知道如何检查这些签名吗?
代码取自msdn站点,是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <?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签名,但是您必须自己实现和注册签名描述。
签名说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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注册此描述:
1 2 | const string XmlDsigRsaSha512 ="http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"; CryptoConfig.AddAlgorithm( typeof( RSAPKCS1SHA512SignatureDescription ), XmlDsigRsaSha512 ); |
我在Windows7 64位上用.NET 4.0测试了它。
根据我的研究,
1 2 3 4 5 6 | 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 |
这些可用于签名和验证。不幸的是,
1 | http://www.w3.org/2001/04/xmldsig-more#rsa-sha512 |
不支持用作签名算法。
最终,所有的加密方法都会下降到
编辑:我可能刚刚找到了一个让它工作的方法。以下代码段对我有用:
1 2 3 4 5 6 7 8 9 | 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:在进一步调查涉及咨询来源后
http://www.dotnetframework.org/default.aspx/4@0/4@0/untmp/devdiv_tfs/dev10/releases/rtmrel/ndp/clr/src/managedlibraries/security/system/security/cryptography/xml/signedxml@cs/1305376/signedxml@cs
我认为上述解决方案行不通。它所做的只是更改已签名文档中的签名名,但是不幸的是,仍然使用RSA-SHA1计算签名。
唯一可行的方法是将RSA-SHA512作为
1 2 | signedXml.ComputeSignature( KeyedHashAlgorithm hash ); signedXml.CheckSignature( KeyedHashAlgorithm hash ); |