Certificate 超详细解析cer证书(序列号,颁发者,公钥等)

news/2024/10/19 6:18:47/

我们一般说的证书就是数字证书:数字证书是指在互联网通讯中标志通讯各方身份信息的一个数字认证,人们可以在网上用它来识别对方的身份

一般有两种:PFX证书、CER证书

PFX证书:
由Public Key Cryptography Standards #12,PKCS#12标准定义,包含了公钥和私钥的二进制格式的证书形式,以pfx作为证书文件后缀名。

一般RSA证书比较多,现在国内的RSA根证到期,有些企业已经不用了。

SM2证书:
1.二进制编码的证书
证书中没有私钥,DER 编码二进制格式的证书文件,以cer作为证书文件后缀名。
2.Base64编码的证书
证书中没有私钥,BASE64 编码格式的证书文件,也是以cer作为证书文件后缀名。

一般简称SM2证书也为cer证书

下面就着重讲一下SM2证书
申请流程:
一般个人/企业在设备上生成csr文件,包含身份信息一起提交给CA,CA会给你制作一本证书,这证书具有一定的法律效应的哦。

证书信息
一般CA返回的是证书base64编码形式,直接把保存到记事本以.cer结尾,双击就可以看到证书的相关信息

下面是证书的示例:
在这里插入图片描述
在这里插入图片描述
是不是可以看到证书的相关信息。

我们可以用证书来进行签名验签,加解密等操作;我们还会提取证书的相关信息。

下面重点来了,我们讲一下怎么获取到证书的相关信息,这才是本文的重中之重

解析证书我们离不开一个依赖包,就是bc包,这个bc包很重要

		<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.64</version></dependency>

这个bc包里面的一些方法,如:Certificate 就是专门用来为证书服务的,在证书行业以及工程中必不可少

步骤

  1. 将证书base64编码转换为byte类型
byte[] buffer = Base64.decodeBase64(certBase64);

2.将byte转换为普通stream型

ByteArrayInputStream bIn = new ByteArrayInputStream(buffer);

3.将普通stream转为证书服务所需特定的stream型

ASN1InputStream dIn = new ASN1InputStream(bIn);
ASN1Sequence asq = (ASN1Sequence) dIn.readObject();

4.转证书

 Certificate certificate = Certificate.getInstance(asq);

5.解析证书内容

//            系列号解析String serialNo = certificate.getSerialNumber().getValue().toString(16);System.out.println("序列号:" + serialNo);

解析签名算法,一般证书实际的签名算法是字符串,但是解析出来的是特定形式,这个特定形式国际上就是用来代表某种算法,所以要特别注意下

// 签名算法 1.2.156.10197.1.501 表示SM2算法String algorithm = certificate.getSignatureAlgorithm().getAlgorithm().toString();System.out.println("算法:" + algorithm);
 // 颁发者String issuer = certificate.getIssuer().toString();System.out.println("颁发者:" + issuer);

解析出来的时间是date类型的,如果你不想要date类型而是获取string类型,一定要注意:你获取到的是GMT格式的字符串,这个字符串和实际的背景时间相差8小时,所以还是老老实实按照的方法获取date再进行格式转换

DateUtils.getDateString是我自己写的时间转换工具类。下一篇中我再贴出来。

Date startTime = certificate.getStartDate().getDate();String startTimeStr = DateUtils.getDateString(startTime, "yyyy-MM-dd HH:mm:ss");System.out.println("有效期:" + startTimeStr);
Date endTime = certificate.getEndDate().getDate();String endTimeStr = DateUtils.getDateString(endTime, "yyyy-MM-dd HH:mm:ss");System.out.println("失效日:" + endTimeStr);

这是获取使用者中CN项,如果你不想要CN而是想要获取整个使用者,可以直接到certificate.getSubject()为止

org.bouncycastle.asn1.x500.RDN rdn = certificate.getSubject().getRDNs(BCStyle.CN)[0];String cn = rdn.getFirst().getValue().toString();System.out.println("CN:" + cn);

这是解析公钥,一般比较重要,每家CA的公钥格式可能不一样,所以获取到的结果有细微差别,就是前缀是否带有:04标识

DERBitString publicKeyData = certificate.getSubjectPublicKeyInfo().getPublicKeyData();String publicKeyDataStr = publicKeyData.toString().replaceAll("#034200", "");System.out.println("公钥:" + publicKeyDataStr);

附加解析:现在主流的CA都会有家扩展项,就是oid,我们有时候也需要解析下oid的值,oid的解析一般用循环解析方式。

			Extensions exes=  certificate.getTBSCertificate().getExtensions();ASN1ObjectIdentifier[] list = exes.getExtensionOIDs();for (ASN1ObjectIdentifier a:list) {Extension el = exes.getExtension(a);String oid = el.getExtnId().toString();String value = new String(el.getExtnValue().getOctets());System.out.println("oid:" + oid + "->" + "value:" + value);}

特别说明:扩展项中我们这是解析出所有扩展项,有些扩展项的value是乱码,目前还不知道每家CA这些扩展项到底是啥编码格式。我试过了主流的编码格式,都不行,都是乱码,只有纯字符串的才正常。

来看下实际效果:
在这里插入图片描述

由于证书是比较重要的东西,一般不随便泄露,所以重要信息已经打码,悉知。

一般用到的扩展项有两种:个人扩展项,企业扩展项,这两种都有国际标准
个人身份标识码 IdentifyCode
oid固定为:1.2.156.10260.4.1.1
企业组织机构代码
oid固定为:1.2.156. 10260.4.1.4

