Dot-Net

如何根據 X509Certificate2Collection 鏈驗證 X509Certificate2

  • May 31, 2011

我正在編寫一個 SAML 2.0 響應解析器來處理 ASP.Net 中的 POST 身份驗證(在 C# 和 MVC 中,但這不太相關)。

所以我有一個.p7b文件來驗證,它可以讀入X509Certificate2Collection一個範例斷言 - 一個 base 64 編碼的 SAML 響應。

理想情況下,我想使用內置的WSSecurityTokenSerializer,但是失敗了,所以我正在尋找一種可行的方法。

我正在直接閱讀 XML:

// get the base 64 encoded SAML
string samlAssertionRaw = GetFromHttpRequest();

// load a new XML document
var assertion = new XmlDocument { PreserveWhitespace = true };
assertion.LoadXml(samlAssertionRaw);

// use a namespace manager to avoid the worst of xpaths
var ns = new XmlNamespaceManager(assertion.NameTable);
ns.AddNamespace("samlp", @"urn:oasis:names:tc:SAML:2.0:protocol");
ns.AddNamespace("saml", @"urn:oasis:names:tc:SAML:2.0:assertion");
ns.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);

// get the signature XML node
var signNode = assertion.SelectSingleNode(
   "/samlp:Response/saml:Assertion/ds:Signature", ns);

// load the XML signature
var signedXml = new SignedXml(assertion.DocumentElement);
signedXml.LoadXml(signNode as XmlElement);

// get the certificate, basically:
// signedXml.KeyInfo.OfType<KeyInfoX509Data>().First().
//     Certificates.OfType<X509Certificate2>().First()
// but with added checks
var certificate = GetFirstX509Certificate(signedXml);

// check the key and signature match
if (!signedXml.CheckSignature(certificate, true))
{
   throw new SecurityException("Signature check failed.");
}

// go on and read the SAML attributes from the XML doc

這很有效,但它所做的只是檢查X509Certificate2SAML 響應中的簽名和公鑰是否匹配。它不會以任何方式驗證它來自誰,我需要在接受 SAML 身份驗證之前這樣做。

似乎有兩種方法可以檢查在 SAML 響應中找到的證書 - 我可以這樣做,certificate.Verify()或者我可以使用簽名進行檢查signedXml.CheckSignature(certificate, false)

然而,兩者都返回假。

我認為這是因為他們正在根據機器商店或可能線上進行檢查(我不知道如何檢查)。我想對照X509Certificate2Collection從文件中檢索到的內容來檢查它們.p7b——機器上註冊的證書應該被忽略,只.p7b檢查證書。

似乎沒有任何方法可以將 傳遞X509Certificate2CollectionVerifyorCheckSignature方法。

這是對 SAML 響應進行的正確檢查嗎?

有什麼方法可以.p7b按照我想要的方式使用證書嗎?

您是否嘗試過在驗證過程中使用自定義X509Chain配置來搜尋證書。ExtraStore類似於以下內容:

// Placeholder for the certificate to validate
var targetCertificate = new X509Certificate2();
// Placeholder for the extra collection of certificates to be used
var certificates = new X509Certificate2Collection();

var chain = new X509Chain();

chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.ChainPolicy.ExtraStore.AddRange(certificates);

bool isValidCertificate = chain.Build(targetCertificate);

在範例中,吊銷檢查也被禁用,但如果您對 CRL 具有線上或離線訪問權限,則可以啟用它。


ExtraStore應該允許包含不在機器/使用者儲存中的中間證書。但是,受信任的根證書可能需要位於機器或使用者儲存中,具體取決於 中指定的證書,X509Chain否則您將UntrustedRoot失敗。如果在機器或使用者儲存中連根都不可用,您可以嘗試沿著生成的鏈向上走,並保證您遇到的唯一錯誤是由於不受信任的根,同時保證鏈根是您的期望基於X509Certificate2Collection您的驗證。

或者,您可以創建自己的自定義X509CertificateValidator來驗證證書,僅考慮提供的X509Certificate2Collection.

引用自:https://stackoverflow.com/questions/6126388