2012-01-30 273 views
0

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

回答

-1

当你说撤销时,你的意思是无效吗?如果它被撤销,我不会期望它会在你的代码中得到请求,因为Web服务器将首先采取行动。

如果使用x509certificate2,这是从X509证书导出,那么你有更多的属性,您可以检查;下面的链接中有很多例子。

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

+0

是的,我认为X509Certificate2,证书不是来自web请求,它来自证书文件。 – buda 2012-01-31 09:46:35

2

撤销状态由(a)获得CRL列表,并且如果证书被列在那里检查,和(b)发送一个OCSP请求到服务器以检查相同的检查。

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

+0

你确定.NET不执行恢复检查吗? - 当一个解决方案无法在测试环境中从测试证书服务器访问CRL时,我遇到了一些问题,但在很多年前,我不能保证它不是注入解决方案的安全组件。 – faester 2012-01-31 06:13:58

+0

对不起:看来IIS正在检查证书恢复,这可能是我记得的。 – faester 2012-01-31 06:15:11

+0

@faester CrtypoAPI内部执行CRL和OCSP检查,但它们不易于从.NET使用和控制。 – 2012-01-31 06:47:08

1

使用从x509.h文件使用OpenSSL这个API 1.0 /或以上版本

X509_CRL_get0_by_cert(X509_CRL * CRL,X509_REVOKED ** RET,X509 * X);

X在你想检查的证书中;
Ret是撤销结构的地址,其中撤销的原因和所有存储的
crl是CRL。

1

对于未来的读者。如前所述,.NET目前不公开类,X.509证书撤销列表以及OCSP消息传递都不公开。当然,您可以编写自己的代码或使用第三方库。

你可以试试我自己的CryptoAPI托管扩展从PowerShell PKI模块项目(PKI.Core.dll库)。支持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; 
    } 
} 
+0

中所述您使用X509CRL2的方法像冠军一样工作。谢谢!! – JonK 2015-01-22 16:40:48

0

的CRL被存储为在X509Certificate对象的扩展属性的OID。 OID友好名称和值是“CRL分发点”和“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]; 
    } 
}