Java使用X509Certificate获取证书详情
场景
我们在进行加密相关项目的开发时会使用到各种证书,证书文件以.cer后缀结尾。双击打开后可以看到证书的详细信息,包括版本、序列号、签名算法、颁发者、使用者、有效期、公钥等信息。那么我们如何使用java程序获取相应的信息返回给前端展示呢?
证书的内容和意义如表所示:
证书内容 | 意义 |
Version | 告诉这个X.509证书是哪个版本的,目前有v1、V2、v3 |
Serial Number | 由证书分发机构设置证书的序列号 |
Signature Algorithm Identifier | 证书采用什么样的签名算法 |
Issuer Name | 证书发行者名,也就是给这个证书签名的机构名 |
Validity Period | 证书有效时间范围 |
Subject Name | 被证书发行机构签名后的公钥拥有者或实体的名字,采用X.500协议,在Internet上的标志是惟一的。例如:CN=Java,OU=Infosec,O=Infosec Lab,C=CN表示一个subject name。 |
最终效果
{
"code": 200,
"data": {
"effDate": "2023-07-03 17:44:47",
"serialNumber": "00a4cbbc64a19f000003",
"issuerDN": "CN=1111, C=CN",
"type": "EC",
"expDate": "2024-07-02 17:44:47",
"subjectDN": "CN=52000000121320000000_5200000012, O=123, O=00, L=123, L=123, C=CN",
"sigAlgName": "SM3的SM2签名"
},
"msg": "成功"
}
代码实现
/**
*
* @param fileName
* @return 证书详情
*/
public Object getCert(String fileName){
fileName =filePath+File.separator+fileName;
JSONObject jsonObject = new JSONObject();
CertificateFactory cf = null;
X509Certificate cert = null;
try {
cf = CertificateFactory.getInstance("X.509");
FileInputStream in = new FileInputStream(fileName);
cert = (X509Certificate) cf.generateCertificate(in);
} catch (CertificateException e) {
throw new RuntimeException(e);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
//签发者
String subjectDN = cert.getSubjectDN().toString();
//使用者
String issuerDN = cert.getIssuerDN().toString();
//序列号(十进制转十六进制,左补零)
String serialNumber = String.format("%" + 20 + "s", cert.getSerialNumber().toString(16)).replace(' ', '0');
//生效时间
Date effDate = cert.getNotBefore();
//过期时间
Date expDate = cert.getNotAfter();
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String effStr = null;
String expStr = null;
try {
effStr = sdf.format(effDate);
expStr = sdf.format(expDate);
} catch (Exception e) {
e.printStackTrace();
}
//秘钥类型
String type = cert.getPublicKey().getAlgorithm();
//签名哈希算法
String sigAlgName = cert.getSigAlgName();
jsonObject.put("subjectDN",subjectDN);
jsonObject.put("issuerDN",issuerDN);
jsonObject.put("serialNumber",serialNumber);
jsonObject.put("effDate",effStr);
jsonObject.put("expDate",expStr);
jsonObject.put("type",type);
jsonObject.put("sigAlgName", CertType.getNameByCode(sigAlgName));
return jsonObject;
}
/**
*
* 枚举类,实现数字证书对象标识Oid与名称的转换
*/
public enum CertType {
rsaEncryption("1.2.840.113549.1.1.1", "RSA"),
sha1withRSAEncryption("1.2.840.113549.1.1.5", "SHA1"),
ECC("1.2.840.10045.2.1", "ECC"),
SM2("1.2.156.10197.1.301", "SM2"),
SM3WithSM2("1.2.156.10197.1.501", "SM3的SM2签名"),
sha1withSM2("1.2.156.10197.1.502", "SHA1的SM2签名"),
sha256withSM2("1.2.156.10197.1.503", "SHA256的SM2签名"),
sm3withRSAEncryption("1.2.156.10197.1.504", "SM3的RSA签名"),
commonName("2.5.4.3", "主体名"),
emailAddress("1.2.840.113549.1.9.1", "邮箱"),
cRLDistributionPoints("2.5.29.31", "CRL分发点"),
extKeyUsage("2.5.29.37", "扩展密钥用法"),
subjectAltName("2.5.29.17", "使用者备用名称"),
CP("2.5.29.32", "证书策略"),
clientAuth("1.3.6.1.5.5.7.3.2", "客户端认证");
CertType(String code, String name) {
this.code = code;
this.name = name;
}
private String code;
private String name;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static String getNameByCode(String code){
CertType[] values = CertType.values();
for(CertType plateColorEnum:values){
if(code.equals(plateColorEnum.getCode())){
return plateColorEnum.getName();
}
}
return null;
}
public static String getCodeByName(String name){
CertType[] values = CertType.values();
for(CertType plateColorEnum:values){
if(name.equals(plateColorEnum.getName())){
return String.valueOf(plateColorEnum.getCode());
}
}
return null;
}
}
数字证书的对象标识符
数字证书的每项都有对象标识Oid,SM2数字证书的主要区别就是公钥算法、公钥参数、签名算法标识不一样,其余的都是X509里标准项。数字证书常见得对象标识有如下:
对象标识符 | 名称 | OID |
rsaEncryption | RSA算法标识 | 1.2.840.113549.1.1.1 |
sha1withRSAEncryption | SHA1的RSA签名 | 1.2.840.113549.1.1.5 |
ECC | ECC算法标识 | 1.2.840.10045.2.1 |
SM2 | SM2算法标识 | 1.2.156.10197.1.301 |
SM3WithSM2 | SM3的SM2签名 | 1.2.156.10197.1.501 |
sha1withSM2 | SHA1的SM2签名 | 1.2.156.10197.1.502 |
sha256withSM2 | SHA256的SM2签名 | 1.2.156.10197.1.503 |
sm3withRSAEncryption | SM3的RSA签名 | 1.2.156.10197.1.504 |
commonName | 主体名 | 2.5.4.3 |
emailAddress | 邮箱 | 1.2.840.113549.1.9.1 |
cRLDistributionPoints | CRL分发点 | 2.5.29.31 |
extKeyUsage | 扩展密钥用法 | 2.5.29.37 |
subjectAltName | 使用者备用名称 | 2.5.29.17 |
CP | 证书策略 | 2.5.29.32 |
clientAuth | 客户端认证 | 1.3.6.1.5.5.7.3.2 |