为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用RSA和SHA256和.NET签署文件?

如何使用RSA和SHA256和.NET签署文件?

哆啦的时光机 2019-10-28 10:31:11
我的应用程序将获取一组文件并对其进行签名。(我不是要对程序集进行签名。)我从中获取了一个.p12文件,该文件是私钥。这是我尝试使用的代码,但是得到了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);根据这个答案,这是不可能的(RSACryptoServiceProvider它不支持SHA-256),但是我希望可以使用不同的库(例如Bouncy Castle)来实现。我是新手,发现Bouncy Castle非常令人困惑。我正在将Java应用程序移植到C#,并且必须使用相同类型的加密来对文件进行签名,因此我陷入了RSA + SHA256的困境。如何使用Bouncy Castle,OpenSSL.NET,Security.Cryptography或我未曾听说的其他第三方库来执行此操作?我假设,如果可以用Java完成,那么可以用C#完成。更新:这是我从Poupou的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没有使用密钥存储文件中的PrivateKey。那是对的吗?
查看完整描述

3 回答

?
撒科打诨

TA贡献1934条经验 获得超2个赞

RSA + SHA256可以并且将...


您后面的示例可能并非始终有效,它应使用哈希算法的OID,而不是名称。根据你的第一个例子,这是从调用获得的CryptoConfig.MapNameToOID(AlgorithmName),其中AlgorithmName是您所提供的(即“SHA256”)。


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


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:


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

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


//Create some data to sign

byte[] data = new byte[1024];


//Sign the data

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

最后,可以直接使用证书的公钥进行验证,而无需像使用私钥那样进行重建:


key = (RSACryptoServiceProvider)publicCert.PublicKey.Key;

if (!key.VerifyData(data, CryptoConfig.MapNameToOID("SHA256"), sig))

    throw new CryptographicException();


查看完整回答
反对 回复 2019-10-28
  • 3 回答
  • 0 关注
  • 553 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信