【发布时间】:2020-11-24 18:03:12
【问题描述】:
我正在编写一个程序来进行加密,使用存储在硬件设备(智能卡)上的证书。
- 程序必须使用 .Net Framework 4.5.2 :( 无法更改。
- 我执行的加密操作没有问题 :)
序言
据我了解,当包含一个或多个证书的智能卡连接到计算机时,证书会出现在 Windows 证书存储区 (CurrentUser/My) 中。
这是由必须安装的智能卡软件管理的。
由于我的软件必须适用于任何硬件设备,最简单的解决方案是弹出一个窗口,让用户选择要使用的证书。
第一个问题
我不想显示 CurrentUser/My 上的所有证书,而只显示那些有相关硬件连接到计算机的证书。
这或多或少是我正在使用的代码:
X509Store storeObject = new X509Store(StoreName.My, StoreLocation.CurrentUser);
storeObject.Open(OpenFlags.ReadOnly);
foreach (var certificate in storeObject.Certificates)
{
bool isValid = false;
if (certificate.HasPrivateKey)
{
try
{
var rsaKey = certificate.PrivateKey as RSACryptoServiceProvider;
if (rsaKey.CspKeyContainerInfo.HardwareDevice)
{
isValid = true;
}
}
catch (Exception ex)
{
// just log
}
}
}
尽管这个解决方案非常难看,但这是我想出的最好的。
如果满足以下条件,则证书属于智能卡:
- HasPrivateKey 为真。
- 如果智能卡已连接,则将 PrivateKey 转换为 RSACryptoServiceProvider 不会引发异常。
- HardwareDevice 则为真。
问题出在 PrivateKey 转换上:似乎很多事情都是由 CryptoApi 系统在此转换期间执行的(当然包括对智能卡软件的调用)。
这非常慢,如果智能卡软件出现某种故障,则会显示无法控制的错误消息,...
问题
有没有其他方法可以确定证书是否属于硬件设备? 并确定硬件当前是否已连接?
第二个问题
证书可能需要 PIN。
我必须(这是一个先决条件)避免出现要求输入 PIN 的 Windows 输入框。
收集 PIN 码并在我的加密操作期间使用它对我来说不是问题。
我的问题是了解是否需要 PIN。
我在网上找到的任何示例都假定如果 rsaKey.CspKeyContainerInfo.HardwareDevice == true 则需要 PIN。
但我不确定。
问题
有什么方法可以确定证书是否需要 PIN 码?
结论
我也喜欢外部库,只要它们是免费的(最好是开源的)和/或来自 Microsoft。
非常感谢!
【问题讨论】:
-
使用 Windows 资源管理器让卡第一次工作。当您设置驱动程序时,很多这些问题都会自动处理。阅读供应商用户手册。一旦卡与资源管理器一起使用,您就可以将其与 c# 代码一起使用。 Windows 资源管理器将解锁卡,然后您就可以读写了。智能卡具有不同的寻址模式和数据大小 (8,16,32,64)。因此,请确保您可以使用 windows 编写并使用 c# 阅读(反之亦然)。然后在c#中编写代码解锁。您需要知道能够解锁卡的尺寸。
-
This is very slow-- 有多慢?您可以考虑使用 Win32 互操作来查询证书属性,读取提供程序名称,然后查询提供程序信息,说明密钥是否存储在智能卡上。 -
@Crypt32 对于每次转换(certificate.PrivateKey as RSACryptoServiceProvider)慢至 2/3 秒。我的问题不是获取证书属性,除了 PrivateKey,因为上面的转换有时(当卡没有连接,或者智能卡软件有问题时)会出现问题。我想知道这是否是检索 CspKeyContainerInfo.HardwareDevice 属性并了解卡是否已连接的唯一方法。我将尝试使用 Win32 互操作,但我怀疑我会得到相同的结果。
-
属性不是
X509Certificate2对象的一部分,它们不能直接从.NET API访问,它们可以通过Win32互操作获得。
标签: c# smartcard x509certificate2