2011-09-26 100 views
3

我試圖驗證從簽名證書鏈回到特定的根證書,這是而不是受Windows信任(它是應用程序的專用證書)。獲取證書鏈到私人根

我目前的嘗試做到這一點涉及創建一個鏈接引擎,它只信任我想要的特定證書作爲根目錄,以便不會生成其他鏈。

HCERTSTORE hPrivateRootStore = CertOpenStore(CERT_STORE_PROV_FILENAME, dwEncoding, 
    NULL, CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, 
    _T("C:\\Test\\PrivateRoot.cer")); 
CERT_CHAIN_ENGINE_CONFIG config; 
memset(&config, 0, sizeof(config)); 
config.cbSize = sizeof(config); 
config.hRestrictedTrust = hPrivateRootStore; 
config.dwFlags = CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL | CERT_CHAIN_ENABLE_SHARE_STORE; 
HCERTCHAINENGINE hEngine; 
CertCreateCertificateChainEngine(&config, &hEngine); 
CERT_CHAIN_PARA params; 
memset(&params, 0, sizeof(params)); 
params.cbSize = sizeof(params); 
PCCERT_CHAIN_CONTEXT chains = NULL; 
if (CertGetCertificateChain(hEngine, pCertContext, NULL, hStore, &params, 
    0, NULL, &chains)) 
    ... 
(檢查省略錯誤清晰度; pCertContexthStoreCryptQueryObject來提取簽署的二進制文件的簽名和相關證書。)

不幸的是,這似乎並沒有工作;儘管使用了自定義鏈接引擎,但它似乎仍在搜索操作系統存儲庫,並且沒有找到鏈或找到一個不同的根目錄(這是操作系統信任的)。我只能通過將我的私有根證書添加到操作系統信任的商店來獲得我想要的鏈。

我也嘗試將config.hRestrictedOther設置爲空的內存存儲區,因爲文檔建議非空的hRestrictedTrust會再次引入系統存儲區,但這沒有任何區別。

有什麼我失蹤,或更好的方式來做到這一點?

編輯:只是爲了給更多的情況下,我試圖做類似驅動程序簽名的證書,其中籤名證書鏈接回兩個不同的東西根:一個標準的CA根由OS信任,一個內部根目錄(在驅動程序中也受操作系統信任,但在我的情況下只會受到我的應用程序的信任)。交叉發生在「主」鏈中間的某個地方;可能會有許多不同的文件都與不同的「真實」CA簽署,但仍然鏈接到我的內部證書。

+0

經過一番調查,我發現在Win7中'hExclusiveRoot'成員被添加到'CERT_CHAIN_ENGINE_CONFIG'。我認爲相關的描述清楚地表明'CertCreateCertificateChainEngine'不提供任何機制來忽略舊版本中的系統存儲(這讓我想知道它到底是什麼,但這是一個單獨的問題)。所以,新的問題:是否有其他方法來枚舉可能的鏈回到我想要的根?與'CertVerifyCertificateChainPolicy'兼容的東西會很好,儘管如果需要的話我可能沒有它。 – Miral

+0

你試圖分析的證書文件格式是什麼? –

+0

該主題是Authenticode簽名的二進制文件,所需的根目錄是一個編譯到應用程序中的.cer,並作爲「PCCERT_CONTEXT」加載。 – Miral

回答

2

我已經找到了一個半熟的解決方法;這有點難看,但它確實有點用。我從 Chromium's test suite得到了基本的想法;它涉及在Crypt32中安裝一個鉤子,以便當它試圖打開系統存儲以構建鏈時,它將獲得我的自定義存儲,而只包含我所需的證書。

好的是,這似乎迫使 CertGetCertificateChain去「過去」真正的CA證書鏈中的所有方法我自定義證書,而不是在CA證書停止(這是它通常不會當是可信的)。

糟糕的是,它似乎並沒有阻止它建立鏈和信任任何其他CA證書。我可以通過明確驗證鏈的根源是我想要的證書來解決這個問題,但這並不理想,而且我不確定是否有情況會導致此問題。

仍在尋找更好的解決方案;我肯定會覺得我在某個地方走錯了路。

好的,新的計劃。我現在只是手動走鏈(因爲我知道我關心的所有證書都將在從簽名中提取的hStore中。基本結構如下:

  • 使用WinVerifyTrust做基本的「是不是篡改」身份驗證。
  • 使用CryptQueryObject獲得證書存儲hStore從.exe
  • 使用CryptMsgGetParamCertFindCertificateInStore找到從hStore簽名證書。
  • 從簽名證書開始,使用CertFindCertificateInStoreCERT_FIND_SUBJECT_NAME循環查找潛在的頒發者證書;繼續前行,直到我點擊自簽名證書或找到我想要的根(通過CertComparePublicKeyInfo檢查比賽)。
  • 如果CertVerifySubjectCertificateContext表示簽名不匹配,則放棄特定的分支。

似乎比我以前的方法更清潔。思想/評論/替代品?

(在某些方面似乎更有意義的東西是添加一個額外的自定義聯署[類似於時間戳],而不是試圖鏈接這樣的證書,但我找不到任何關於這樣做的信息,或者有什麼優點/缺點)。

相關問題