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);
        }
        //获取签名算法的OID
        AlgorithmIdentifier 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地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/724540.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式开发十八:USART串口通信实验

上一节我们学习了串口通信的基本理论&#xff0c;串口通信是学习单片机的一个重要的一步&#xff0c;非常重要&#xff0c;这一节我们通过实验来学习串口通信的使用&#xff0c;以及串口的接收中断的使用。 一、发送单个字节uint8_t数据或者字符型数据 实现的功能&#xff1a;…

conda下安装32位版本python

前言&#xff1a;当前主流的系统为64bit系统&#xff0c;conda软件为64bit软件&#xff0c;因此使用conda创建虚拟环境安装python时默认安装的python为64bit版本&#xff0c;但部分研发场景需要调用32bit依赖&#xff0c;只能使用32bit的python&#xff0c;因此需要安装32bit的…

KVB投资安全小知识:如何识别一个货币是避险货币还是风险货币?

摘要 在全球经济不断变化的今天&#xff0c;理解货币的避险属性和风险特征对投资者至关重要。本文将详细探讨如何准确识别一个货币是避险货币还是风险货币&#xff0c;并结合具体的货币案例分析它们的本质差异。通过深入分析不同因素对货币走势的影响&#xff0c;帮助读者在金…

【面试八股总结】Redis数据结构及底层实现

一、五种基本数据结构 Redis 提供了丰富的数据类型&#xff0c;常见的有五种数据类型&#xff1a;String&#xff08;字符串&#xff09;&#xff0c;Hash&#xff08;哈希&#xff09;&#xff0c;List&#xff08;列表&#xff09;&#xff0c;Set&#xff08;集合&#xff0…

【Java】已解决java.util.EmptyStackException异常

文章目录 一、问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.util.EmptyStackException异常 一、问题背景 java.util.EmptyStackException是Java在使用java.util.Stack类时可能会遇到的一个异常。这个异常通常在尝试从空的栈中弹出&am…

[吃瓜教程]概览西瓜书+南瓜书第1、2章

第一章 绪论 1.1机器学习的定义,什么是机器学习&#xff1f; 1&#xff09;机器学习是这样一门学科&#xff0c;它致力于研究如何通过计算的手段&#xff0c;利用经验来改善系统自身的性能。 2&#xff09;机器学习所研究的主要内容是关于在计算机上从数据中产生模型的算法&a…

【golang学习之旅】Go程序快速开始 Go程序开发的基本注意事项

系列文章 【golang学习之旅】使用VScode安装配置Go开发环境 【golang学习之旅】报错&#xff1a;a declared but not used 【golang学习之旅】Go 的基本数据类型 【golang学习之旅】深入理解字符串string数据类型 【golang学习之旅】go mod tidy 【golang学习之旅】记录一次 p…

linux配置Vnc Server给Windows连接

1. linux 安装必要vnc server和桌面组件 sudo apt -y install tightvncserversudo apt install xfce4 xfce4-goodies2. linux 配置vncserver密码 #bash vncserver参考: https://cn.linux-console.net/?p21846#google_vignette 3. 将启动桌面命令写入.vnc/xstartup # .vnc/x…

了解指标体系1:指标是大数据开发中的关键要素

在大数据开发的过程中&#xff0c;指标体系是一个至关重要的概念。本文将介绍什么是指标&#xff0c;为什么它们如此重要&#xff0c;以及如何在大数据项目中有效地构建和应用指标体系。 目录 什么是指标&#xff1f;指标的类型为什么指标如此重要&#xff1f;如何构建有效的指…

2024最新自动化测试 —— Jest 测试框架应用

什么是自动化测试 在软件测试中&#xff0c;自动化测试指的是使用独立于待测软件的其他软件来自动执行测试、比较实际结果与预期并生成测试报告这一过程。在测试流程已经确定后&#xff0c;测试自动化可以自动执行的一些重复但必要的测试工作。也可以完成手动测试几乎不可能完…

