SAML с SKI вместо сертификата в узле X509Data

Я уже внедрил механизм аутентификации на основе протокола SAML. В проекте используется библиотека SAML2. Все работало нормально, пока не произошли изменения на сервере. Раньше сервер отвечал узлом:

<ds:KeyInfo><ds:X509Data><ds:X509Certificate>Here was certificate</ds:X509Certificate></ds:X509Data></ds:KeyInfo>

Но он изменился на:

<ds:X509SKI>Here is Subject Key Identifier</ds:X509SKI>

В библиотеке SAML2 есть метод CheckSignature, который можно применить к ответу сервера:

/// <summary>
/// Checks the signature.
/// </summary>
/// <returns>True of the signature is valid, else false.</returns>
public bool CheckSignature()
{
    return XmlSignatureUtils.CheckSignature(Document);
}

Здесь указывает:

/// <summary>
/// Verifies the signature of the XmlDocument instance using the key enclosed with the signature.
/// </summary>
/// <param name="doc">The doc.</param>
/// <returns><code>true</code> if the document's signature can be verified. <code>false</code> if the signature could
/// not be verified.</returns>
/// <exception cref="InvalidOperationException">if the XmlDocument instance does not contain a signed XML document.</exception>
public static bool CheckSignature(XmlDocument doc)
{
    CheckDocument(doc);
    var signedXml = RetrieveSignature(doc);

    if (signedXml.SignatureMethod.Contains("rsa-sha256"))
    {
        // SHA256 keys must be obtained from message manually
        var trustedCertificates = GetCertificates(doc);
        foreach (var cert in trustedCertificates)
        {
            if (signedXml.CheckSignature(cert.PublicKey.Key))
            {
                return true;
            }
        }

        return false;
    }

    return signedXml.CheckSignature();
}

И, наконец, метод GetCertificates выглядит так:

/// <summary>
/// Gets the certificates.
/// </summary>
/// <param name="doc">The document.</param>
/// <returns>List of <see cref="X509Certificate2"/>.</returns>
private static List<X509Certificate2> GetCertificates(XmlDocument doc)
{
    var certificates = new List<X509Certificate2>();
    var x509CertificateNodeList = doc.GetElementsByTagName("ds:X509Certificate");
    if (x509CertificateNodeList.Count == 0)
    {
        x509CertificateNodeList = doc.GetElementsByTagName("X509Certificate");
    }

    foreach (XmlNode xn in x509CertificateNodeList)
    {
        try
        {
            var xc = new X509Certificate2(Convert.FromBase64String(xn.InnerText));
            certificates.Add(xc);
        }
        catch
        {
            // Swallow the certificate parse error
        }
    }

    return certificates;
}

Как видите, библиотека проверяет только сертификаты, а не идентификаторы ключей субъекта. Я считаю, что могу реализовать сравнение SKI между установленным сертификатом и предоставленным элементом самостоятельно, но я не уверен, что это законный способ сделать это.

Здесь Томас Порнин написал:

Идентификатор ключа субъекта не играет роли в проверке, по крайней мере, не в алгоритме, который составляет раздел 6 RFC 5280. Он предназначен для помощи в построении пути.

Его заявление предполагает, что я не могу выполнить проверку, сравнив SKI из ответа сервера и установленного сертификата.

RFC 5280 Предлагает то же самое, но у меня нет времени чтобы прочитать его внимательно, поэтому я ищу вашей помощи.

Является ли сравнение идентификатора ключа субъекта установленного сертификата X509 и идентификатора в ответе SAML правильным способом проверки ответа?


person Landeeyo    schedule 19.01.2016    source источник


Ответы (1)


Нет, как уже было сказано, SKI используется только для привязки сертификатов в цепочке (когда используется совпадение ключей). Он не предоставляет достаточно информации о сертификате и его деталях.

Однако, если у клиента предустановлен полный сертификат, клиент может использовать SKI для поиска нужного сертификата и использования сертификата для процедур проверки.

person Crypt32    schedule 19.01.2016