Отзыв сертификата X509

Как я могу программно получить отзыв X509Certificate? Я могу получить информацию, если сертификат отозван, но мне нужно узнать, когда он отозван, я думаю, что в списке CRL есть эта информация, но может ли кто-нибудь сказать мне, как ее прочитать.


person buda    schedule 30.01.2012    source источник


Ответы (8)


Статус отзыва проверяется путем (а) получения списков CRL и проверки наличия в них сертификата и (б) отправки запроса OCSP на сервер для его проверки.

.NET не позволяет вам сделать это. CryptoAPI может иметь некоторые средства для этих операций, но проще всего использовать стороннюю библиотеку для .NET. BouncyCastle утверждает, что имеет некоторую поддержку OCSP и CRL, а наш SecureBlackbox обеспечивает полную поддержку (доступны как клиентские, так и серверные компоненты) для OCSP и CRL, а также мы предоставляем компонент, который выполняет полную проверку сертификата (со всеми проверками CRL и OCSP и Связь HTTP и LDAP при необходимости) с одним вызовом метода.

person Eugene Mayevski 'Callback    schedule 31.01.2012
comment
Вы уверены, что .NET не выполняет проверки отзыва? -- Я сталкивался с проблемами, когда решение не могло получить доступ к CRL с тестового сервера сертификатов в тестовой среде, но это было много лет назад, и я не могу гарантировать, что это не компонент безопасности, внедренный в решение. . - person faester; 31.01.2012
comment
Извините: кажется, IIS проверяет отзыв сертификата, наверное, это то, что я помню. - person faester; 31.01.2012
comment
@faester CrtypoAPI выполняет внутренние проверки CRL и OCSP, но их нелегко использовать и контролировать из .NET. - person Eugene Mayevski 'Callback; 31.01.2012
comment
Я могу проверить статус отзыва, но я хочу получить точную дату отзыва. Эта информация существует в списке CRL, и CRL проверки отзыва сертификата, я хочу прочитать запись CRL, чтобы получить некоторую информацию, дату отзыва, код причины CRL и т. д. - person buda; 31.01.2012
comment
@buda Вот о чем я говорил - person Eugene Mayevski 'Callback; 31.01.2012
comment
@buda Да, но если вы заинтересованы, вы можете использовать наши каналы поддержки, как описано на eldos.com/sbb/support-tech.php - person Eugene Mayevski 'Callback; 31.01.2012

CRL хранится как OID в свойстве extensions объекта X509Certificate. OID FriendlyName и значение — «точки распространения CRL» и «2.5.29.31». Выполнив поиск OID со значением 2.5.29.31 в расширениях сертификата, вы можете затем проанализировать необработанные данные и получить точки распространения.

Я нашел следующий пример кода: здесь. Я протестировал его как на публично подписанных сертификатах, так и на внутренних сертификатах Microsoft CA; он возвращает URL-адрес или строку подключения LDAP.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace System.Security.Cryptography.X509Certificates
{
    public static class X509Certificate2Extensions
    {
        /// <summary>
        /// Returns an array of CRL distribution points for X509Certificate2 object.
        /// </summary>
        /// <param name="certificate">X509Certificate2 object.</param>
        /// <returns>Array of CRL distribution points.</returns>
        public static string[] GetCrlDistributionPoints(this X509Certificate2 certificate)
        {
            X509Extension ext = certificate.Extensions.Cast<X509Extension>().FirstOrDefault(
                e => e.Oid.Value == "2.5.29.31");

            if (ext == null || ext.RawData == null || ext.RawData.Length < 11)
                return EmptyStrings;

            int prev = -2;
            List<string> items = new List<string>();
            while (prev != -1 && ext.RawData.Length > prev + 1)
            {
                int next = IndexOf(ext.RawData, 0x86, prev == -2 ? 8 : prev + 1);
                if (next == -1)
                {
                    if (prev >= 0)
                    {
                        string item = Encoding.UTF8.GetString(ext.RawData, prev + 2, ext.RawData.Length - (prev + 2));
                        items.Add(item);
                    }

                    break;
                }

                if (prev >= 0 && next > prev)
                {
                    string item = Encoding.UTF8.GetString(ext.RawData, prev + 2, next - (prev + 2));
                    items.Add(item);
                }

                prev = next;
            }

            return items.ToArray();
        }

        static int IndexOf(byte[] instance, byte item, int start)
        {
            for (int i = start, l = instance.Length; i < l; i++)
                if (instance[i] == item)
                    return i;

            return -1;
        }

        static string[] EmptyStrings = new string[0];
    }
}
person Hive    schedule 30.11.2016
comment
Спасибо за это - добавление ссылок на магические числа, используемые в этом методе, было бы бонусом. - person Aaron Hudon; 06.09.2018

используйте этот API из файла x509.h используйте openssl 1.0 / или более позднюю версию

X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x);

X в сертификате, который вы хотите проверить;
Ret — это адрес структуры отзыва, где причина отзыва и все хранящиеся
crl — это CRL.

person Balamurugan    schedule 09.05.2012

Для будущих читателей.

Как уже было сказано, .NET в настоящее время не предоставляет открытые классы ни для списков отзыва сертификатов X.509, ни для обмена сообщениями OCSP. Конечно, вы можете написать свой собственный код или использовать сторонние библиотеки.