xcode和iPhone真机或者watch真机连接问题

1.如果真机是第一次连接xocde&#xff0c;就需要开启真机上的开发者模式&#xff0c;开启开发者模式的方式&#xff1a; iphone/ipad开启方式: 设置 > 隐私与安全 > 开发者模式 > 开启&#xff0c;然后重启就可以了 watch设置&#xff1a;很麻烦&#xff0c;看文章…

对身外之物,不必在意

不管对待自己还是他人&#xff0c;外在的条件不值得挂怀&#xff0c;人在不得已颠沛流离时期&#xff0c;吃不好、穿不好&#xff0c;都应该从容接受。

外汇天眼:盈透证券为客户提供更丰富的欧洲衍生品交易渠道

电子交易巨头盈透证券&#xff08;纳斯达克代码&#xff1a;IBKR&#xff09;今日宣布&#xff0c;通过Cboe欧洲期权交易所&#xff08;CEDX&#xff09;新增欧洲股票期权和欧洲指数期货及期权。这一新增功能使得盈透证券的客户可以在单一统一平台上&#xff0c;除了股票、期权…

力扣469A

文章目录 1. 题目链接2. 题目代码3. 题目总结4. 代码分析 1. 题目链接 I Wanna Be the Guy 2. 题目代码 #include<iostream> #include<set> using namespace std; int main(){int highestLevelOfGame;cin >> highestLevelOfGame;set<int> levelCanPas…

【profinet】从站开发要点

目录 0、常见缩写及关键字注释 1、profinet简介 2、profinet协议栈 3、profinet数据帧 4、profinet网络解决方案示例 5、Application areas 注&#xff1a;本文主要简述profinet从站开发涉及到的知识点。【不足之处后续慢慢补充】。 0、常见缩写及关键字注释 MRP: Media…

移动硬盘接入mac无法复制文件进去怎么办,mac里的文件如何存进移动硬盘

如果要传输的文件数据量比较大&#xff0c;相比于使用U盘&#xff0c;移动硬盘是更多的选择。移动硬盘可存储量大、传输速度快&#xff0c;是实用性比较强的储存设备。不仅是Windows设备&#xff0c;Mac电脑也经常使用到移动硬盘。但有时候&#xff0c;移动硬盘在Mac上不能传文…

XHS-Downloader是一款小红书图片视频下载工具

这款软件可以提取账号发布、收藏、点赞作品链接&#xff1b;提取搜索结果作品链接、用户链接&#xff1b;下载小红书作品信息&#xff1b;提取小红书作品下载地址&#xff1b;下载小红书无水印作品文件&#xff01; &#x1f4d1; 功能清单 ✅ 采集小红书图文 / 视频作品信息…

【Pmac】PMAC QT联合开发中各种可能遇到的坑

目录 1. 错误 C2027 使用了未定义类型“PCOMMSERVERLib::DEVUPLOAD”2. 输入了正确的pmac的ip地址&#xff0c;没有显示可选的pmac设备3. Pmac DTC-28B无读数 使用QT编写PMAC上位机程序时&#xff0c;利用QT中的dump工具可以将pcommserver.exe转化为pcommserverlib.h和pcommser…

AMBA-CHI协议详解(四)

《AMBA 5 CHI Architecture Specification》 AMBA-CHI协议详解&#xff08;一&#xff09; AMBA-CHI协议详解&#xff08;二&#xff09; AMBA-CHI协议详解&#xff08;三&#xff09; AMBA-CHI协议详解&#xff08;四&#xff09; 文章目录 2.3.3 Atomic transactions2.3.4 S…

Hadoop3:MapReduce中的Shuffle机制

一、流程图 Shuffle是Map方法之后&#xff0c;Reduce方法之前的数据处理过程称。 二、图解说明 1、数据流向 map方法中context.write(outK, outV);开始&#xff0c;写入环形缓冲区&#xff0c;再进行分区排序&#xff0c;写到磁盘 reduce方法拉取磁盘上的数据&#xff0c;…