簡體   English   中英

驗證SAML斷言上的簽名

[英]Verify signature on SAML assertion

我有兩個簽名,一個是關於響應(通過驗證),一個是關於嵌套的SAML斷言(沒有)。 這是我正在使用的精簡代碼:

foreach (XmlElement node in xmlDoc.SelectNodes("//*[local-name()='Signature']"))
{// Verify this Signature block
    SignedXml signedXml = new SignedXml(node.ParentNode as XmlElement);
    signedXml.LoadXml(node);
    KeyInfoX509Data x509Data = signedXml.Signature.KeyInfo.OfType<KeyInfoX509Data>().First();

    // Verify certificate
    X509Certificate2 cert = x509Data.Certificates[0] as X509Certificate2;
    log.Info(string.Format("Cert s/n: {0}", cert.SerialNumber));
    VerifyX509Chain(cert);// Custom method

    // Check for approval
    X509Store store = new X509Store(StoreName.TrustedPublisher, StoreLocation.LocalMachine);
    store.Open(OpenFlags.ReadOnly);
    X509Certificate2Collection collection = store.Certificates.Find(X509FindType.FindBySerialNumber, cert.SerialNumber, true);
    Debug.Assert(collection.Count == 1);// Standing in for brevity

    // Verify signature
    signedXml.CheckSignature(cert, true);
}

為了完整起見,這里是XML的概述:

<samlp2:Response Destination="http://www.testhabaGoba.com" ID="ResponseId_934151edfe060ceec3067670c2f0f1ea" IssueInstant="2013-09-24T14:33:29.507Z" Version="2.0" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp2="urn:oasis:names:tc:SAML:2.0:protocol">
    ...
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        ...
    </ds:Signature>
    ...
    <saml2:Assertion ID="SamlAssertion-05fd8af7f2c9972e69cdbca612d3f3b8" IssueInstant="2013-09-24T14:33:29.496Z" Version="2.0" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
        ...
        <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            ...
        </ds:Signature>
        ...
    </saml2:Assertion>
</samlp2:Response>

我也嘗試過只簽署的斷言,但也失敗了。 我究竟做錯了什么? 為什么CheckSignature總是在SAML斷言上失敗?

編輯結果只有斷言的斷言是Java生成的(OpenSAML)並且有更多的環節可以跳過。 請指教。

此代碼使用Ultimate saml( http://www.componentpro.com/saml.net/ )驗證SAML響應。 它有助於驗證響應中嵌套的SAML斷言簽名。

XmlDocument xmlDocument = new XmlDocument(); 
xmlDocument.Load(samlResponseXmlToVerify); 

XmlDocument xmlDocumentMetadata = new XmlDocument(); 
xmlDocumentMetadata.Load(samlMetadataXmlToExtractCertData); 

// Load the SAML response from the XML document. 
Response samlResponse = new Response(xmlDocument.DocumentElement); 

// Is it signed?  
if (samlResponse.IsSigned()) 
{ 
    // Validate the SAML response with the certificate.  
    if (!samlResponse.Validate(xmlDocumentMetadata.DocumentElement)) 
    { 
        throw new ApplicationException("SAML response signature is not valid."); 
    } 
} 

有關更多詳細信息,請參閱此在線示例代碼: http//www.componentpro.com/doc/saml/ComponentPro.Saml.SignableSamlObject.Validate().htm

我不確定為什么,但看起來SignedXml只能驗證根文檔元素中的簽名。 我發現從現有的XmlElement片段創建新的XmlDocument的最快方法是使用ImportNode方法。

您更新的驗證代碼如下所示:

foreach (XmlElement item in xmlDoc.SelectNodes("//*[local-name()='Signature']"))
{
    var node = item;
    if (node.ParentNode != xmlDoc.DocumentElement)
    {
        var doc = new XmlDocument();
        var parentNode = doc.ImportNode(item.ParentNode, true);
        doc.AppendChild(parentNode);
        node = (XmlElement) parentNode.SelectSingleNode("*[local-name()='Signature']");
    }
    var signedXml = new SignedXml((XmlElement) node.ParentNode);
    signedXml.LoadXml(node);
    //TODO: validate
}

這大約是重新解析OuterXml速度的兩倍,正如其他人基於我使用8kB SAML響應文檔的測試所建議的那樣。

我發現這個答案引用了另一個答案 (由同一個人 )並總結如下: 實現是古怪的,Signature塊必須是DocumentElement的子代。 發現這篇文章也以更好的方式解決了這個問題。

修改代碼

foreach (XmlElement node in xmlDoc.SelectNodes("//*[local-name()='Signature']"))
{// Verify this Signature block
    // *** BEGIN: ADDED CODE ***
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(node.ParentNode.OuterXml);
    XmlElement signature = doc.SelectSingleNode("//*[local-name()='Signature']") as XmlElement;
    // This variable ^^^ is the same as node, just in doc instead of xmlDoc (important distinction)
    // *** END: ADDED CODE ***

    // Setup
    SignedXml signedXml = new SignedXml(node.ParentNode as XmlElement);
    signedXml.LoadXml(node);
    KeyInfoX509Data x509Data = signedXml.Signature.KeyInfo.OfType<KeyInfoX509Data>().First();

    // Verify certificate
    ...

不幸的是,這仍然不能解釋Java生成的SAML。 需要更復雜,更少記錄的東西來解釋這一點。 我收到了一個新的Java生成的SAML令牌,它與給定的代碼一起使用。 我使用的那個一定是有缺陷的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM