当前位置: 首页 > news >正文

Certificate数字证书的有效性验证

1.证书相关概念

        在讲证书有效性验证的逻辑之前,先了解几个概念。

  1.  证书颁发机构:一般为运营数字证书的机构,该机构负责证书的签发、吊销等生命周期管理。
  2. 证书链:证书颁发机构一般会由多个组成,为树状层级,第一级的机构证书叫根证书、第二级叫二级子CA证书,多个层级的机构证书组成一个文件叫证书链(后缀为:.p7b)。
  3. 吊销列表:由证书颁发机构发布,若证书过期或因某些原因(密钥泄漏)吊销,则会将该证书添加至吊销列表。吊销列表为一个文件,包含已吊销的证书序列号(后缀为:.crl)。

2.证书相关概念

        数字证书的有效性验证分为三个步骤:

        1.验证证书的有效期,证书的有效期是一个时间短,需验证当前使用证书的时间不早于开始时间,不晚于结束时间。

        2.证书链的验证:验证证书是否由合法的机构签发的。

        2.验证证书签发机构发布的吊销列表是否包含当前证书,若包含,则当前证书已不可用,为无效证书。

3.使用场景

        一般我们在调用https的服务接口时,会做证书的有效性校验。避免证书过期或因密钥泄漏后仍在使用。造成不安全的因素。

4.代码案例

依赖的jar包坐标如下:

        <dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15to18</artifactId><version>1.68</version></dependency><dependency><groupId>org.bouncycastle</groupId><artifactId>bcpkix-jdk15to18</artifactId><version>1.68</version></dependency>

以下为代码实现

    //以下静态块不能省略static {if(Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {Security.addProvider(new BouncyCastleProvider());}}/*** 验证用户证书的有效性,包括验证有效期、证书信任列表、吊销状态等** @param certFile       用户证书* @param certChainFile  证书链文件* @param crlFile        证书吊销列表文件* @throws CertificateNotYetValidException 证书未生效* @throws CertificateExpiredException     证书已过期* @throws SignatureException              证书不被信任* @throws IsRevokedException 证书被吊销*/public static void verifyCertificate(File certFile, File certChainFile, File crlFile) throws CertificateNotYetValidException, CertificateExpiredException,IsRevokedException, CertificateEncodingException {X509Certificate certificate = CertFileUtil.getCertificate(certFile);certificate.checkValidity();CertPath certPath = null;try {certPath = CertFileUtil.getCertPath(certChainFile);} catch (CertificateException e) {e.printStackTrace();throw new CommonException("证书链读取异常,原因:"+e.getMessage());}catch (FileNotFoundException e){throw new CommonException("未找到证书链文件,原因:"+e.getMessage());}List<X509Certificate> certList = (List<X509Certificate>) certPath.getCertificates();boolean flag = false;for(X509Certificate caCert : certList) {if(certificate.getIssuerX500Principal().equals(caCert.getSubjectX500Principal())) {//使用机构证书验签用户证书flag = verify(caCert.getPublicKey(),certificate);if(flag) {break;}}}if(!flag) {throw new CommonException("证书链验证证书签名失败");}X509CRL crlObj = CertFileUtil.getCrl(crlFile);if(crlObj.isRevoked(certificate)){X509CRLEntry crlEntry = crlObj.getRevokedCertificate(certificate);throw new IsRevokedException(crlEntry.getRevocationReason());}}private static boolean verify(PublicKey publicKey,X509Certificate certObj) {byte[] signValue = certObj.getSignature();byte[] data = null;try {data = certObj.getTBSCertificate();} catch (CertificateEncodingException e) {throw new CommonException("证书格式错误,未获取到证书内容,原因:"+e.getMessage(),e);}//获取签名算法的OIDAlgorithmIdentifier oid = new AlgorithmIdentifier(new ASN1ObjectIdentifier(certObj.getSigAlgOID()), DERNull.INSTANCE);String signName = new DefaultAlgorithmNameFinder().getAlgorithmName(oid);return verificationSignature(publicKey.getEncoded(), signName, signValue,data);}/*** 数字签名验签* @param publicKey 公钥(PKCS8编码的私钥字节数组,可参考非对称密钥对的生成接口返回结果。)* @param signAlg 签名算法* @param signValue 签名值* @param data 签名值的原文* @return true为验签通过,表示签名者是合法的。false为验证未通过,签名者为非法。*/private static boolean verificationSignature(byte[] publicKey, String signAlg, byte[] signValue,byte[] data)throws CryptoException{PublicKey key = null;if(signAlg.endsWith("RSA")) {key = SoftwareKeyUtil.bytesToPublicKey(publicKey, "RSA");}else{key = SoftwareKeyUtil.bytesToPublicKey(publicKey, "SM2");}Signature inSignatue = null;try {inSignatue = Signature.getInstance(signAlg, BouncyCastleProvider.PROVIDER_NAME);} catch (NoSuchAlgorithmException e) {e.printStackTrace();throw new CryptoException("未找到算法",e);}catch (NoSuchProviderException e){throw new CryptoException("未找到安全程序提供商,原因:"+e.getMessage(),e);}try {inSignatue.initVerify(key);} catch (InvalidKeyException e) {e.printStackTrace();throw new CryptoException("无效的公钥",e);}try {inSignatue.update(data);} catch (SignatureException e) {e.printStackTrace();throw new CryptoException("签名更新数据异常",e);}try {return inSignatue.verify(signValue);} catch (SignatureException e) {e.printStackTrace();throw new CryptoException("签名异常",e);}}

