数字证书的有效性验证

最近在做数字证书有效性验证的接口,主要是从数字证书的有效期、颁发根证书和CRL进行验证,下面我就从这几个方面来说数字证书的有效性验证。

一、有效期

证书的有效期验证这个比较简单,就是使用时间在必须在证书起始和结束日期之间才有效,通过解析X.509对象很容易获取起止时间,判断证书有效期代码如下:

 
  
        /// /// 有效期验证 /// /// /// public static bool CheckDate( string cert) { byte [] bt = Convert.FromBase64String(cert); System.Security.Cryptography.X509Certificates.X509Certificate2 x509 = new System.Security.Cryptography.X509Certificates.X509Certificate2(bt); string date = x509.GetExpirationDateString(); DateTime dtex = Convert.ToDateTime(date); DateTime dtnow = DateTime.Now; DateTime dteff = Convert.ToDateTime(x509.GetEffectiveDateString()); if (dteff < dtnow && dtnow < dtex) { return true ; } return false ; }

二、颁发根证书

每个数字证书都有颁发根证书的签名,验证证书就是用根证书公钥来验证证书颁发者签名。首先,必须要找到数字证书的颁发根证书,Windows本身集成一些权威的受信任的根证书颁发机构,如VeriSign等,如果不在受信任的证书列表,我们打开证书会显示“Windows 没有足够信息,不能验证该证书”,当然我们可以把根证书加到受信任的根证书列表,这样证书就可以显示正常。

一般带证书链的数字证书中会包含证书颁发机构颁发者,逐级验证到最顶级根证书,每一级都用上级颁发根证书验证证书签名,直到证书颁发者和使用者一样自己可以验证自己通过。根证书的基本约束会不一样,Subject Type=CA代表可以签发证书,而一般的用户证书为Subject Type=End Entity,为终端实体不能再签发证书。

三、CRL验证

CRL是经CA签名的证书作废列表,用于做证书冻结和撤销时对证书有效性状态控制。一般数字证书中都有 CRL分发点地址,提供了HTTP和LDAP方式访问。通过BouncyCastle库解析X509证书的扩展项我们可以获取到CRL地址,然后使用相应方式下载CRL进行验证。

 
  
获取数字证书CRL
1 /**/ /// 2/// 获取X.509证书中的CRL地址 3/// 4/// 5/// 6/// CRL路径(先返回http格式路径,然后再是ldap) 7///   8 public static string GetCrlPath( string cert) 9 ... { 10string crl = string.Empty; 11 12 Org.BouncyCastle.X509.X509Certificate certificate = new Org.BouncyCastle.X509.X509CertificateParser().ReadCertificate(Convert.FromBase64String(cert)); 13 14 Org.BouncyCastle.Asn1.Asn1OctetString crlValues = certificate.GetExtensionValue(Org.BouncyCastle.Asn1.X509.X509Extensions.CrlDistributionPoints); 15 16if (crlValues == null) return crl; 17 18string ldapCRL = string.Empty; 19byte[] crlData = crlValues.GetOctets(); 20 21 Org.BouncyCastle.Asn1.Asn1InputStream ais = new Org.BouncyCastle.Asn1.Asn1InputStream(crlValues.GetOctets()); 22 Org.BouncyCastle.Asn1.Asn1Sequence seq = (Org.BouncyCastle.Asn1.Asn1Sequence)ais.ReadObject(); 23 24int dpCount = seq.Count; 25for (int i = 0; i < dpCount; i++) 26...{ 27 Org.BouncyCastle.Asn1.Asn1Sequence point1 = (Org.BouncyCastle.Asn1.Asn1Sequence)seq.GetObjectAt(i); 28 Org.BouncyCastle.Asn1.Asn1Encodable tobj = point1.GetObjectAt(0); 29while (tobj.GetType().IsSubclassOf(typeof(Org.BouncyCastle.Asn1.Asn1TaggedObject)) && !((Org.BouncyCastle.Asn1.DerTaggedObject)tobj).IsEmpty()) 30...{ 31if (tobj.GetType().IsSubclassOf(typeof(Org.BouncyCastle.Asn1.Asn1TaggedObject))) 32 tobj = ((Org.BouncyCastle.Asn1.Asn1TaggedObject)tobj).GetObject(); 33 } 34 35if (tobj is Org.BouncyCastle.Asn1.DerSequence) 36...{ 37// 跳过非URL的CRL地址 38 continue; 39 } 40 41// 取最后一个CRL地址 42 string tmpCrl = Encoding.ASCII.GetString(((Org.BouncyCastle.Asn1.DerOctetString)tobj).GetOctets()); 43 44if (tmpCrl.StartsWith("http", StringComparison.CurrentCultureIgnoreCase)) 45 crl = tmpCrl; 46else if (tmpCrl.StartsWith("ldap", StringComparison.CurrentCultureIgnoreCase)) 47 ldapCRL = tmpCrl; 48 49 } 50 51return string.IsNullOrEmpty(crl) ? ldapCRL : crl; 52 } 53 54 /**/ /// 55/// 即时获取CRL数据 56/// 57/// 58/// 59 public static byte [] GetCRLData( string crl) 60 ... { 61byte[] crlData = null; 62 63if (crl.StartsWith("http", StringComparison.CurrentCultureIgnoreCase)) 64...{ 65try 66...{ 67 System.Net.WebClient webClient = new System.Net.WebClient(); 68 crlData = webClient.DownloadData(crl); 69 70 } 71catch (Exception ex) 72...{ 73throw ex; 74 } 75 } 76else if (crl.StartsWith("ldap", StringComparison.CurrentCultureIgnoreCase)) 77...{ 78 79try 80...{ 81string ldapPath = crl.Replace("ldap://", "").Replace("LDAP://", ""); 82string[] ldapItems = ldapPath.Split('/'); 83 84string ldapHost = "LDAP://" + ldapItems[0].Replace(":389",""); 85string ldapFilter = ldapItems[1].Split('?')[0]; 86 87 DirectoryEntry de = new DirectoryEntry(); 88 de.Path = ldapHost + "/" + ldapFilter; 89 de.AuthenticationType = AuthenticationTypes.Signing; 90 de.Username = ""; 91 de.Password = ""; 92 93 DirectorySearcher a = new DirectorySearcher(de); 94 95 crlData = (byte[])a.FindOne().Properties["certificateRevocationList;binary"][0]; 96 } 97catch (Exception ex) 98...{ 99throw ex; 100 } 101 } 102103if (crlData!= null && crlData.Length>0 && crlData[0] != 0x30) 104...{ 105// 非Der编码格式转换 106 crlData = Convert.FromBase64String(Encoding.ASCII.GetString(crlData)); 107 } 108109return crlData; 110111 }

在用LDAP方式下载CRL时,注意LDAP协议名称要大写,不然访问会出错。下载的CRL格式可能是BASE64编码的,需要判断转换成DER编码二进制格式。

CRL分全量CRL和增量CRL,另外还有分段CRL,即同个CA的证书分不同的CRL地址段,主要是为了分流服务器负载。CRL有生效日期和下次更新时间,一般是定时更新,所以CRL并不是即时状态的。因此还有OCSP在线证书状态协议,可以即时的查询证书状态。

最后,总结证书有效性验证流程设计,如下图。

数字证书的有效性验证_第1张图片

你可能感兴趣的:(数字证书的有效性验证)