【问题标题】:Revoked X509Certificate吊销 X509 证书
【发布时间】:2012-02-22 14:43:51
【问题描述】:

当 X509Certificate 被撤销时,如何以编程方式获取?如果证书被吊销,我可以获取信息,但我需要获取何时被吊销,我认为 CRL 列表有该信息,但有人可以告诉我如何阅读。

【问题讨论】:

    标签: c# .net security pki x509certificate2


    【解决方案1】:

    我没有支持@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)"
    

    【讨论】:

      【解决方案2】:

      第一步是从证书中提取 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);    
      

      【讨论】:

        【解决方案3】:

        CRL 作为 OID 存储在 X509Certificate 对象的扩展属性中。 OID FriendlyName 和 Value 是“CRL Distribution Points”和“2.5.29.31”。在证书的扩展中搜索值为 2.5.29.31 的 OID,然后您可以解析原始数据并获取分发点。

        我找到了以下代码示例here。我在公开签名证书和内部 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];
            }
        }
        

        【讨论】:

        • 感谢您的支持 - 添加对此方法中使用的幻数的引用将是一个奖励。
        【解决方案4】:

        为未来的读者。

        如前所述,.NET 目前不公开公共类,也不针对 X.509 证书吊销列表,也不针对 OCSP 消息传递。当然,您可以编写自己的代码或使用 3rd 方库。

        您可以从PowerShell PKI 模块项目(PKI.Core.dll 库)尝试我自己的 CryptoAPI 托管扩展。支持 X509 CRL 托管类(建立在 CryptoAPI 本机函数之上):X509CRL2 class。 RevokedCertificates 属性存储一组已撤销的证书。此外,库包括存储在 PKI.OCSP 命名空间中的 OCSP 消息传递类(完全托管)。如果您的证书在 AIA 扩展中包含 OCSP 链接,那么您可以通过实例化 OCSPRequest 对象并调用 OCSPRequest.SendRequest 方法轻松地从 X509Certificate2 对象构造 OCSP 请求。返回对象是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;
            }
        }
        

        【讨论】:

        • 您使用 X509CRL2 的方法非常成功。谢谢!!
        【解决方案5】:

        使用 x509.h 文件中的此 API 使用 openssl 1.0 / 或更高版本

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

        您要检查的证书中的 X ;
        Ret 是撤销结构的地址,撤销原因和所有存储的位置
        crl 是 CRL。

        【讨论】:

          【解决方案6】:

          通过以下方式检查吊销状态:(a) 获取 CRL 列表并检查证书是否在此处列出,以及 (b) 向服务器发送 OCSP 请求以进行检查。

          .NET 不允许您这样做。 CryptoAPI 可能对这些操作有一些方法,但最简单的方法是使用 .NET 的第三方库。 BouncyCastle 声称对 OCSP 和 CRL 有一些支持,我们的 SecureBlackbox 为 OCSP 和 CRL 提供了完整的支持(客户端和服务器组件都可用),我们还提供了一个执行完整证书验证的组件(包括所有 CRL 和 OCSP 检查和HTTP 和 LDAP 通信(在需要时)使用一个方法调用。

          【讨论】:

          • 您确定 .NET 不执行吊销检查吗? -- 当解决方案无法从测试环境中的测试证书服务器访问 CRL 时,我遇到了问题,但这是多年前的事了,我不能保证它不是注入解决方案的安全组件.
          • 抱歉:似乎 IIS 正在检查证书吊销,这可能是我记得的。
          • @faester CrtypoAPI 在内部执行 CRL 和 OCSP 检查,但它们不容易从 .NET 中使用和控制。
          • 我可以检查吊销状态,但我想获得准确的吊销日期。该信息存在于 CRL 列表中,并且证书吊销检查 CRL,我想阅读 CRL 条目以获取一些信息、吊销日期、CRL 原因代码等。
          • @buda 我说的是这个
          【解决方案7】:

          当您说撤销时,您的意思是无效吗?如果它被撤销,我不希望它在你的代码中到达请求,因为网络服务器会首先阻碍。

          如果您使用从 x509certificate 派生的 x509certificate2,那么您可以检查更多属性;下面的链接中有许多示例。

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

          【讨论】:

          • 是的,我认为是 X509Certificate2,证书不是来自网络请求,而是来自证书文件。
          【解决方案8】:
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-07-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多