Как я могу программно получить отзыв X509Certificate? Я могу получить информацию, если сертификат отозван, но мне нужно узнать, когда он отозван, я думаю, что в списке CRL есть эта информация, но может ли кто-нибудь сказать мне, как ее прочитать.
Отзыв сертификата X509
Ответы (8)
Статус отзыва проверяется путем (а) получения списков CRL и проверки наличия в них сертификата и (б) отправки запроса OCSP на сервер для его проверки.
.NET не позволяет вам сделать это. CryptoAPI может иметь некоторые средства для этих операций, но проще всего использовать стороннюю библиотеку для .NET. BouncyCastle утверждает, что имеет некоторую поддержку OCSP и CRL, а наш SecureBlackbox обеспечивает полную поддержку (доступны как клиентские, так и серверные компоненты) для OCSP и CRL, а также мы предоставляем компонент, который выполняет полную проверку сертификата (со всеми проверками CRL и OCSP и Связь HTTP и LDAP при необходимости) с одним вызовом метода.
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];
}
}
используйте этот API из файла x509.h используйте openssl 1.0 / или более позднюю версию
X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x);
X в сертификате, который вы хотите проверить;
Ret — это адрес структуры отзыва, где причина отзыва и все хранящиеся
crl — это CRL.
Для будущих читателей.
Как уже было сказано, .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;
}
}
У меня нет репутации, чтобы проголосовать за ответ @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)"
Это может помочь вам:
С уважением.
Первый шаг — извлечь точки распространения 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);
Когда вы говорите отозвано, вы имеете в виду недействительное? Если его отозвать, я бы не ожидал, что он получит запрос в вашем коде, поскольку веб-сервер сначала будет мешать.
Если вы используете x509certificate2, производный от x509certificate, то у вас есть намного больше свойств, которые вы можете проверить; по ссылке ниже есть несколько примеров.