2014-01-24 39 views
1

我在寫一個使用x509證書籤名XML文檔的類。我已經能夠獲得我的智能卡證書並簽名。獲取所有連接的智能卡的列表

但是,要做到這一點,我必須在Windows密鑰庫中尋找x509證書,所以我必須知道關於我的智能卡的信息,例如頒發者名稱或序列號。這很好。

但我想要一個更方便的方法來獲得智能卡證書。我有兩個想法:

  • 獲取來自密鑰庫的所有證書,並尋找那些「來自智能卡」的人。 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?

如何獲得SmartCard證書以簽署XML消息?如果你想給我一個獎勵答案,爲什麼這個Interop我沒有工作?

+1

'SCardListCards'沒有返回智能卡列表,因爲您可能在錯誤的域中搜索它們。 嘗試在系統上下文中搜索智能卡,而不是在用戶上下文中。 例如:'Interop.SCardEstablishContext(2,0,0,ref處理);' – ClotzA

+0

試過了,並沒有工作。我也試圖與SCardListReaders進行互操作,並且工作。現在我試圖像這樣初始化crds變量:'string crds = new string('\ 0',1000);'但結果是一樣的。該字符串不會更改。 –

+1

看來你需要調用'SCardListCards'兩次:第一次獲得緩衝區長度,第二次實際填充緩衝區。 看看這個例子:http://www.pinvoke.net/default.aspx/winscard.scardestablishcontext – ClotzA

回答

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。