我正在编写一个使用 x509 证书签署 XML 文档的类。我已经能够获得我的 SmartCard 证书并对其进行签名。
但是,为此我必须在 Windows Keystore 中查找 x509 证书,因此我必须知道一些关于我的智能卡的信息,例如发行者名称或序列号。这很好。
但我想要一种更方便的方法来获取智能卡证书。我有两个想法:
- 从 Keystore 获取所有证书并寻找那些“来自智能卡”的证书。 But I dont think i'm able to get such information .
与
winscard.dll
互操作并获取有关连接到我的计算机的智能卡的一些信息,因此我可以使用它来查找正确的证书,但这不起作用:[DllImport("winscard.dll")] public static extern long SCardListCards( uint hContext, int pbAtr, int rgguidInterfaces, int cguidInterfaceCount, [MarshalAs(UnmanagedType.LPTStr)] ref string mszCards, ref int pcchCards); [DllImport("winscard.dll")] public static extern long SCardEstablishContext(uint dwScope, int pvReserved1, int pvReserved2, ref uint phContext);
这是一个测试方法。 string crds
包含智能卡列表。
[TestMethod]
public void TestInterop()
{
uint handle = 0;
Interop.SCardEstablishContext(0, 0, 0, ref handle);
string crds = "";
int pcch = 0;
Interop.SCardListCards(handle, 0, 0, 0, ref crds, ref pcch);
Assert.IsTrue(crds != "");
}
这个测试每次都会失败,因为 crds
永远不会改变。
如果我尝试将 crds
作为 byte[]
返回:
[DllImport("winscard.dll", EntryPoint = "SCardListCards")]
public static extern long SCardListCardsRetBytes(
uint hContext, int pbAtr,
int rgguidInterfaces, int cguidInterfaceCount,
ref byte[] mszCards,
ref int pcchCards);
我的 byte[] crds
变成了:
byte[] {171}
当我用byte[] crds = {};
初始化它时为什么是 171?byte[] {0}
当我用byte[] crds = new byte[32];
初始化它时为什么是 0?
如何获得智能卡证书来签署 XML 消息?如果您想给我一个额外的答案,为什么我做的这个 Interop 不起作用?
最佳答案
我发现了一种仅使用 C# 即可知道 X509Certificate
是否来自智能卡的方法。这为我解决了问题,自从我编写代码以来已经有一段时间了,我删除了互操作 C# 和 C++ 代码。这对我有用:
if (certificate.HasPrivateKey)
{
ICspAsymmetricAlgorithm aa = certificate.PrivateKey as ICspAsymmetricAlgorithm;
if (aa == null || !aa.CspKeyContainerInfo.HardwareDevice)
DoWhateverYouWant(certificate);
}
如果在代码运行的那一刻没有连接卡,对我来说不是问题。如果您想获得连接到您的 PC 的智能卡列表,可以使用 winscard
native API。
关于c# - 获取所有连接的智能卡的列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21333115/