简体   繁体   English

RSACng无法验证哈希值

[英]RSACng fails to verify hash

I have an old code block that uses RSACryptoServiceProvider that I wanted to port over to use the newer RSACng . 我有一个旧的代码块,使用RSACryptoServiceProvider ,我想移植到使用较新的RSACng I have run into a problem that I am unable to solve: RSACng 's VerifyHash method doesn't appear to verify the hash as expected. 我遇到了一个我无法解决的问题: RSACngVerifyHash方法似乎没有按预期验证哈希。 The same code and data, when used with RSACryptoServiceProvider , works fine and the verification succeeds. RSACryptoServiceProvider使用时,相同的代码和数据工作正常,验证成功。

I have done some investigation and .NET source stepping, eventually going all the way down to NCryptVerifySignature . 我做了一些调查和.NET源步骤,最终一直到NCryptVerifySignature I made sure the hash, signature, etc are all the same that RSACryptoServiceProvider works with. 我确保散列,签名等与RSACryptoServiceProvider工作方式完全相同。 In the end, for unknown reasons, NCryptVerifySignature is not successful in verifying the hash in this case. 最后,由于未知原因, NCryptVerifySignature在这种情况下无法验证散列。

My code is below: 我的代码如下:

var rsaKeyPub = "BgIAAACkAABSU0ExAAgAAAMAAAC7N02Zb0lf3UO4pl3ymFvkrNSkPP0Q076vYzvbeTqS5vkBcoXloM044q1LCFtaXw6DUzSFM0IqoGOONb+PW+UeNcTcA/+MKNi7nzbBGg3kAj8QhuxO3u2QJXg62Zb9H+SEvZYfi9PhOCSo0LpWKl72k+uaoTyPAuV738TamRvXWb8XOswSmsHQa38q1Id4TW7CzvVOjc0vnhL+rZ8Po1qg5FJc8m8gdGWC0a4NJTzBsOqLzeVE12B8zgIMehu1gGw/SjY5PVEkDABWgY2DzxLT3rbs6oZ5ZLSHu041q3s1ihOQ8+GMRx3qqvPyB4JVlyd7jqN0j0dT+Yqr+8t3/Liu";
var hash = "Ow1kg47GAgf9cyZbisDuTRNy5NQ=";
var signature = "bBnFouYvuZSYZIPihDB4J/CVC7o5ej3MrbkZV9cn6vgL23rDW1jevWEHx4wGBXLc443DKrZ0XQlSpp3FE/+isyDMcGh7c0buMufiYuOQ0rbo8e4tvuZuZpt+06xnBQcYyFMqe4lkFcI0f/NeAIvy1vME+Kq4v3ikwR4+CsjObgEJIBdWB0B4cqp8355pxtYJv2BQ7UHy/Tv0+OtslgbxikrwU2CQ+tR3XHywIdzm0BEOBfdnOlky96ED18BAqwLlxjef0snCl3DvKz93gtIIQVwEoDRlKC/v/Xb4Eke/fyvt66orLEIyL8Emaer9J6P38ZB1pWRuOsLCv4ly8fnOMw==";
RSAParameters rsaParams;
using (var rsa = new RSACryptoServiceProvider())
{
    rsa.ImportCspBlob(Convert.FromBase64String(rsaKeyPub));
    //Export now for easy importing in the next function. This is not the reason the next block returns false.
    rsaParams = rsa.ExportParameters(false);
    Console.WriteLine(rsa.VerifyHash(Convert.FromBase64String(hash), Convert.FromBase64String(signature), HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1));
}
using (var rsa = new RSACng())
{
    rsa.ImportParameters(rsaParams);
    Console.WriteLine(rsa.VerifyHash(Convert.FromBase64String(hash), Convert.FromBase64String(signature), HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1));
}

Does anyone have any advice on what I am doing wrong? 有没有人对我做错了什么有任何建议? This is using the latest .NET Framework (4.7.2). 这是使用最新的.NET Framework(4.7.2)。

I dug at this a bit and the issue is because the signature, when run through OpenSSL via: 我挖了一下这个问题是因为签名,当通过OpenSSL运行时:

openssl rsautl -verify -in sig.bin -inkey pub.key -pubin -hexdump -raw presents: openssl rsautl -verify -in sig.bin -inkey pub.key -pubin -hexdump -raw

0000 - 00 01 ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0010 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0020 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0030 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0040 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0050 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0060 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0070 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0080 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
0090 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
00a0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
00b0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
00c0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
00d0 - ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff   ................
00e0 - ff ff ff ff ff ff ff ff-ff ff ff 00 3b 0d 64 83   ............;.d.
00f0 - 8e c6 02 07 fd 73 26 5b-8a c0 ee 4d 13 72 e4 d4   .....s&[...M.r..

Essentially you have a signature with PKCSv1.5 padding with the hash at the end. 基本上你有一个带有PKCSv1.5填充的签名,最后是哈希。 However, the signature is missing the SEQUENCE(OID(SHA-1), OCTETSTRING) - the digest is going straight in. 但是,签名缺少SEQUENCE(OID(SHA-1), OCTETSTRING) - 摘要直接进入。

CNG expects the OID to be there as defined in RSASSA-PKCS1-v1_5. CNG希望OID在RSASSA-PKCS1-v1_5中定义。 You can ask CNG to relax this requirement by passing in NULL to the BCRYPT_PKCS1_PADDING_INFO 's pszAlgId , however this is not exposed anywhere in .NET Framework or Core as far as I know. 可以通过将NULL传递给BCRYPT_PKCS1_PADDING_INFOpszAlgId 请求CNG放宽此要求,但据我所知,这不会在.NET Framework或Core中的任何地方公开。

As far as how to fix it, the easiest thing right now if possible is to use CAPI / RsaCryptoServiceProvider. 至于如何修复它,如果可能的话,现在最简单的方法是使用CAPI / RsaCryptoServiceProvider。 GitHub issue 34202 may track any additional progress on CNG's behavior. GitHub问题34202可以跟踪CNG行为的任何其他进展。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM