密码学研究-证书

简介:

引入:

在密码学中,证书是一个非常重要的概念,我这里不想展开了, 通常的证书都是基于X.509规范的,有兴趣的同学可以去看对应介绍:http://en.wikipedia.org/wiki/X509


实践:

其实证书无处不在,我们的浏览器里面一般都会可以看到一些证书,有些是自动添加进去的,有些可以手动添加进去,比如我自己机器上用Chrome:在chrome://settings/advanced里面

你往下看到HTTPS/SSL ,点击Manage Certificates...按钮: 就会看出被管理的证书列表:

161615114.png

161705736.png


我们选出其中某个证书,比如Alibaba.com,然后导出到本地,然后用java提供的Certificate类来分析这个证书。


为了分析证书,我们写了一个工具类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package  com.charles.certificatestudy;
import  java.io.FileInputStream;
import  java.math.BigInteger;
import  java.security.PublicKey;
import  java.security.cert.CRL;
import  java.security.cert.Certificate;
import  java.security.cert.CertificateFactory;
import  java.security.cert.X509Certificate;
import  java.util.Date;
import  javax.security.auth.x500.X500Principal;
import  sun.misc.BASE64Encoder;
/**
  *
  * Description: 这个工具类提供了证书的一般操作
  *
  * @author charles.wang
  * @created Oct 29, 2013 2:57:58 PM
  *
  */
public  class  CertificateUtil {
                                                 
     public  static  X509Certificate getX509certFromCertificatePath(String certificateName)  throws  Exception{
         CertificateFactory certificateFactory = CertificateFactory.getInstance( "X.509" );
         // 获得证书文件的输入流
         FileInputStream in =  new  FileInputStream(certificateName);
         // 获得证书
         Certificate certificate = certificateFactory.generateCertificate(in);
         // 获取证书的类型
         String certType = certificate.getType();
         System.out.println( "证书类型:"  + certType);
         X509Certificate x509cert = (X509Certificate) certificate;
                                                     
         // 关闭流
         in.close();
                                                     
         return  x509cert;
     }
                                                 
     /**
      * 分析证书文件
      * @param certficateName  被分析的证书路径名
      * @throws Exception
      */
     public  static  void  parseX509Certificate(X509Certificate x509cert)  throws  Exception {
                                                     
         // 开始用证书的API提取相关信息:
         // 读取证书版本号,这个证书的版本号识别用于该证书的X.509标准的版本,它可以用来影响证书所能指定的信息
         // 迄今为止,已经定义了3个版本
         int  version = x509cert.getVersion();
         System.out.println( "\n证书版本号为:"  + version);
         // 读取证书序列号
         BigInteger serialNumber = x509cert.getSerialNumber();
         System.out.println( "\n证书序列号为:"  + ( new  BASE64Encoder()).encode(serialNumber.toByteArray()));
         // 读取证书的签名算法名,CA用此算法来签名证书
         String algName = x509cert.getSigAlgName();
         System.out.println( "\n证书的签名算法名为:"  + algName);
         // 获得证书的签发者,其名字采用X.500标准,并且给出信息
         // 这个证书的签发者通常是一个CA,使用该证书意味着信任签写该证书的实体
         X500Principal issuerPrincipal = x509cert.getIssuerX500Principal();
         System.out.println( "\n证书的发布者为:"  + issuerPrincipal.getName());
         // 读取出证书的有效期
         Date notAfter = x509cert.getNotAfter();
         Date notBefore = x509cert.getNotBefore();
         System.out.println( "\n证书的有效期为:"  + notBefore.toLocaleString() +  " 之后,"  + notAfter.toLocaleString() +  " 之前" );
         // 读取证书的主体,它代表的是公钥的实体,其名字仍然使用X.500标准
         X500Principal subjectPrincipal = x509cert.getSubjectX500Principal();
         System.out.println( "证书主题为:"  + subjectPrincipal.getName());
         // 读取证书的公钥
         PublicKey publicKey = x509cert.getPublicKey();
         System.out.println( "\n获取证书的公钥信息" );
         System.out.println( "证书的公钥的算法为:"  + publicKey.getAlgorithm());
         System.out.println( "证书公钥的格式为:"  + publicKey.getFormat());
         // 获得公钥的字节数组
         byte [] publicKeyBytes = publicKey.getEncoded();
         System.out.println( "证书公钥为:"  + ( new  BASE64Encoder()).encode(publicKeyBytes));
         // 读取证书的基本约束
         System.out.println( "\n证书路径的长度为:"  + x509cert.getBasicConstraints());
         // 证书所含公钥所能完成的功能或者服务
         boolean [] keyUsages = x509cert.getKeyUsage();
         // KeyUsage ::= BIT STRING {
         // digitalSignature (0),
         // nonRepudiation (1),
         // keyEncipherment (2),
         // dataEncipherment (3),
         // keyAgreement (4),
         // keyCertSign (5),
         // cRLSign (6),
         // encipherOnly (7),
         // decipherOnly (8) }
         if  (keyUsages[ 0 ])
             System.out.println( "此证书的公钥可以用来数字签名" );
         if  (keyUsages[ 1 ])
             System.out.println( "此证书的公钥具有不可否认性" );
         if  (keyUsages[ 2 ])
             System.out.println( "此证书的公钥可以用于加密" );
         if  (keyUsages[ 3 ])
             System.out.println( "此证书的公钥用于将用户数据加密" );
         if  (keyUsages[ 4 ])
             System.out.println( "此证书的公钥用于密钥协议" );
         if  (keyUsages[ 5 ])
             System.out.println( "此证书的公钥用于验证在证书上的签名" );
         if  (keyUsages[ 6 ])
             System.out.println( "此证书的公钥用于验证有关撤销消息" );
         if  (keyUsages[ 7 ])
             System.out.println( "此证书的公钥只可以用于加密,并且履行密钥协议" );
         if  (keyUsages[ 8 ])
             System.out.println( "此证书的公钥只可以用于解密,并且履行密钥协议" );
         // 读取证书的签名算法的OID字符串
         String algOIDString = x509cert.getSigAlgOID();
         System.out.println( "\n证书的签名算法OID字符串为:"  + algOIDString);
         x509cert.getSigAlgParams();
         // 读取证书的签名值
         byte [] certSignature = x509cert.getSignature();
         System.out.println( "\n证书的签名值为:"  + ( new  BASE64Encoder()).encode(certSignature));
         x509cert.getSubjectAlternativeNames();
         // 读取证书的DER编码的二进制证书信息
         byte [] tbsCertificate = x509cert.getTBSCertificate();
         System.out.println( "\n证书的DER编码的二进制证书信息为:"  + ( new  BASE64Encoder()).encode(tbsCertificate));
                                                    
     }
                                                 
