我在我的应用程序的客户机 - 服务器架构,使用SSL。 目前,私人密钥存储在CAPI的密钥存储位置。 出于安全原因,我想存储在一个安全的地方的关键,理想的硬件签名模块(HSM)就是这个目的建造。 不幸的是,这种存储设备上的私钥,我无法弄清楚如何在我的应用程序中使用它。
在服务器上,我只是使用SslStream
类和AuthenticateAsServer(...)
调用。 此方法需要一个X509Certificate
,有它加载私钥对象,但因为私有密钥存储在一个安全的HSM(如非导出)的位置,我不知道如何做到这一点。
在客户端,我使用的是HttpWebRequest
对象,然后使用ClientCertificates
属性加我的客户端身份验证证书,但我在这里有同样的问题:我如何才能私钥?
我知道有一些硬件安全模块充当SSL加速器,但我并不真的需要一个加速器。 此外,这些产品往往有网络服务器,如IIS和Apache是哪个我不使用特殊的集成。
有任何想法吗? 我能想到的唯一的事情就是写我自己的SSL库,可以让我的手离开交易到HSM签订部分,但是这似乎是一个巨大的工作量。
作为拉斯穆斯说你应该从你的HSM生产使用CSP。 检查此链接:
http://forums.asp.net/t/1531893.aspx
我成功地用一点点不同的方法在客户端上的客户端进行身份验证的HTTPS HttpWebRequest
, ClientCertificates
和智能卡。 在我的情况下,私有密钥存储在智能卡(类似于HSM)。 智能卡CSP然后使用PKCS#11签名,ENC /解密等,但这并不重要。 物业X509Certificate.Handle
在SSL建立用于签名的客户端上的挑战,这个手柄包含有关证书的私钥信息。
在我的情况,我想以编程为智能卡设置引脚,以避免“输入PIN”从智能卡对话框中SSL创作的过程中,我也有这个功能做到了:
public void SetContext(X509Certificate2 cert)
{
IntPtr p = IntPtr.Zero;
bool result = Win32.CryptAcquireContext(ref p, "keyContainer", "Siemens Card API CSP", 1, 0);
byte[] pin = new ASCIIEncoding().GetBytes("0000");
result = Win32.CryptSetProvParam(p, 32, pin, 0);
result = Win32.CertSetCertificateContextProperty(cert.Handle, 1, 0, p);
}
你可以找到所有已安装的CSP的名称HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider
。 Win32
是我对C ++ / C#互操作类,看起来像这样:
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CryptAcquireContext(
ref IntPtr hProv,
string pszContainer,
string pszProvider,
uint dwProvType,
uint dwFlags
);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CryptSetProvParam(
IntPtr hProv,
uint dwParam,
[In] byte[] pbData,
uint dwFlags);
[DllImport("CRYPT32.DLL")]
internal static extern Boolean CertSetCertificateContextProperty(
IntPtr pCertContext,
uint dwPropId,
uint dwFlags,
IntPtr pvData
);
如果HSM带有CAPI CSP与可以做到以下几点:
var certificate = new X509Certificate2(pathToPublicCert);
var cspParameters = new CspParameters()
{
ProviderType = 1, /* Use 1 instead of 24 (the default) */
ProivderName = "My HSM Cryptographic Provider Name",
KeyContainerName = "My Private Key Container Name",
KeyNumber = 1, /* Key exchange key */
Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseNonExportableKey,
};
var privateKey = new RSACryptoServiceProvider(cspParameters);
certificate.PrivateKey = privateKey;
这应该工作。 请注意,如果您使用24而不是1提供商类型,这可能无法正常工作(它没有至少在默认CSP)。
在HSM的我曾经使用过,这是不可见的。 有通常用于生成密钥对(用于生成证书请求或已完成的证书分发到更多的机器比,你生成的证书请求,这取决于它是什么样的HSM)的一个不同的过程,但一旦安装了证书在机器上,显示为一个带有私钥的正常证书,你只需要使用它,就像任何其他证件。
取决于HSM的配置设置私钥被导出。 您需要发言的HSM供应商以找出他们的HSM的提供此功能。
该HSM可以用CryptoAPI的CSP实现出货。 如果键正确映射到CryptoAPI中的证书,SslStream应该能够使用它而不导出。