如何使用RSA和SHA256与.NET签名文件? [英] How can I sign a file using RSA and SHA256 with .NET?

查看:2003
本文介绍了如何使用RSA和SHA256与.NET签名文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程式会收集一组档案并签名。 (我不想签署一个程序集。)有一个.p12文件,我从中获得私钥。

My application will take a set of files and sign them. (I'm not trying to sign an assembly.) There is a .p12 file that I get the private key from.

这是我试图使用的代码,但我得到一个 System.Security.Cryptography.CryptographicException指定的算法无效。

This is the code I was trying to use, but I get a System.Security.Cryptography.CryptographicException "Invalid algorithm specified.".

X509Certificate pXCert = new X509Certificate2(@"keyStore.p12", "password");
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)pXCert.PrivateKey;
string id = CryptoConfig.MapNameToOID("SHA256");
return csp.SignData(File.ReadAllBytes(filePath), id);

根据 answer 它不能做(RSACryptoServiceProvider不支持SHA-256),但我希望它可能可能使用不同的图书馆,如Bouncy城​​堡。

According to this answer it can't be done (the RSACryptoServiceProvider does not support SHA-256), but I was hoping that it might be possible using a different library, like Bouncy Castle.

我是新的这个东西,我发现Bouncy城​​堡是非常混乱。我将一个Java应用程序移植到C#,我必须使用相同类型的加密来签署文件,所以我被困在RSA + SHA256。

I'm new to this stuff and I'm finding Bouncy Castle to be very confusing. I'm porting a Java app to C# and I have to use the same type of encryption to sign the files, so I am stuck with RSA + SHA256.

如何我使用Bouncy城​​堡,OpenSSL.NET,Security.Cryptography或另一个我没有听说过的第三方库这样做?我假设,如果它可以在Java中完成,那么它可以在C#中完成。

How can I do this using Bouncy Castle, OpenSSL.NET, Security.Cryptography, or another 3rd party library I haven't heard of? I'm assuming, if it can be done in Java then it can be done in C#.

更新:

这是我从poupou的anwser链接获得的

this is what I got from the link in poupou's anwser

        X509Certificate2 cert = new X509Certificate2(KeyStoreFile, password");
        RSACryptoServiceProvider rsacsp = (RSACryptoServiceProvider)cert.PrivateKey;
        CspParameters cspParam = new CspParameters();
        cspParam.KeyContainerName = rsacsp.CspKeyContainerInfo.KeyContainerName;
        cspParam.KeyNumber = rsaCSP.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2;
        RSACryptoServiceProvider aescsp = new RSACryptoServiceProvider(cspParam);
        aescsp.PersistKeyInCsp = false;
        byte[] signed = aescsp.SignData(File.ReadAllBytes(file), "SHA256");
        bool isValid = aescsp.VerifyData(File.ReadAllBytes(file), "SHA256", signed);

问题是,我没有得到与原来的工具相同的结果。就我可以从阅读代码告诉CryptoServiceProvider做实际签名不使用私钥从密钥存储文件。是正确的?

The problem is that I'm not getting the same results as I got with the original tool. As far as I can tell from reading the code the CryptoServiceProvider that does the actual signing is not using the PrivateKey from key store file. Is that Correct?

推荐答案

RSA + SHA256可以并将工作...

RSA + SHA256 can and will work...

您的后续示例可能不能始终工作,应该使用哈希算法的OID,而不是名称。根据你的第一个例子,这是从调用[CryptoConfig.MapNameToOID](AlgorithmName) 1 其中AlgorithmName是您提供的(即SHA256)。

Your later example may not work all the time, it should use the hash algorithm's OID, rather than it's name. As per your first example, this is obtained from a call to [CryptoConfig.MapNameToOID](AlgorithmName)1 where AlgorithmName is what you are providing (i.e. "SHA256").

首先,您需要的是证书与私钥。我通常通过使用公共密钥文件(.cer)来识别私钥,然后枚举证书并匹配哈希值从LocalMachine或CurrentUser存储中读取...

First you are going to need is the certificate with the private key. I normally read mine from the LocalMachine or CurrentUser store by using a public key file (.cer) to identify the private key, and then enumerate the certificates and match on the hash...

X509Certificate2 publicCert = new X509Certificate2(@"C:\mycertificate.cer");

//Fetch private key from the local machine store
X509Certificate2 privateCert = null;
X509Store store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
foreach( X509Certificate2 cert in store.Certificates)
{
    if (cert.GetCertHashString() == publicCert.GetCertHashString())
        privateCert = cert;
}

但是,一旦您获得了带有私钥的证书我们需要重建它。这可能是必需的,因为证书创建它的私钥的方式,但我不确定为什么。无论如何,我们首先导出密钥,然后使用任何你喜欢的中间格式重新导入它,最简单的是xml:

However you get there, once you've obtained a certificate with a private key we need to reconstruct it. This may be required due to the way the certificate creates it's private key, but I'm not really sure why. Anyway, we do this by first exporting the key and then re-importing it using whatever intermediate format you like, the easiest is xml:

//Round-trip the key to XML and back, there might be a better way but this works
RSACryptoServiceProvider key = new RSACryptoServiceProvider();
key.FromXmlString(privateCert.PrivateKey.ToXmlString(true));

一旦完成,我们现在可以如下签名一个数据:

Once that is done we can now sign a piece of data as follows:

//Create some data to sign
byte[] data = new byte[1024];

//Sign the data
byte[] sig = key.SignData(data, CryptoConfig.MapNameToOID("SHA256"));

最后,验证可以使用证书的公钥直接完成,无需重建与私钥:

Lastly, the verification can be done directly with the certificate's public key without need for the reconstruction as we did with the private key:

key = (RSACryptoServiceProvider)publicCert.PublicKey.Key;
if (!key.VerifyData(data, CryptoConfig.MapNameToOID("SHA256"), sig))
    throw new CryptographicException();

这篇关于如何使用RSA和SHA256与.NET签名文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