如果你知道哪些證書可以是根證書和中間證書的證書來檢查,你可以加載根和中間的公共密鑰ChainPolicy.ExtraStore
X509Chain
對象集合
我的任務是編寫一個Windows Forms應用程序來安裝證書,只要它是依賴於我國政府已知的「國家根證書」發佈的。是允許頒發證書來驗證與國家Web服務的連接的有限數量的CA,所以我擁有了一個有限的一組證書可能在鏈中,並且可能在目標機器上丟失。我收集了CA和政府根證書的所有公鑰,並將其存儲在應用的子目錄「cert」中: ![chain certificates](https://i.stack.imgur.com/zok4R.png)
在Visual Studio中,我將該目錄cert添加到解決方案中,資源。這讓我枚舉了我的c#庫代碼中的「可信」證書集合,即使未安裝頒發者證書,也可以構建一個鏈來檢查證書。我做了一個包裝類X509Chain爲了這個目的:
private class X509TestChain : X509Chain, IDisposable
{
public X509TestChain(X509Certificate2 oCert)
: base(false)
{
try
{
ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
if (!Build(oCert) || (ChainElements.Count <= 1))
{
Trace.WriteLine("X509Chain.Build failed with installed certificates.");
Assembly asmExe = System.Reflection.Assembly.GetEntryAssembly();
if (asmExe != null)
{
string[] asResources = asmExe.GetManifestResourceNames();
foreach (string sResource in asResources)
{
if (sResource.IndexOf(".cert.") >= 0)
{
try
{
using (Stream str = asmExe.GetManifestResourceStream(sResource))
using (BinaryReader br = new BinaryReader(str))
{
byte[] abResCert = new byte[str.Length];
br.Read(abResCert, 0, abResCert.Length);
X509Certificate2 oResCert = new X509Certificate2(abResCert);
Trace.WriteLine("Adding extra certificate: " + oResCert.Subject);
ChainPolicy.ExtraStore.Add(oResCert);
}
}
catch (Exception ex)
{
Trace.Write(ex);
}
}
}
}
if (Build(oCert) && (ChainElements.Count > 1))
Trace.WriteLine("X509Chain.Build succeeded with extra certificates.");
else
Trace.WriteLine("X509Chain.Build still fails with extra certificates.");
}
}
catch (Exception ex)
{
Trace.Write(ex);
}
}
public void Dispose()
{
try
{
Trace.WriteLine(string.Format("Dispose: remove {0} extra certificates.", ChainPolicy.ExtraStore.Count));
ChainPolicy.ExtraStore.Clear();
}
catch (Exception ex)
{
Trace.Write(ex);
}
}
}
在調用函數,我現在就可以成功地檢查是否有未知的證書由國家根證書導出:
bool bChainOK = false;
using (X509TestChain oChain = new X509TestChain(oCert))
{
if ((oChain.ChainElements.Count > 0)
&& IsPKIOverheidRootCert(oChain.ChainElements[oChain.ChainElements.Count - 1].Certificate))
bChainOK = true;
if (!bChainOK)
{
TraceChain(oChain);
sMessage = "Root certificate not present or not PKI Overheid (Staat der Nederlanden)";
return false;
}
}
return true;
要完成圖片:檢查根證書(通常是安裝的,因爲它包含在Windows Update中,但理論上也可能丟失),我將友好名稱和指紋與公佈的值進行比較:
private static bool IsPKIOverheidRootCert(X509Certificate2 oCert)
{
if (oCert != null)
{
string sFriendlyName = oCert.FriendlyName;
if ((sFriendlyName.IndexOf("Staat der Nederlanden") >= 0)
&& (sFriendlyName.IndexOf(" Root CA") >= 0))
{
switch (oCert.Thumbprint)
{
case "101DFA3FD50BCBBB9BB5600C1955A41AF4733A04": // Staat der Nederlanden Root CA - G1
case "59AF82799186C7B47507CBCF035746EB04DDB716": // Staat der Nederlanden Root CA - G2
case "76E27EC14FDB82C1C0A675B505BE3D29B4EDDBBB": // Staat der Nederlanden EV Root CA
return true;
}
}
}
return false;
}
我不確定這個檢查是否安全,但在我的情況下,Windows Forms應用程序的操作員非常確定可以訪問要安裝的有效證書。該軟件的目標是過濾證書列表,以幫助他在計算機的機器存儲區中只安裝正確的證書(該軟件還安裝中間證書和根證書的公鑰,以確保證書的運行時行爲Web服務客戶端是正確的)。
我編輯了這個問題,它是一個.NET 2.0 Winforms應用程序。 – RainerM 2011-05-23 14:54:23