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