     /**
      * 获取证书的撤销列表
      * @param certificateName
      * @return
      * @throws Exception
      */
     public  static  CRL getCRLForCertifate(String certificateName)  throws  Exception {
                                                     
                                                  
         //实例化证书,并且指定证书的类型是X.509
         CertificateFactory certifateFactory = CertificateFactory.getInstance( "X.509" );
         //获取证书的输入流
         FileInputStream in =  new  FileInputStream(certificateName);
                                                     
         //获取证书的撤销列表
         CRL crl = certifateFactory.generateCRL(in);
                                                     
         in.close();
                                                     
         return  crl;
                                                
     }
                                                 
                                                
}



然后我们写一个测试类来测试这些方法,它会先读取证书文件,然后把其中的信息分离出来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package  com.charles.certificatestudy;
import  java.security.cert.X509Certificate;
import  sun.misc.BASE64Encoder;
/**
  *
  * Description: 这个类用于演示Certificate的一般使用
  *
  * @author charles.wang
  * @created Oct 29, 2013 12:03:51 PM
  *
  */
public  class  CertificateDemo {
     /**
      * @param args
      */
     public  static  void  main(String[] args)  throws  Exception {
                                         
         String certificateFilePath= "alibaba.cer" ;
         //获取证书对象
         X509Certificate x509cert=CertificateUtil.getX509certFromCertificatePath(certificateFilePath);
                                            
         //分析证书
         CertificateUtil.parseX509Certificate(x509cert);
                                            
     }
}



我们运行例子,测试,会打印出指定的证书信息:

162044199.png


我们比较选择的证书文件:

162108330.png


可以看到,这信息和我们用API读取出来的信息是完全一致的。





本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1316841,如需转载请自行联系原作者
目录
相关文章
|
7月前
|
算法 安全 关系型数据库
密码学系列之七:数字签名
密码学系列之七:数字签名
|
7月前
|
机器学习/深度学习 算法 安全
密码学系列之六:公钥密码体制
密码学系列之六:公钥密码体制
|
3月前
|
算法 安全 搜索推荐
深入理解密码学技术
深入理解密码学技术
41 1
|
算法 安全 数据安全/隐私保护
【密码学】 一篇文章讲透数字签名
数字签名(又称公钥数字签名)是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。它是一种类似写在纸上的普通的物理签名,但是在使用了公钥加密领域的技术来实现的,用于鉴别数字信息的方法。一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。数字签名是非对称密钥加密技术与数字摘要技术的应用。数字签名可以识别消息是否被篡改, 并验证消息的可靠性, 也可以防止否认。
728 0
【密码学】 一篇文章讲透数字签名
|
Rust 算法 JavaScript
【密码学】密码学相关资料整理
感觉我也写了不少的文章了,这里整理一下,之后这个整理会佛系更新,手动狗头,具体的链接查看原文获取吧,因为这个链接好像加不进去。
【密码学】密码学相关资料整理
|
算法 安全 区块链
一文读懂密码学中的证书
一文读懂密码学中的证书
一文读懂密码学中的证书
|
存储 算法 区块链
密码学系列之:加密货币中的scrypt算法
密码学系列之:加密货币中的scrypt算法