获取所有连接的智能卡列表

时间:2014-01-24 12:46:32

标签: c# interop x509certificate smartcard

我正在编写一个使用x509证书签署XML文档的类。我已经能够获得我的智能卡证书并签名了。

但是,要做到这一点,我必须在Windows密钥库中查找x509证书,因此我必须了解我的智能卡,例如颁发者名称或序列号。那太好了。

但我想要一种更方便的方法来获得SmartCard证书。我有两个想法:

  • 从Keystore获取所有证书,并寻找那些“来自SmartCard”的人。 But I dont think i'm able to get such information
  • winscard.dll互操作并获取有关连接到我的计算机的SmartCard的一些信息,因此我可以使用它来查找正确的证书,但这不起作用:

    [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?

如何获取SmartCard证书以签署XML消息?如果你想给我一个奖金答案,为什么我这样做的Interop不起作用?

1 个答案:

答案 0 :(得分:0)

我发现了一种方法,可以知道X509Certificate来自只使用C#的智能卡。这解决了我的问题,自从我编写代码以来已经有一段时间了,我删除了互操作C#和C ++代码。这对我有用:

if (certificate.HasPrivateKey)
{
    ICspAsymmetricAlgorithm aa = certificate.PrivateKey as ICspAsymmetricAlgorithm;

    if (aa == null || !aa.CspKeyContainerInfo.HardwareDevice) 
         DoWhateverYouWant(certificate);
}

如果在代码运行时卡未连接,对我来说不是问题。如果您想获得连接到PC的智能卡列表,可以使用winscard本机API。