这是亲手实践出来的, 目前在各网站还未知道详细的解析方式。尊重原创,谢谢!!

最后附上全部源码

package jp.utils;import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.Extensions;import java.io.ByteArrayInputStream;
import java.util.Date;public class DecodeCertUtils {public static void main(String[] args) {String certBase64 = "";try {byte[] buffer = Base64.decodeBase64(certBase64);ByteArrayInputStream bIn = new ByteArrayInputStream(buffer);ASN1InputStream dIn = new ASN1InputStream(bIn);ASN1Sequence asq = (ASN1Sequence) dIn.readObject();Certificate certificate = Certificate.getInstance(asq);Extensions exes=  certificate.getTBSCertificate().getExtensions();ASN1ObjectIdentifier[] list = exes.getExtensionOIDs();for (ASN1ObjectIdentifier a:list) {Extension el = exes.getExtension(a);String oid = el.getExtnId().toString();String value = new String(el.getExtnValue().getOctets());System.out.println("oid:" + oid + "->" + "value:" + value);}//            系列号解析String serialNo = certificate.getSerialNumber().getValue().toString(16);System.out.println("序列号:" + serialNo);// 签名算法 1.2.156.10197.1.501 表示SM2算法String algorithm = certificate.getSignatureAlgorithm().getAlgorithm().toString();System.out.println("算法:" + algorithm);// 颁发者String issuer = certificate.getIssuer().toString();System.out.println("颁发者:" + issuer);Date startTime = certificate.getStartDate().getDate();String startTimeStr = DateUtils.getDateString(startTime, "yyyy-MM-dd HH:mm:ss");System.out.println("有效期:" + startTimeStr);Date endTime = certificate.getEndDate().getDate();String endTimeStr = DateUtils.getDateString(endTime, "yyyy-MM-dd HH:mm:ss");System.out.println("失效日:" + endTimeStr);org.bouncycastle.asn1.x500.RDN rdn = certificate.getSubject().getRDNs(BCStyle.CN)[0];String cn = rdn.getFirst().getValue().toString();System.out.println("CN:" + cn);DERBitString publicKeyData = certificate.getSubjectPublicKeyInfo().getPublicKeyData();String publicKeyDataStr = publicKeyData.toString().replaceAll("#034200", "");System.out.println("公钥:" + publicKeyDataStr);bIn.close();dIn.close();} catch (Exception e) {e.printStackTrace();}}
}

http://www.ppmy.cn/news/187284.html

相关文章

近3万个斗图头像图片大全ACCESS\EXCEL

再发一个头像图片的数据图片包&#xff0c;和《4万多论坛头像个性头像ACCESS数据库》不同的是&#xff0c;这个数据表有一条记录只包含一张图片的&#xff0c;也有一条记录包含多张图片的&#xff0c;具体看截图&#xff0c;截图包含所有字段&#xff1a; 二级目录汇总统计&…

Linux命令详解(14)useradd命令

useradd用于添加一个linux账户。adduser跟本命令等价。 useradd同样属于不复杂但很重要的命令。 --help获得帮助信息。 -b选项&#xff0c;制定家目录的根 -c选项&#xff0c;给新用户添加说明信息 -d选项&#xff0c;给新用户设置家目录 -D选项&#xff0c;新用户使用默认…

PostgresSQL - 生成uuid

一、创建函数 uuid-ossp CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; uuid-ossp模块提供使用多种标准算法之一生成普遍唯一标识符 &#xff08;UUID&#xff09; 的功能。也有功能来产生某些特殊的UUID常数。 此模块依赖于 OSSP UUID 库&#xff0c;该库可在 http:…

创想ender3-V2切片软件参考设置,来优化DIY的3d打印机

创想ender3作为这几年的热门明星打印机&#xff0c;近来终于入手了&#xff0c;可以用他们切片软件的参数设置&#xff0c;优化自己diy的打印机。 1.Start G-code预备打印前划线先挤出材料&#xff0c;ender3打印前先在一边画200mm的线&#xff0c;让挤出机充分挤出线材 它的…

delphi fmx android 屏幕分辨率

android下,和windows系统获取分辨率,有一定的区别 比如我手机是2460x1080像素 但我在android下用screen.width,screen.height得到的是692*300 多 刚开始没在意,因为开发的app一切正常 后来到客户电视上,客户看到自己电视 是900多x500多,说分辨率有问题 于是我开始找an…

Java 生成X.509 V3证书

使用Java语言生成X.509 V3证书 1. X.509 V3证书 X.509 是公钥证书的格式标准, 广泛用于 TLS/SSL 安全通信或者其他需要认证的环境中。 X.509 证书可以由 CA&#xff08;Certificate Authority&#xff0c;数字证书认证机构&#xff09;颁发&#xff0c;也可以自签名产生。 X…

Exchange 2016 批量添加X500地址,解决迁移后退信的问题

最近公司跨域迁移 Exchange2010 到 Exchange2016。由于邮箱数据是pst导入导出的&#xff0c;在回复以前的邮件时&#xff0c;会收到未送达的退信。 虽然可以重新输入地址解决&#xff0c;但同学用起来很不方便。后来经过查询&#xff0c;在新邮箱系统添加原邮箱系统的X500地址即…

java正则替换括号的逗号

1.java正则替换括号的逗号&#xff0c;逗号前后是数字&#xff0c;举例 可以使用正则表达式来匹配括号中的逗号&#xff0c;然后使用Java的replaceAll()函数进行替换。示例如下&#xff1a; String str "示例文本(1, 2, 3), 示例文本(4,5)"; String regex "…