我是 XML 数字签名主题的新手。在阅读了一些教程后,我决定做一些实践活动,并尝试遵循一些示例来提高我的理解。有一点我需要帮助。
这是我正在尝试的示例:
https://docs.microsoft.com/en-us/dotnet/standard/security/how-to-sign-xml-documents-with-digital-signatures https://docs.microsoft.com/en-us/dotnet /standard/security/how-to-verify-the-digital-signatures-of-xml-documents
要签名的数据很简单(从站点复制/粘贴会产生 TAB 字符,因此我在将文件保存到磁盘之前将所有 TAB 转换为单个空格):
<root>
<creditcard>
<number>19834209</number>
<expiry>02/02/2002</expiry>
</creditcard>
</root>
当我使用此数据运行示例代码时,会生成以下Signature
元素并将其添加到根元素内的文件中:
<Signature xmlns="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/2001/04/xmldsig-more#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>AjI/9vkjyZWM9noiF0J0RRZEUAjBil96ETvT9Cl85rI=</DigestValue></Reference></SignedInfo><SignatureValue>YY5B15W2W9TyoV4HjZTh554Z/yh06iz7+yKM/AgsdzU6QvakH54rPJZ9rQkIrLehxJlX76xXgp9Pe+ougMA6QSj7NvqRBXoxgQcpf1W/m4cfCzTd7iT7A93xhqCdU1F4AohvJZRqwbeApOqxjuXmcF9kqLFDcSTuRZSgIPJdSS8=</SignatureValue></Signature>
我手动对输入进行规范化并编写了一些代码,并验证了规范化输入的 SHA256 摘要确实与其中的匹配DigestValue
(Signature
即,到目前为止,我对事情如何在幕后工作的理解,至少在规范化方面是正确的)。但是,到目前为止,我验证签名值的尝试都失败了。无论我做什么,我都无法获得 API 产生的签名值。当然,示例的验证部分(使用 API)有效,并表明签名有效。
这是“手动”验证的代码:
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
byte[] originalData = File.ReadAllBytes("signedinfo.xml");
byte[] signedBytes;
try
{
SHA256 mySHA256 = SHA256.Create();
byte[] digest=mySHA256.ComputeHash(originalData);
signedBytes = rsaKey.SignHash(digest, CryptoConfig.MapNameToOID("SHA256"));
Console.WriteLine(System.Convert.ToBase64String(signedBytes));
}
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
}
SignedInfo.xml
如下:
<SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>AjI/9vkjyZWM9noiF0J0RRZEUAjBil96ETvT9Cl85rI=</DigestValue></Reference></SignedInfo>
我在https://www.di-mgt.com.au/xmldsig2.html找到了一个指南,其中提到了在规范化期间传播命名空间SignedInfo
,所以我也尝试了以下SignedInfo.xml
方法:
<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>AjI/9vkjyZWM9noiF0J0RRZEUAjBil96ETvT9Cl85rI=</DigestValue></Reference></SignedInfo>
这仍然不会产生与示例中的 API 相同的签名。
我将不胜感激任何帮助找出我做错了什么。