buda
buda

Reputation: 2372

Revoked X509Certificate

How can I programmatically get when X509Certificate is revoked? I can get information if certificate is revoked, but i need to get when is revoked, i think that CRL list have that info, but can someone tell me how to read that.

Upvotes: 1

Views: 8325

Answers (8)

Ben Lewis
Ben Lewis

Reputation: 11

I don't have the reputation to upvote @Hive's answer above but it was exactly what I needed, except for the language. I've posted my PowerShell port below:

$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)"

Upvotes: 1

Aaron Hudon
Aaron Hudon

Reputation: 5839

The first step is to extract the CRL distribution points from the certificate, and then match your certificate's serial number against the content of the CRL from the distribution point.

Here's an alternative way to extract the CRL distribution points with fewer magic numbers and bit twiddling. (tested in .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);    

Upvotes: 1

Hive
Hive

Reputation: 213

The CRL is stored as an OID in the extensions property of the X509Certificate object. The OID FriendlyName and Value are 'CRL Distribution Points' and '2.5.29.31'. Searching the certificate's extensions for an OID with value 2.5.29.31, you can then parse the raw data and get the distribution point(s).

I found the following code sample here. I tested it on both publicly sign certs and internal Microsoft CA certs; it returns the URL or LDAP connection string.

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];
    }
}

Upvotes: 3

Crypt32
Crypt32

Reputation: 13974

For future readers.

As already was said, .NET currently do not expose public classes nor for X.509 certificate revocation lists, nor for OCSP messaging. Of course, you can write your own code or to use 3rd party libraries.

You can try my own CryptoAPI managed extensions from PowerShell PKI module project (PKI.Core.dll library). There is a support for X509 CRL managed class (built on top of CryptoAPI native functions): X509CRL2 class. RevokedCertificates property stores an array of revoked certificates. In addition, library includes OCSP messaging classes (completely managed) stored in PKI.OCSP namespace. If your certificate contains OCSP links in the AIA extension, then you can easyly construct OCSP request from X509Certificate2 object by instantiating OCSPRequest object and invoking OCSPRequest.SendRequest method. Return object is an instance of OCSPResponse class.

Basically, the code woul look as this:

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 would mean that the certificate is not revoked.

with X509 CRL the code would look as this:

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;
    }
}

Upvotes: 1

Balamurugan
Balamurugan

Reputation: 2359

use this API from x509.h file use openssl 1.0 / or above version

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

X in the certificate u want to check ;
Ret is the Address of the revocation structure where reason for the revocation and all stored
crl is the CRL .

Upvotes: 1

Revocation status is checked by (a) obtaining CRL lists and checking if the certificate is listed there, and (b) sending an OCSP request to the server to check the same.

.NET doesn't let you do this. CryptoAPI might have some means for these operations, but the easiest is to use third-party library for .NET. BouncyCastle claims to have some support for OCSP and CRLs, and our SecureBlackbox provides complete support (both client and server components are available) for OCSP and CRL, and also we provide a component which performs complete certificate validation (with all CRL and OCSP checks and HTTP and LDAP communication when needed) with one method call.

Upvotes: 2

WestDiscGolf
WestDiscGolf

Reputation: 4108

When you say revoked, do you mean invalid? If its revoked I wouldn't expect it to arrive at the request in your code as the web server will have got in the way first.

If you use the x509certificate2, which is derived from x509certificate, then you have a lot more properties which you can check; there are a number of examples on the link below.

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

Upvotes: -1

Related Questions