在使用C# / CSP中的HSM进行RSA加密时,如何使用不可导出密钥?

8
我正在尝试使用以下代码(RSA密钥CSP50C8C7CD不可导出,且位于HSM中)在C#中使用RSA(CSP中的交换密钥)加密对称密钥:
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操作系统中,通过调用CryptExportKey并传递PRIVATEKEYBLOB参数来导出私钥。

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 操作系统尝试提取私钥(意味着错误,因为该密钥是不可导出的)。
当我在 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中的Encrypt函数需要密钥始终可导出吗?或者我的程序有任何错误?可能是漏掉了某些参数吗?
1个回答

4
您无法在HSM中使用非可导出密钥进行内存加密或解密。由于您尝试在内存中进行加密,.NET会尝试将私钥提取到内存中,而这是被HSM阻止的。另一方面,您可以拥有私钥句柄并将要加密/解密的数据发送到HSM。换句话说,您可以通过指定其句柄告诉HSM使用包含该私钥的私钥对您的数据进行加密。
您的HSM应提供实现PKCS11标准的API,通常使用C编写。您可以从此非托管库中导入方法并在C#中使用它们。在这里,您可以找到一个用C#编写的PKCS11包装库。

使用加密硬件模块(HSM)进行加密,并使用CSP来实现。代码的目的不是在内存中进行加密。HSM提供了一个CSP驱动程序,该驱动程序实现了专门针对Microsoft的API。函数**rsa_dnet.Encrypt(tripleDES.Key, false)**不应尝试提取私钥,因为启用了CspProviderFlags.UseNonExportableKey标志。 - Vasconcelos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接