Revoked X509Certificate

孤人 提交于 2019-12-06 16:21:07

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.

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 .

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

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

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

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!