C # - проверка сертификата клиента, подписанного соответствующим корнем - PullRequest
0 голосов
/ 19 октября 2018

Я знаю, что есть много вопросов по этому аргументу, но я застрял в этом в течение нескольких дней, так что я здесь.У меня есть корневой сертификат и сертификат клиента.Мне нужно реплицировать в проекте веб-API C # то, что делает команда openssl verify -CAfile ca.pem client.pem.

Это то, что я знаю сейчас (надеюсь, что это действительно так):

  • Verify()Метод на самом деле проверить, что сертификат подписан органом.Это как контроль формата.Не имеет значения, какой орган подписал сертификат.
  • X509 Chain - это путь.Добавьте свой сертификат CA в дополнительный магазин, потому что я не собираюсь устанавливать сертификат в Windows.Затем построить, передав сертификат клиента.Давайте волшебство случится!К сожалению, у меня есть некоторые проблемы с конфигурацией.

Позвольте мне быть более ясным с примером

private bool VerifyCertificate(X509Certificate2 client)
{
    X509Chain chain = new X509Chain();
    var stringCert = WebConfigurationManager.AppSettings["CACertificate"];
    var byteCert = Encoding.ASCII.GetBytes(stringCert);
    var authority = new X509Certificate2(byteCert);

    chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
    chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreWrongUsage;

    chain.ChainPolicy.ExtraStore.Add(authority);

    // Do the preliminary validation.
    if (!chain.Build(client))
        return false;

    return true;
}

С этим примером программа возвращает false.Сборка не пройдена.Я уверен, что проблема с ChainPolicy properties, поэтому я попробовал другую конфигурацию

chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
chain.ChainPolicy.VerificationTime = DateTime.Now;
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 0);

Но этот не будет проверять что-нибудь , фактически используя мой сертификатметод возвращает true и, используя другой сертификат CA (который я не использовал для подписи своего клиентского сертификата), метод также возвращает true.

Я искал оболочку OpenSSL для C # и нашел ее, ноК сожалению, он основан на старых библиотеках, и репозиторий больше не обслуживается.Кроме того, я бы достиг своей цели, используя только .net framework, если это возможно.

Так что, ребята, быстрое резюме.Я хочу проверить, что только сертификат, подтвержденный моим сертификатом ca, может пройти проверку, все остальные должны быть остановлены.

Заранее благодарен за любую помощь

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Найдите проблему.В моем случае это был правильный ответ.

 private bool VerifyCertificate(X509Certificate2 client)
    {
        X509Chain chain = new X509Chain();
        var stringCert = WebConfigurationManager.AppSettings["CACertificate"];
        var byteCert = Encoding.ASCII.GetBytes(stringCert);
        var authority = new X509Certificate2(byteCert);

        chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
        chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;

        chain.ChainPolicy.ExtraStore.Add(authority);

        // Do the preliminary validation.
        if (!chain.Build(client))
            return false;

        // This piece makes sure it actually matches your known root
        var valid = chain.ChainElements
            .Cast<X509ChainElement>()
            .Any(x => x.Certificate.Thumbprint == authority.Thumbprint);

        if (!valid)
            return false;

        return true;
    }

Теперь при отладке приложения у меня есть несколько соображений:

  1. Что должен делать метод .Build ()?

Я имею в виду, используя сертификат, подписанный СА, или самозаверяющий сертификат, метод всегда возвращает true НО, если я использую доверенный, он добавит сертификат в chain.ChainElements в противном случае ничего не добавляется.

Мне нужно понять эту вещь, но весь тест, который я сделал, сказал, что метод работает

0 голосов
/ 19 октября 2018

ExtraStore не ограничивает, он предоставляет дополнительные сертификаты, чтобы помочь завершить цепочку.Он не предоставляет данные о доверии.

Чтобы определить, выдан ли сертификат центром сертификации, что вам нужно, вы должны сделать что-то вроде:

private static readonly X509Certificate2 s_trustedRoot = ObtainTheRoot();
private static readonly byte[] s_normalizedRoot = s_trustedRoot.RawData;

private bool VerifyCertificate(X509Certificate2 candidate)
{
    X509Chain chain = new X509Chain();
    // set all the things you need to set to make it build

    if (!chain.Build(candidate))
        return false;

    // Check that the root certificate was the expected one.
    X509ChainElementCollection elements = chain.ChainElements;
    return elements[elements.Count - 1].Certificate.RawData.SequenceEqual(s_normalizedRoot);
}

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

...