2011-05-25 59 views
10

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

所以我有一個.p7b文件來驗證,並可以讀取到一個X509Certificate2Collection和一個示例斷言 - 一個基地64編碼的SAML響應。

理想情況下,我想使用內置的WSSecurityTokenSerializer,但that fails,所以我正在尋找一種可行的方式。

我讀取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 

也就是說很多作品,但所有它做的是檢查簽名和SAML響應匹配X509Certificate2公鑰。它不以任何方式驗證它來自哪裏,我需要在接受SAML身份驗證之前執行此操作。

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

然而,兩者都返回false。

我認爲這是因爲他們正在對機器商店或可能在線檢查(我不知道如何檢查)。我想檢查它們與從.p7b文件檢索到的X509Certificate2Collection,而不是 - 在機器上註冊的證書應該被忽略,並且只檢查.p7b證書。

似乎沒有辦法將X509Certificate2Collection傳遞給VerifyCheckSignature方法。

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

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

+0

GetFirstX509Certificate是做什麼的? – theycallmemorty 2011-05-25 20:41:36

+0

我在這裏問了一個類似的問題:http://security.stackexchange.com/questions/3905/verify-saml-response-is-from-a-trusted-source但最終結束在您的文章,因爲我有與CheckSignature相同的問題 – theycallmemorty 2011-05-25 20:43:46

+0

@theycallmemorty - 我嘗試在註釋中解釋,但它使用X509Certificate2'簽名'signedXml.KeyInfo [0] .Certificates [0],但使用檢查和強制轉換。 – Keith 2011-05-25 22:34:08

回答

5

您是否嘗試過使用自定義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

+0

是的,我試過了 - 'chain.Build'回來無效,因爲我的'X509Certificate2Collection'是無效的。然而,我並不想驗證集合,我很樂意將'.p7b'的內容視爲權威 - 我只想檢查SAML證書與.p7b集合。 – Keith 2011-05-31 12:36:51

+0

我認爲這個問題可能與'chain.ChainPolicy.ExtraStore.AddRange'有關 - 我不想添加到現有的機器或用戶存儲,我只需要用'.p7b'文件中的鍵來重新開始。 – Keith 2011-05-31 12:38:03

+0

執行構建後獲得的'ChainStatus'是什麼?我的理解是'ExtraStore'不會給機器或用戶商店增加任何東西,只是在驗證過程中包含指定的證書。 – 2011-05-31 12:48:36

相關問題