Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何(正确地)使用RSA和SHA256与.NET验证文件?_C#_.net_Hash_Rsa_Digital Signature - Fatal编程技术网

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

C# 如何(正确地)使用RSA和SHA256与.NET验证文件?,c#,.net,hash,rsa,digital-signature,C#,.net,Hash,Rsa,Digital Signature,我正在用.NET对数据进行数字签名/验证。我修改了该示例代码以使用SHA256,并点击了“指定的算法无效”异常,这导致我在.NET4.0中使用SHA256对数据进行签名 从那篇文章中,我了解到如何通过显式加载支持SHA256的加密提供程序而不依赖可导出的私钥来正确生成数字签名(请参阅以下方法底部的代码,其中构建了RSACryptServiceProvider): 值得注意的是,我使用的是makecert.exe中的自签名证书。根据同一篇文章,如果我在makercert.exe中包含适当的-sp或

我正在用.NET对数据进行数字签名/验证。我修改了该示例代码以使用SHA256,并点击了“指定的算法无效”异常,这导致我在.NET4.0中使用SHA256对数据进行签名

从那篇文章中,我了解到如何通过显式加载支持SHA256的加密提供程序而不依赖可导出的私钥来正确生成数字签名(请参阅以下方法底部的代码,其中构建了RSACryptServiceProvider):

值得注意的是,我使用的是makecert.exe中的自签名证书。根据同一篇文章,如果我在makercert.exe中包含适当的-sp-sy标志,这些问题就不会发生。但是,即使指定了这些标志中的任何一个(当前使用的是-sy 24),我仍然必须执行变通方法

这个实现与那篇文章中的略有不同(同样,因为我们的私钥是不可导出的)。但该答案确实表明,验证可以在不显式加载支持SHA256的加密提供程序的情况下完成。因此,在使用上述方法返回之前,我应该能够做到这一点:

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
byte[] signature = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));

// Test to verify the signed hash with public cert
csp = (RSACryptoServiceProvider)publicCert.PublicKey.Key;
if (!csp.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA256"), signature))
    throw new CryptographicException();

return signature;
但是,这无法验证(顺便说一句,我已经尝试了SignData/VerifyDataSignHash/VerifyHash)。唯一可以让它验证的方法是,是否再次显式加载支持SHA256的加密提供程序。不幸的是,从公共证书构造的CspKeyContainerInfoKeyContainerName成员始终为空。因此,获取数据进行验证的唯一方法是缓存(或硬编码)私钥的KeyContainerName。因此,上面的方法和下面的代码片段中出现mKeyContainerName字段的原因如下:

// Test to verify the signed hash with public cert
csp = (RSACryptoServiceProvider)publicCert.PublicKey.Key;
enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo;
cspparams = new CspParameters
(
    enhCsp.ProviderType, enhCsp.ProviderName, mKeyContainerName
);
csp = new RSACryptoServiceProvider(cspparams);
if (!csp.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA256"), signature))
    throw new CryptographicException();
这确实可以验证,但我不喜欢硬编码私钥的KeyContainerName。私钥在进行验证的计算机上不可用


有人知道更好的方法来实现这一点吗?谢谢

我无意中找到了自己的答案。事实证明,使用使用makecert.exe创建的自签名证书是罪魁祸首。如果我使用OpenSSL创建的证书或商业证书,我就不再需要显式加载支持SHA256的加密提供程序。因此,我不必在用于实例化RSACryptServiceProvider的CspParameters对象中硬编码容器名称。此签名代码现在按预期工作:

RSACryptoServiceProvider csp = (RSACryptoServiceProvider)privateCert.PrivateKey;
// Sign the hash
byte[] signature = csp.SignHash(hash, CryptoConfig.MapNameToOID("SHA256"));
验证端也是如此:

// Test to verify the signed hash with public cert
csp = (RSACryptoServiceProvider)publicCert.PublicKey.Key;
我从未发现makecert.exe生成的证书有什么不同,但这对我来说并不重要,因为我们现在正在使用商业证书进行签名

// Test to verify the signed hash with public cert
csp = (RSACryptoServiceProvider)publicCert.PublicKey.Key;