Вы можете попробовать мои собственные управляемые расширения CryptoAPI из проекта модуля PowerShell PKI (библиотека PKI.Core.dll). Существует поддержка управляемого класса X509 CRL (построенного поверх собственных функций CryptoAPI): класс X509CRL2 . Свойство RevokedCertificates хранит массив отозванных сертификатов. Кроме того, библиотека включает классы обмена сообщениями OCSP (полностью управляемые), хранящиеся в пространстве имен PKI.OCSP. Если ваш сертификат содержит ссылки OCSP в расширении AIA, вы можете легко создать запрос OCSP из объекта X509Certificate2, создав экземпляр объект OCSPRequest и вызов метода OCSPRequest.SendRequest. Возвращаемый объект — это экземпляр класса OCSPResponse.

В основном код будет выглядеть так:

using System;
using System.Security.Cryptography.X509Certificates;
using PKI.OCSP;

public class Class1 {
    public static DateTime? GetrevocationDate(X509Certificate2 cert) {
        OCSPRequest request = new OCSPRequest(cert);
        OCSPResponse response = request.SendRequest();
        if (response.Responses[0].CertStatus == CertificateStatus.Revoked) {
            return response.Responses[0].RevocationInfo.RevocationDate;
        }
        return null;
    }
}

NULL будет означать, что сертификат не отозван.

с X509 CRL код будет выглядеть так:

using System;
using System.Security.Cryptography.X509Certificates;

public class Class1 {
    // crlRawData could a type of System.String and pass the path to a CRL file there.
    public static DateTime? GetrevocationDate(X509Certificate2 cert, Byte[] crlRawData) {
        X509CRL2 crl = new X509CRL2(crlRawData);
        X509CRLEntry entry = crl.RevokedCertificates[cert.SerialNumber];
        if (entry != null) {
            return entry.RevocationDate;
        }
        return null;
    }
}
person Crypt32    schedule 27.10.2014
comment
Ваш метод с использованием X509CRL2 работал как чемпион. Спасибо!! - person JonK; 22.01.2015

У меня нет репутации, чтобы проголосовать за ответ @Hive выше, но это было именно то, что мне было нужно, за исключением языка. Я разместил свой порт PowerShell ниже:

$cert = (Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.Subject -match "SUBJECT NAME*"})

function IndexOfByte([byte[]]$instance, [byte]$item, [int]$start)
{
    $len = $instance.Length
    for ($i = $start; $i -lt $len; $i++) {
        if ($instance[$i] -eq $item) { return $i }
    }

    return -1;
}

$crls = $cert.Extensions | ? { $_.Oid.FriendlyName -eq "CRL Distribution Points" }

$prev = -2;
[System.Collections.ArrayList]$items = @();

while ($prev -ne -1 -and $crls.RawData.Length -gt $prev + 1)
{
    if($prev -eq -2) { $y = 8 } else {$y = $prev + 1}
    $next = IndexOfByte -instance $crls.RawData -item 0x86 -start $y
    if ($next -eq -1) {
        if ($prev -ge 0) {
            $item = [system.Text.Encoding]::UTF8.GetString($crls.RawData, $prev + 2, $crls.RawData.Length - ($prev + 2));
            $items.Add($item);
        }
        break;
    }

    if ($prev -ge 0 -and $next -gt $prev) {
        $item = [system.Text.Encoding]::UTF8.GetString($crls.RawData, $prev + 2, $next - ($prev + 2));
        $items.Add($item);
    }
    $prev = $next;
}

Write-Host "Certificate CRLs: `n$($items | out-string)"
person Ben Lewis    schedule 08.07.2021

Это может помочь вам:

http://blogs.msdn.com/b/alejacma/archive/2010/05/10/how-to-get-info-from-client-certificates-issued-by-ca-c.aspx

С уважением.

person Oscar Jara    schedule 30.01.2012

Первый шаг — извлечь точки распространения CRL из сертификата, а затем сопоставить серийный номер сертификата с содержимым CRL из точки распространения.

Вот альтернативный способ извлечения точек распространения CRL с меньшим количеством магических чисел и битовой перестановкой. (проверено в .NET Core 2.1)

var path = "<path to signed file>";
// get certificate
var cert = new X509Certificate2(path);
// extract the CRL distribution points information
var crlInfo = cert.Extensions["2.5.29.31"];
var crlDistribitionPoints = new AsnEncodedData(crlInfo.Oid, crlInfo.RawData).Format(false);
Console.Writeline(crlDistribitionPoints);    
person Aaron Hudon    schedule 06.09.2018

Когда вы говорите отозвано, вы имеете в виду недействительное? Если его отозвать, я бы не ожидал, что он получит запрос в вашем коде, поскольку веб-сервер сначала будет мешать.

Если вы используете x509certificate2, производный от x509certificate, то у вас есть намного больше свойств, которые вы можете проверить; по ссылке ниже есть несколько примеров.

http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.aspx

person WestDiscGolf    schedule 30.01.2012
comment
Да, я думал X509Certificate2, сертификат не из веб-запроса, а из файла сертификата. - person buda; 31.01.2012