c# – 如何(正确)使用RSA和SHA256与.NET验证文件?

c# – 如何(正确)使用RSA和SHA256与.NET验证文件?,第1张

概述我在跟踪 this great tutorial使用.NET进行数字签名/验证数据.我修改了该示例代码以使用SHA256并点击“指定的无效算法”异常,这使我得到了关于在.NET 4.0中使用SHA256签名数据的 this SO question. One of the answers从该帖子中帮助我弄清楚如何通过显式加载支持SHA256的加密提供程序而不依赖于可导出的私钥来正确生成数字签名(请参 我在跟踪 this great tutorial使用.NET进行数字签名/验证数据.我修改了该示例代码以使用SHA256并点击“指定的无效算法”异常,这使我得到了关于在.NET 4.0中使用SHA256签名数据的 this SO question.

One of the answers从该帖子中帮助我弄清楚如何通过显式加载支持SHA256的加密提供程序而不依赖于可导出的私钥来正确生成数字签名(请参阅构建RSACryptoServiceProvIDer的以下方法底部的代码):

static string mKeyContainername;static byte[] SignText(string text,string publicCertPath){    // Access Personal (MY) certificate store of current user    X509Store store = new X509Store(Storename.My,StoreLocation.CurrentUser);    store.Open(OpenFlags.Readonly);    // Load the certificate we'll use to verify the signature from a file.    X509Certificate2 publicCert = new X509Certificate2(publicCertPath);    publicCert.Verify();    string publicHash = publicCert.GetCertHashString();    // Find the certificate we'll use to sign    X509Certificate2 privateCert = null;    foreach(X509Certificate2 cert in store.Certificates)    {            if(cert.GetCertHashString() == publicHash)            {                    // We found it. Get its associated private key                    privateCert = cert;                    break;            }    }    store.Close();    if(privateCert == null)    {            throw new Exception("No valID private cert was found");    }    // Hash the string    UnicodeEnCoding enCoding = new UnicodeEnCoding();    byte[] data = enCoding.GetBytes(text);    SHA256Managed sha256 = new SHA256Managed();    byte[] hash = sha256.ComputeHash(data);    // The basic crypto provIDer only supports SHA-1.    // Force Enhanced RSA and AES Cryptographic ProvIDer which supports SHA-256.    RSACryptoServiceProvIDer csp = (RSACryptoServiceProvIDer)privateCert.PrivateKey;    var enhCsp = new RSACryptoServiceProvIDer().CspKeyContainerInfo;    mKeyContainername = csp.CspKeyContainerInfo.KeyContainername;    var cspparams = new CspParameters    (            enhCsp.ProvIDerType,enhCsp.ProvIDername,mKeyContainername    );    csp = new RSACryptoServiceProvIDer(cspparams);    // Sign the hash    return csp.SignHash(hash,CryptoConfig.MapnameToOID("SHA256"));}

值得注意的是,我使用的是makecert.exe的自签名证书.根据同一篇文章中的another answer,如果我在makercert.exe中包含正确的-sp或-sy标志,则不会出现这些问题.但是,即使指定了这些标志之一(当前使用-sy 24),我仍然需要执行变通方法.

此实现与该帖子中的accepted answer稍有不同(同样,因为我们的私钥不可导出).但该答案确实表明可以在不明确加载支持SHA256的加密提供程序的情况下完成验证.因此,我应该能够在返回上述方法之前执行此 *** 作:

RSACryptoServiceProvIDer csp = (RSACryptoServiceProvIDer)privateCert.PrivateKey;var enhCsp = new RSACryptoServiceProvIDer().CspKeyContainerInfo;mKeyContainername = csp.CspKeyContainerInfo.KeyContainername;var cspparams = new CspParameters(    enhCsp.ProvIDerType,mKeyContainername);csp = new RSACryptoServiceProvIDer(cspparams);// Sign the hashbyte[] signature = csp.SignHash(hash,CryptoConfig.MapnameToOID("SHA256"));// Test to verify the signed hash with public certcsp = (RSACryptoServiceProvIDer)publicCert.PublicKey.Key;if (!csp.VerifyHash(hash,CryptoConfig.MapnameToOID("SHA256"),signature))    throw new CryptographicException();return signature;

但是,这不会验证(顺便说一句,我已经尝试过SignData / VerifyData和SignHash / VerifyHash).我可以让它验证的唯一方法是我是否再次明确加载一个支持SHA256的加密提供程序.不幸的是,从公共证书构造的CspKeyContainerInfo的KeyContainername成员始终为null.因此,我可以获得数据验证的唯一方法是缓存(或硬编码)私钥的KeyContainername.因此,上面的方法和片段中的mKeyContainername字段的原因如下:

// Test to verify the signed hash with public certcsp = (RSACryptoServiceProvIDer)publicCert.PublicKey.Key;enhCsp = new RSACryptoServiceProvIDer().CspKeyContainerInfo;cspparams = new CspParameters(    enhCsp.ProvIDerType,mKeyContainername);csp = new RSACryptoServiceProvIDer(cspparams);if (!csp.VerifyHash(hash,signature))    throw new CryptographicException();

这确实验证了,但我不喜欢硬编码私钥的KeyContainername.私钥在进行验证的计算机上不可用.

有谁知道更好的方法来实现这一目标?谢谢!

解决方法 我偶然发现了自己的答案.原来使用makecert.exe创建的自签名证书是罪魁祸首.如果我使用使用OpenSSL或商业证书创建的证书,我不再需要显式加载支持SHA256的加密提供程序.因此,我不必在用于实例化RSACryptoServiceProvIDer的CspParameters对象中对容器名称进行硬编码.此签名代码现在按预期工作:

RSACryptoServiceProvIDer csp = (RSACryptoServiceProvIDer)privateCert.PrivateKey;// Sign the hashbyte[] signature = csp.SignHash(hash,CryptoConfig.MapnameToOID("SHA256"));

验证方面也是如此:

// Test to verify the signed hash with public certcsp = (RSACryptoServiceProvIDer)publicCert.PublicKey.Key;

我从来没有发现makecert.exe生成的证书有什么不同,但它对我来说并不重要,因为我们现在正在签署商业证书.

总结

以上是内存溢出为你收集整理的c# – 如何(正确)使用RSA和SHA256与.NET验证文件?全部内容,希望文章能够帮你解决c# – 如何(正确)使用RSA和SHA256与.NET验证文件?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1226504.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-05
下一篇2022-06-05

发表评论

登录后才能评论

评论列表(0条)

    保存