Halo

A magic place for coding

0%

X.509 数字证书读入程序设计与 Java 实现

X.509 证书结构描述

  X.509 是密码学中公钥证书的格式标准。在日常生活中,X.509 证书已应用在包括 TLS/SSL 在内的众多 Internet 协议里,同时它也用在很多非在线应用场景里。X.509 证书包含公钥、身份信息(网络主机名、组织或个体的名称等)和签名信息(可以是证书签发机构 CA 的签名,也可以是自签名)。对于一份经过可信的证书签发机构签名(如 CA)或者可以通过其他方式验证的证书,证书的拥有者就可以用证书及相应的私钥来创建安全的通信,对文档进行数字签名。

  • Certificate
    • Version Number
    • Serial Number
    • Signature Algorithm ID
    • Issuer Name
    • Validity period
      • Not Before
      • Not After
    • Subject name
    • Subject Public Key Info
      • Public Key Algorithm
      • Subject Public Key
    • Issuer Unique Identifier (optional)
    • Subject Unique Identifier (optional)
    • Extensions (optional)
    • Certificate Signature Algorithm
    • Certificate Signature

下面给出几个例子(使用 openssl 来查看证书内容):

  1. Github 网站的证书:

    github 证书 1

    github 证书 2

  2. Google 网站的证书:

    google 证书 1

    google 证书 2


数据结构

  1. CertificateFactory:用于指定证书标准类型,在后面用来生成该标准类型的证书。
  2. Certificate:证书的基类。
  3. X509Certificate:从 Certificate 中继承下来,里面包含了 X509 的许多特有属性,以及访问这些属性的方法。
  4. RSAPublicKey:RSA 加密的公钥。继承 PublicKey 父类,用于解密输出证书中的公钥算法以及公钥信息。

Java 实现

Handler.java:

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
import java.security.*;
import java.io.*;
import java.util.*;
import java.security.cert.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.math.BigInteger;
import java.util.Base64;
import java.security.interfaces.RSAPublicKey;

public class Handler {
public static void main(String [] args) {
// Prompt the user to input certificate name
System.out.print ("Please input the certificate: ");
Scanner input = new Scanner (System.in);
String certificatePath = input.next ();

Certificate c = null;
String s;
try {
CertificateFactory cf = CertificateFactory.getInstance ("X.509");
// Read Certification
FileInputStream in = new FileInputStream (certificatePath);
c = cf.generateCertificate (in);
in.close ();

s = c.toString ();

// Output as a txt file
FileOutputStream fout = new FileOutputStream ("tmp.txt");
BufferedWriter out = new BufferedWriter (new OutputStreamWriter (fout));
out.write (s, 0, s.length ());
out.close ();
}
catch (Exception ex) {
ex.printStackTrace ();
}

//convert certificate to X509
X509Certificate t = (X509Certificate) c;
// Print Info
System.out.println ("X.509 Certificate:");
System.out.println (" Data:");
System.out.println (" Version: " + t.getVersion ());
System.out.println (" Serial Number: ");
System.out.println (stringFormat ((t.getSerialNumber ().toString (16)), 16, 12));
System.out.println (" Signature Algorithm: " + t.getSigAlgName ());
System.out.println (" Issuer Name: " + t.getIssuerDN ());
System.out.println (" Validity");
System.out.println (" Not Before: " + t.getNotBefore ());
System.out.println (" Not After : " + t.getNotAfter ());
System.out.println (" Subject: " + t.getSubjectDN ());
// Public Key
RSAPublicKey publicKey = (RSAPublicKey) t.getPublicKey ();
System.out.println (" Subject Public Key Info: ");
System.out.println (" Public Key Algorithm: " + publicKey.getAlgorithm ());
System.out.println (" Public-Key: (" + (publicKey.getModulus ().toString (16)).length () * 4 + "bit)");
System.out.println (" Modulus:");
String st = (publicKey.getModulus ()).toString (16);
st = "00" + st;
System.out.println (stringFormat (st, 30, 20));
String exponent = (publicKey.getPublicExponent ().toString ());
String exponentHex = (publicKey.getPublicExponent ().toString (16));
System.out.println (" Exponent: " + exponent + " (0x" + exponentHex + ")");

System.out.println ();
// Signature
System.out.println (" Signature Algorithm: " + t.getSigAlgName ());
byte[] signature = t.getSignature ();
String sig = (new BigInteger (signature)).toString (16);
System.out.println (stringFormat (sig, 36, 8));

byte[] by = t.getExtensionValue ("2.5.29.32");
String str = new String (by);
System.out.println (str);
}

private static String stringFormat(String str, int format, int space) {
String spaceStr = "";
for (int i = 0; i < space; i++) {
spaceStr += " ";
}
String result = spaceStr;

for (int i = 0; i < str.length ()-1;) {
result += str.charAt (i);
i++;
result += str.charAt (i);
i++;
if (i == str.length ()) {
break;
}
else if (i != 0 && i % format == 0) {
result += ":\n";
result += spaceStr;
}
else if (i % 2 == 0) {
result += ":";
}
}
return result;
}
}

运行结果

  1. Github

    github 结果 1

    github 结果 2

  2. Google

    google 结果 1

    google 结果 2

  ** 分析 **:以上就是经过我编写的 Java 程序显示的证书内容。对比第一部分中的图片可以看出,证书的基本信息显示正确,公钥解密后的显示也是正确的。因为拓展部分比较麻烦,在这个程序中就没有实现了,但是基本原理是一样的。同时也使用文件流将证书内容直接输出成一个 txt 文件。


   以上就是对 X.509 证书的一些分享和读入程序的实现了,希望能够帮助到大家,最后谢谢您的支持!

Welcome to my other publishing channels