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

一般有两种: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();}}
}

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

  1. Android技能树 — 网络小结(6)之 OkHttp超超超超超超超详细解析

    前言: 本文也做了一次标题党,哈哈,其实写的还是很水,各位原谅我O(∩_∩)O. 介于自己的网络方面知识烂的一塌糊涂,所以准备写相关网络的文章,但是考虑全部写在一篇太长了,所以分开写,希望大家能仔细看 ...

  2. 单片机数字钟(调时,调时闪烁,万年历,年月日)超详细解析

    2019/07/13 单片机数字钟(调时,调时闪烁,万年历,年月日)超详细解析 发表日期:2019/07/13 单片机开发板:巫妖王2.0, 使用同款开发板可直接上板测试 文档说明: 实现功能 : 一 ...

  3. 计算机网络之交换机的工作原理---超详细解析,谁都看得懂!!

    在了解交换机的工作原理之前,我们先要了解几个概念. 一.相关概念  1.OSI七层模型是哪七层? 自上而下分别是: 应用层 表示层 会话层 传输层 网络层 数据链路层 物理层 交换机工作在数据链路层, ...

  4. 【智能算法】粒子群算法(Particle Swarm Optimization)超详细解析+入门代码实例讲解...

    喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 01 算法起源 粒子群优化算法(PSO)是一种进化计算技术(evolutionary computation),1995 年由E ...

  5. VUE 钩子函数超详细解析

    点击上方蓝色字体关注我吧 一起学习,一起进步,做积极的人! 前言 Vue 实例在被创建时,会经过一系列的初始化过程,初始化过程中会运行一些函数,叫做生命周期钩子函数,通过运用钩子函数,用户在可以在Vu ...

  6. 超详细解析python爬虫爬取京东图片

    超详细图片爬虫实战 实例讲解(京东商城手机图片爬取) 1.创建一个文件夹来存放你爬取的图片 2.第一部分代码分析 3.第二部分代码分析 完整的代码如下所示: 升级版代码: 爬取过程中首先你需要观察在手 ...

  7. 两万字深度讲解系统设计!超详细解析!面试复习必备!

    Table of Contents generated with DocToc 三高 高并发 高性能 高可用 网站统计IP PV UV实现原理 如何进行系统拆分? 场景题:设计判断论文抄袭的系统 设计 ...

  8. flag push tcp 作用_TCP协议超详细解析及攻击/防范

    TCP 协议作用 TCP 协议使用的是面向连接的方法进行通信的,其作用如下: 面向流的处理:TCP 以流的方式处理数据.换句话说,TCP 可以一个字节一个字节地接收数据,而不是一次接收一个预订格式的数 ...

  9. 关于主从复制的超详细解析(全)

    目录 前言 1. 主从复制 1.1 方式 2. Mysql的主从复制 2.1 一主一从 2.1.1 window和linux通讯 2.1.2 linux和linux的通讯 2.2 双主双从 3. Re ...

最新文章

  1. 美国多所高校宣称9月线下开学,纽约大学教授:请停止妄想!
  2. windows常用命令(高级语句篇)
  3. 强制回收和IDisposable.Dispose方法
  4. java并发进程共享变量_JAVA并发编程学习:共享对象
  5. C语言再学习-- readelf、objdump、nm使用详解
  6. [签名算法]DSA 算法
  7. 记录一次SQL优化,增加索引,随便写的当笔记了
  8. C# 输出目录结构树到Console或文本文件
  9. 嵌入式linux 零基础-实践起步 --- 001 --- linux的版本
  10. linux下centeros7 关于mysql的下载与安装过程
  11. 24岁大专非科班转行前端开发可行性有多少?
  12. SpringBoot指南(八)——SpringBoot整合Redis
  13. Java数据类型分类
  14. linux无缝升级的版本,Angular 1 和 Angular 2 集成:无缝升级的方法
  15. iPhone SDK开发基础之自定义仪表控件
  16. Django的缓存(1)
  17. android投影仪分辨率是多少,如何挑选投影仪流明 分辨率?千万不要这样选,不然后果不堪设想...
  18. 马斯克 的 2500 吨 推力 的 大火箭 没什么 了不起
  19. mysql 视图 统计_mysql 视图
  20. OSChina 周六乱弹 —— 想通过么?收费!!!

热门文章

  1. Axure 9 实战案例,基本元件的应用 1,用矩形与标题设计视频封面
  2. 黑客入侵微软邮件服务器部署勒索软件、惠普更新打印机漏洞|12月2日全球网络安全热点
  3. 分析网络钓鱼的原理及防御措施
  4. 视觉SLAM笔记(40) 特征点的缺陷
  5. APP开发定制需求的常说分销模式,对于分销大家了解多少呢?
  6. 我涉及的数据可视化的实现技术和工具
  7. 大学开学初计算机水平测试,请查收这份大学生开学攻略——
  8. java对接支付宝支付
  9. 华硕笔记本电脑计算机打不开,华硕笔记本电脑无线开关打不开怎么办
  10. pyecharts各省人口GDP可视化分析