C# X509Certificate2:确定证书私钥是否属于硬件设备,以及它是否需要PIN
我正在编写一个程序,使用存储在硬件设备(智能卡)上的证书进行加密C# X509Certificate2:确定证书私钥是否属于硬件设备,以及它是否需要PIN,c#,smartcard,x509certificate2,C#,Smartcard,X509certificate2,我正在编写一个程序,使用存储在硬件设备(智能卡)上的证书进行加密 程序必须使用.Net Framework 4.5.2:(不可能更改此选项 我执行的加密操作没有问题:) 序言 据我所知,当包含一个或多个证书的智能卡连接到计算机时,证书将显示在Windows证书存储(CurrentUser/My)中 这由必须安装的智能卡软件管理 由于我的软件必须与任何硬件设备一起工作,最简单的解决方案是弹出一个窗口,让用户选择要使用的证书 第一个问题 我不想显示CurrentUser/My上的所有证书,只想显
- 程序必须使用.Net Framework 4.5.2:(不可能更改此选项
- 我执行的加密操作没有问题:)
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是真的
- 如果智能卡已连接,则向RSACryptServiceProvider强制转换PrivateKey不会引发异常
- 因此,硬件设备是正确的
多谢各位 在评论中,我提供了Win32互操作解决方案,它可能比延迟操作更快。建议的解决方案将扩展证书属性,从中读取提供商名称(我相信,.NET在内部某处也会这样做?)。然后打开指定的提供程序(CSP或KSP)并从提供程序中查询硬件能力。此解决方案不涉及私钥,也不提示输入PIN 呼叫顺序:
CERT\u KEY\u PROV\u INFO\u PROP\u ID
属性pwszProvName
字段NCRYPT\u IMPL\u TYPE\u属性
属性pbOutput
参数将存储4字节整数值)是否启用了NCRYPT\u IMPL\u HARDWARE\u标志
PP\u IMPTYPE
属性pbData
参数将存储一个4字节长的字节数组,该数组表示实现类型的按位组合。检查此值是否启用了CRYPT\u IMPL\u HARDWARE1
标志我目前正在努力解决与OP类似的问题。在我的情况下,用户必须选择任何证书并设置PIN码,无论该证书是否需要PIN码。就目前而言,我提出的唯一解决方案是:
- 提出设置用户确定PIN码的方法
- 检查执行CryptSetProvParam(使用dwParam 32-KeyExchangePin)时是否发生异常,如果发生异常,请通过Marshal.GetLastWin32Error()检查异常值
- 根据错误值确定证书的私钥不需要PIN码
然而,我非常希望看到基于加密API的“正确”解决方案。使用windows资源管理器第一次使卡工作。当您设置驱动程序时,许多问题都会自动处理。阅读供应商用户手册。一旦卡与资源管理器一起使用,您就可以将其与c#代码一起使用。Windows资源管理器将解锁该卡,然后您可以进行读写操作。智能卡有不同的寻址模式和数据大小(8,16,32,64)。因此,请确保您可以使用windows进行写操作,并使用c#进行读操作(反之亦然)。然后编写代码以在c#中解锁。您需要知道解锁卡的大小。
这非常慢
——有多慢?您可以考虑使用Win32互操作来查询证书属性,读取提供程序名称,然后查询提供程序。