使用C#/ CSP在HSM中使用不可导出密钥进行RSA加密

我正在尝试使用这段代码在C#中使用RSA(CSP中的Exchange密钥)加密对称密钥(RSA密钥CSP50C8C7CD不可导出,并且它在HSM中):

CspParameters csp_dnet = new CspParameters(1, "HSM especific CSP");
csp_dnet.Flags = CspProviderFlags.UseNonExportableKey;
csp_dnet.KeyContainerName = "test";

RSACryptoServiceProvider rsa_dnet = new RSACryptoServiceProvider(csp_dnet);

// Create 3DES key
TripleDES tripleDES = new TripleDESCryptoServiceProvider();

// Encrypt 3DES with RSA
byte[] encryptedSessionKey = rsa_dnet.Encrypt(tripleDES.Key, false);

看到CSP日志,我注意到C#正在尝试导出密钥以继续操作.下面的CSP日志只显示了关于rsa_dnet.Encrypt的部分:

LOG CSP

...

[12/12/2012 17:28:45] [3688] D [CryptExportKey]  Blob type: PRIVATEKEYBLOB

...

[12/12/2012 17:28:45] [3688] E [CryptExportKey]  Return: FALSE. An internal error occurred.

Windows SO调用CryptExportKey传递PRIVATEKEYBLOB意味着导出de私钥.

LOG HSM

...
2012/12/12 17:44:02 [4DD18140] new key 'test/CSP50C8C7CD', t: 6, a: 0
2012/12/12 17:44:14 [4DC2A1C0] 'test' auth ok, 10.0.87.19
2012/12/12 17:44:17 [4DC2A1C0] 'test/CSP50C8C7CD' not exportable, conn: 9  --- ERROR

在HSM中,此日志显示Windows SO正在尝试提取私钥(ERRO是什么意思,因为密钥是不可导出的).

当我在HSM中使用可导出的密钥CSP50C8C7CE时,日志显示一切都可以:

LOG HSM

...

2012/12/12 17:47:46 [4DEF4040] 'test' auth ok, IP: 10.0.87.19
2012/12/12 17:47:46 [4DEF4040] export: 'test/CSP50C8C7CE', 1462
2012/12/12 17:47:46 [4DEF4040] export: 'test/CSP50C8C7CE', 1462
2012/12/12 17:47:46 [4DEF4040] delete 'test/CSP50C8C7CE'
2012/12/12 17:47:46 [4DEF4040] import obj 'test/CSP50C8C7CE', 00000004
2012/12/12 17:47:46 [4DEF4040] pk test/CSP50C8C7CE [1]
2012/12/12 17:47:46 [4DEF4040] import obj 'cf1c34c8be5d2fa8a4575c63dd903454', 00000003
2012/12/12 17:47:46 [4DEF4040] delete 'test/CSP50C8C7CE'
2012/12/12 17:47:46 [4DEF4040] import obj 'test/CSP50C8C7CE', 00000006
2012/12/12 17:47:47 [4DEF4040] export: 'cf1c34c8be5d2fa8a4575c63dd903454', 24
2012/12/12 17:47:47 [4DEF4040] delete 'cf1c34c8be5d2fa8a4575c63dd903454'

请注意,此日志显示了许多RSA密钥导入/导出操作(参考:CSP50C8C7CE – 可导出密钥).

问题:库System.Cryptography中的加密功能需要密钥必须始终可导出吗?或者我在我的程序中犯了什么错误?也许任何错过的参数?

最佳答案
您不能在HSM中使用不可导出的密钥在内存中进行加密或解密.由于您尝试在内存中进行加密,因此.NET尝试将私钥提取到内存中,并且HSM会阻止它.另一方面,您可以拥有私钥的句柄,并将“要加密/解密的数据”发送给HSM.换句话说,您可以通过指定其句柄告诉HSM使用它包含的私钥来加密您的数据.

您的HSM应该为您提供实现PKCS11标准的API,并且通常用C语言编写.您可以从此非托管库中使用extern方法并在C#中使用它们. Here你可以找到用C#编写的PKCS11包装库.

转载注明原文:使用C#/ CSP在HSM中使用不可导出密钥进行RSA加密 - 代码日志