无法使用xml(X509Certificate2)中提供的证书公钥验证签名值

时间:2014-12-23 21:13:57

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

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

//需要你的帮助。

 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);

}

1 个答案:

答案 0 :(得分:1)

黑暗中的一些镜头:

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

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

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

  4. 可以尝试可逆加密算法。 Rinjdael是.NET的原生,并且是可逆的。适用于调试和概念验证工作。 (注意:它使用Time作为salt的一部分,因此RJ与哈希不匹配,它会解密。因此对于生产环境中的密码不好。)

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

  6. 关于NotePad的注意事项:如果您已在记事本中打开Xml以快速查看或编辑并保存它,那么现在您的字符串上可能会有额外的“行尾”字符。如果你在Word中做了同样的事......哦,我的......可能想要试一份原件。

  7. 如果失败,请尝试生成新的加密值并查看它们是否匹配。