Как полностью проверить сертификат X509? - PullRequest
1 голос
/ 07 февраля 2020

Мне нужно проверить сертификат (X509Certificate2) так же, как он проверен перед использованием для связи.

X509Certificate2.Verify () в этом случае будет возвращать true, пока сертификат не выдан серверу, на котором он установлен.

Есть ли готовый блок кода для полной проверки сертификат X509?

С уважением

Редактировать: Это код, который я пробовал с:

var certificate = GetServerCertificate(CertificateStore,CertificateLocation,Thumbprint);

            if(certificate != null)
            {
                if(certificate.Verify())
                    _logger.Log(NLog.LogLevel.Info, $"Yes");
                else
                    _logger.Log(NLog.LogLevel.Info, $"No");
            }

1 Ответ

2 голосов
/ 07 февраля 2020

X509Certificate2.Verify () в этом случае будет возвращать true, пока сертификат не выдан серверу, на котором он установлен.

Метод Verify не проверяет что-нибудь о именах хостов. Он проверяет, что

  • Срок действия сертификата не истек.
  • Сертификат в конечном итоге связывается с доверенным root полномочием.
  • Все сертификаты в цепочке соответствующим образом вложены expiration.
  • Целевой сертификат, если он не выдан самостоятельно, имеет конечную точку отзыва и не отозван.
  • Любые промежуточные сертификаты имеют конечные точки отзыва и не отозваны.

Это точно равно

using (X509Chain chain = new X509Chain())
{
    // Use the default vales of chain.ChainPolicy including:
    //  RevocationMode = X509RevocationMode.Online
    //  RevocationFlag = X509RevocationFlag.ExcludeRoot
    //  VerificationFlags = X509VerificationFlags.NoFlag
    //  VerificationTime = DateTime.Now
    //  UrlRetrievalTimeout = new TimeSpan(0, 0, 0)

    bool verified = chain.Build(cert);

    for (int i = 0; i < chain.ChainElements.Count; i++)
    {
        chain.ChainElements[i].Certificate.Dispose();
    }

    return verified;
}

Есть ли готовый блок кода для полной проверки сертификата X509?

Если "полная проверка" просто означает все то, что делает Verify, тогда да. Если вы также заботитесь о том, чтобы он действовал в качестве сертификата клиента TLS (или сертификата сервера TLS), вы должны использовать более длинную форму (с использованием X509Chain напрямую) и добавить требование политики приложения перед вызовом chain.Build:

// See if it's valid as a TLS server
chain.ChainPolicy.ApplicationPolicy.Add(new Oid("1.3.6.1.5.5.7.3.1"));
// Alternatively, if it's valid as a TLS client
chain.ChainPolicy.ApplicationPolicy.Add(new Oid("1.3.6.1.5.5.7.3.2"));

Имя хоста намного сложнее. Клиентские сертификаты не имеют проверяемых имен, это зависит только от того, что сервер делает с ним. Сертификаты сервера имеют сопоставление имени хоста с SAN / Subject-CN, но нет ничего встроенного, что делает такую ​​проверку, кроме простого соединения с TLS (SslStream).

...