【问题标题】:Calculating SignatureValue from SignedInfo using RSACryptoServiceProvider使用 RSACryptoServiceProvider 从 SignedInfo 计算 SignatureValue
【发布时间】:2021-04-01 12:18:30
【问题描述】:

我是 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 摘要确实与Signature 中的DigestValue 匹配(即我对幕后工作原理的理解,至少关于规范化,到目前为止是正确的)。但是,到目前为止,我验证签名值的尝试都失败了。无论我做什么,我都无法获得 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 相同的签名。

如果能帮助我找出我做错了什么,我将不胜感激。

【问题讨论】:

  • 看起来您正在散列 SignedInfo 并计算其签名,而不是计算散列 (DigestValue) 的签名
  • @mnistic 那部分是正确的。但是,我在 SignedInfo 的规范化中犯了一个明显的错误,忘记将元素从表单 扩展到表单

标签: c# hash cryptography xml-signature xml-dsig


【解决方案1】:

没有完整阅读指南是我的错误。我忘记将元素从&lt;tag /&gt; 扩展为&lt;tag&gt;&lt;/tag&gt;。因此,正确的规范 SignedInfo

<SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></CanonicalizationMethod><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod><DigestValue>AjI/9vkjyZWM9noiF0J0RRZEUAjBil96ETvT9Cl85rI=</DigestValue></Reference></SignedInfo>

有了这个SignedInfo,我可以“手动”验证签名。

在此过程中,让我再提供一点信息,这些信息可能会帮助其他看到此问题的人:There's a note 关于 .Net 对包容性 c14n 算法 (Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315") 的实现与规范和从其他实现。这种差异对跨平台验证有影响。在我的学习中这并没有影响到我,但是万一需要做跨平台验证,这是一个需要注意的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-11
    • 2021-07-25
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 2012-12-12
    • 2018-11-14
    相关资源
    最近更新 更多