测试代码:以下代码只要未出现异常,则为证书有效性验证通过。

public static void main(String[] args) {try {CertificateUtil.verifyCertificate(new File("/home/zhangzz/Downloads/_.csdn.crt"),new File("/home/zhangzz/Downloads/GeoTrust CN RSA CA G1.p7c"));System.out.println("证书有效");} catch (CertificateNotYetValidException e) {System.out.println("证书有效期未开始,请待进入有效期后开始使用:" + e.getMessage());} catch (CertificateExpiredException e) {System.out.println("证书已过期:" + e.getMessage());}}

在数字证书里,是可以看到证书链的http下载地址及吊销列表的下载地址的。如下图:

证书链地址:已CSDN的证书为例,它的上一级就是当前证书的颁发机构证书,可以导出为证书链。

点击*.csdn.net这个证书,它的证书属性里有授权信息访问,该属性为颁发机构的信息,其中CA颁发者就是该机构的CA证书,也可以用该证书直接作为证书链去验证。

具体如何使用代码从证书里获取证书链和吊销列表文件,无需手动更新。这个问题我们下次再分解。

以上的代码可以在git中获取(若未找到代码,请切换dev分支),代码路径:com.zhangzz.crypto.utils.CertificateUtil.java

加密工具starter组件git地址

相关文章:

  • c#一个udp代码
  • asyncua模块中OPC UA的ua.Variant如何表示字典?
  • 四十八、openlayers地图调色总结——锐化、模糊、浮雕滤镜,调整地图色相、饱和度、亮度
  • 之所以选择天津工业大学,因为它是双一流、报考难度适宜,性价比高!天津工业大学计算机考研考情分析!
  • Java基础 - 练习(三)打印空心菱形
  • 超详细的selenium使用指南
  • 驾校在线考试系统源码 手机+PC+平板自适应
  • 了解指标体系1:指标是大数据开发中的关键要素
  • linux系统中,pwd获取当前路径,dirname获取上一层路径;不使用 ../获取上一层路径
  • 连接Huggingface报requests.exceptions.SSLError错误
  • 数据库-连接查询-连接查询
  • 【Java】图的初识
  • MYSQL in和exists
  • Spark日志有哪些?
  • 【接口自动化测试】第二节.Requests库和接口对象封装
  • JS 中的深拷贝与浅拷贝
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • 【React系列】如何构建React应用程序
  • cookie和session
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • Java程序员幽默爆笑锦集
  • Just for fun——迅速写完快速排序
  • laravel 用artisan创建自己的模板
  • mysql中InnoDB引擎中页的概念
  • 对象管理器(defineProperty)学习笔记
  • 诡异!React stopPropagation失灵
  • 讲清楚之javascript作用域
  • 聊聊flink的TableFactory
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 项目实战-Api的解决方案
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • Java性能优化之JVM GC(垃圾回收机制)
  • 不要一棍子打翻所有黑盒模型,其实可以让它们发挥作用 ...
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • "无招胜有招"nbsp;史上最全的互…
  • # 利刃出鞘_Tomcat 核心原理解析(七)
  • %check_box% in rails :coditions={:has_many , :through}
  • (function(){})()的分步解析
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (第61天)多租户架构(CDB/PDB)
  • (二)hibernate配置管理
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (强烈推荐)移动端音视频从零到上手(下)
  • (转)JAVA中的堆栈
  • (转载)(官方)UE4--图像编程----着色器开发
  • .NET 8.0 中有哪些新的变化?
  • .net core 6 集成 elasticsearch 并 使用分词器
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .NET MVC第五章、模型绑定获取表单数据
  • .net 程序发生了一个不可捕获的异常
  • .NET/C# 获取一个正在运行的进程的命令行参数
  • .NET国产化改造探索(一)、VMware安装银河麒麟
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • @vueup/vue-quill使用quill-better-table报moduleClass is not a constructor