【问题标题】:Can't validate signature value using certificate public key provided in an xml (X509Certificate2)无法使用 xml 中提供的证书公钥验证签名值 (X509Certificate2)
【发布时间】:2014-12-23 21:13:57
【问题描述】:

我花了 100 个小时研究这个主题,而其他编写原始项目的高级程序员也无法使其工作。我有一个带有 SignatureValue、Certificate (X509Certificate2) 和 Digest Value 参数的 xml。通过将连接字段(等于摘要值)转换为哈希(SHA1),然后通过私钥加密来生成在同一 xml 中声明的创建和给定签名值。私钥从证书中取出以保护隐私,我只有公钥。现在,无论我如何编码,我总是得到一个错误的值(如在 VerifyHash/verifyHashResult 为假)。这是我正在使用的代码:

// 需要你的帮助。

 static void VerifyHash(string sigVal , string digestVal, System.Security.Cryptography.X509Certificates.X509Certificate2 cert)
        {
            sigValInBytes = Convert.FromBase64String(sigVal);
            try
            {
 using (RSACryptoServiceProvider rsaProviderDecrypt = (RSACryptoServiceProvider)cert.PublicKey.Key)
               {
// Line below always return value of FALSE no matter how I code it. Here I want to verify the hashed freshly calculated digest value that is now hashed with the signature value
                    rsaProviderDecrypt.Decrypt(sigValInBytes, false);

                   rsaProviderDecrypt.Dispose();
               }
             }
        }


// At the main program I get the certificate from the xml given and call the method above:

main
{
// Code below gets the certificate details from a given xml, details of each variable confirmed to be accurate.
char[] Base64_x509ByteArray;
Base64_x509ByteArray = t.DigitalSignatures.First().X509Data.ToCharArray();
byte[] x509ByteArray;
x509ByteArray = Convert.FromBase64CharArray(Base64_x509ByteArray, 0, Base64_x509ByteArray.Length);

// Here am creating the certificate from the gathered data/certificate:
System.Security.Cryptography.X509Certificates.X509Certificate2 cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(x509ByteArray);

VerifyHash(t.DigitalSignatures.FirstOrDefault().SignatureValue.Trim(), concatenatedFieldValues, cert);

}

【问题讨论】:

  • ByteConverter 类在做什么?为什么签名和摘要是string
  • 有什么理由要使用X509Certificate2 吗?可以给你另一个建议吗?
  • 对于问题 #1,我继续进行了一些更改并删除了字节转换,因为我不需要刚刚发布的新代码。我认为我更近了一步,并且在使用 rsaProviderDecrypt.Decrypt(sigValInBytes, false) 时做正确的事情,尤其是在使用 FromBase64String 将 sigVal 转换为字节数组之后,因为这使得字节数组的大小不大于 256。但是收到一个新错误“密钥不存在”
  • 对于问题 #2:我必须使用 X509Certificate,因为这是供应商用来加密数字签名的(我这里别无选择)。
  • 知道为什么我会收到新错误“找不到密钥”吗?

标签: c# cryptography digital-signature x509certificate2 xml-signature


【解决方案1】:

黑暗中的一些镜头:

  1. 找到损坏的部分:尝试在代码中执行整个“加密/哈希检查”过程,而不通过 XML 传输任何内容。如果您可以在本地散列字符串,并且散列匹配,那么问题出在 XML 中。否则,问题出在证书或解密器中。

  2. 如果问题出在证书/加密器端,请尝试使用本地 .NET 加密类进行哈希匹配。如果失败,则问题是加密设置。否则就是证书。

  3. 在黑暗中大开杀戒:在哈希检查之后立即调用Dispose不应该重要,但这在我使用 Rijndael 算法解密时引起了问题。最好的猜测是优化器提前关闭了流或者类似的奇怪的东西。将构造函数移出using 语句并在访问修复“优化”的结果后手动调用Dispose

  4. 可能会尝试可逆加密算法。 Rinjdael 是 .NET 原生的,并且是可逆的。适合调试和概念验证工作。 (注意:它使用时间作为盐的一部分,所以 RJ 不匹配哈希值,它会解密。所以在生产环境中不适合密码。)

  5. 如果原因是 XML,请检查编码。加密对编码非常敏感,而 XML 序列化程序从一开始就是个笨蛋。字符串可能看起来相同,但表示方式不同,或者添加了额外的控制字符。 Sql Server nvarchars 是 UCS-2,varchars 是 iso-8859-1,C# 字符串是 utf-8 等。容易编码不匹配,而编码更改很容易导致这种情况。在插入 Xml 之前尝试将原始值转换为 utf-16,并将 Xml 声明编码设置为 utf-16。为了安全起见。

  6. 1234563如果你在 Word 中做同样的事情......哦,我的......可能想尝试原始副本。
  7. 如果失败,请尝试生成新的加密值并查看它们是否匹配。

【讨论】:

  • 非常感谢以上几点,我正在考虑一些要点,实际上我对我的代码进行了更新并编写了一个 decrpt 调用(发布在上面的原始代码中),但现在我有了一个新的错误“未找到密钥”虽然我确信密钥已被提取并且存在(请参阅上面的更新代码)。谢谢。
猜你喜欢
  • 2022-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-26
  • 2015-12-28
  • 1970-01-01
  • 2012-07-26
  • 1970-01-01
相关资源
最近更新 更多