Certificate数字证书的有效性验证

news2024/9/21 0:45:55

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地址

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

产品Web3D交互展示有什么优势?如何快速制作?

智能互联网时代&#xff0c;传统的图片、文字、视频等产品展示方式&#xff0c;因为缺少互动性&#xff0c;很难引起用户的兴趣&#xff0c;已经逐渐失去了宣传优势。 Web3D交互展示技术的出现&#xff0c;让众多品牌和企业找到了新的方向&#xff0c;线上产品展示不在枯燥无趣…

大屏适配方案汇总

1. 适配方案1&#xff1a;rem font-size 我们都知道&#xff0c;在 css 中 1rem 等于 html 根元素设定的 font-size 的 px 值&#xff0c;通过动态的修改html 根元素的 font-size 大小就能动态的改变 rem 的大小&#xff0c;从而实现适配。 原理 动态设置 HTML 根字体大小将…

大模型上下文实验之大海捞针和数星星

大模型上下文实验之大海捞针和数星星 大海捞针和数星星大海捞针大海捞针测试简介Greg Kamradt 的“大海捞针”实验实验步骤实验预期 ChatGPT-4 128K的实验结果Claude-2.1 200K的实验结果 数星星数星星简介多证据获取多证据推理 实验结果多证据获取任务示例多证据推理任务示例 数…

Adobe Premiere 视频编辑软件下载安装,pr 全系列资源分享!

Adobe Premiere以其强大的功能、灵活的操作和卓越的性能&#xff0c;成为视频编辑领域的佼佼者。 在剪辑方面&#xff0c;Adobe Premiere提供了强大而灵活的工具集。用户可以在直观的时间线上对视频进行精细的裁剪、剪辑和合并操作。无论是快速剪辑短片&#xff0c;还是精心打造…

洗地机哪个品牌比较好?四款好用靠谱的优质洗地机推荐

随着现代生活节奏的加快&#xff0c;家庭清洁成了一项耗时且繁琐的任务。洗地机凭借其智能化和高效的清洁能力&#xff0c;越来越受到大家的青睐。然而&#xff0c;市场上各种品牌和型号琳琅满目&#xff0c;让人眼花缭乱。为了帮助大家在众多选择中找到心仪的产品&#xff0c;…

真人模特+虚拟模特:阿里通义万相带你体验全新的卖家秀!

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff0c;致力于程序服务生活&#xff01; 一、引言 在数字化和虚拟化的时代&#xff0c;正在经历一场由人工智能驱动的革命。这场革命不仅改变了的生活&#xff0c;也正在改变的商业环境。阿里巴巴集团是这场革命的重要参与者…

铁路定向声波冲击波智能驱鸟器

对于铁路系统来说&#xff0c;鸟类活动会带来潜在的安全隐患。铁路沿线的接触网、电杆等设备&#xff0c;是鸟类筑巢的理想场所&#xff0c;但鸟类在筑巢过程中&#xff0c;常常使用的树枝、铁丝等杂物&#xff0c;一旦掉落在接触网设备上&#xff0c;就可能造成带电体与接地侧…

6月19日(周三)A股行情总结:A股震荡收跌,恒生科技指数大涨3%,10年期国债期货转涨续创新高

内容提要 车路云概念延续昨日涨势&#xff0c;华铭智能20CM 3连板。贵金属及PEEK材料概念全日走强&#xff1b;港股有色金属及能源股走强&#xff0c;紫金矿业涨超3%&#xff0c;中石油涨超3%。国债期货午后全线转涨&#xff0c;10年期主力合约涨0.05%报104.925元&#xff0c;…

2024年一年一度的618正式结束了,苹果与华为手机销量看看谁是大赢家?

一年一度的618正式结束了&#xff0c;各品牌基本上都发布了相应的战报。但是要告诉大家一点看战报要看定语&#xff0c;定语最少的才是真正的第一。现在给大家汇总下京东平台的数据&#xff0c;看看谁是最大赢家&#xff0c;谁又是国产荣光。注&#xff1a;所有数据截至6月18日…

好用的linux一键换源脚本

最近发现一个好用的linux一键换源脚本&#xff0c;记录一下 官方链接 大陆使用 bash <(curl -sSL https://linuxmirrors.cn/main.sh)# github地址 bash <(curl -sSL https://raw.githubusercontent.com/SuperManito/LinuxMirrors/main/ChangeMirrors.sh) # gitee地址 …

C语言练习01-循环

一、打印五行五列的三角形 如下图&#xff1a; #include<stdio.h>int main() {for (int i 1;i < 5; i){for (int j i; j < 5; j){printf("*");}printf("\n");}return 0; }#include<stdio.h>int main() {for (int i 1;i < 5; i){f…

鸿蒙开发通信与连接:【@ohos.bluetooth (蓝牙)】

蓝牙 说明&#xff1a; 本模块首批接口从API version 7开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 蓝牙模块提供了基础的传统蓝牙能力以及BLE的扫描、广播等功能。 导入模块 import bluetooth from ohos.bluetooth;bluetooth.enableBluet…

6.S081的Lab学习——Lab7: Multithreading

文章目录 前言一、Uthread: switching between threads (moderate)提示&#xff1a;解析 二、Using threads (moderate)解析&#xff1a; 三、Barrier (moderate)解析&#xff1a; 总结 前言 一个本硕双非的小菜鸡&#xff0c;备战24年秋招。打算尝试6.S081&#xff0c;将它的…

讨论字符串(未完)

讨论字符串 C语言中的字符串C中的字符串string类的构造函数string类对象的容量操作string类对象元素访问及遍历迭代器 string类对象的修改操作 string类的模拟实现成员变量构造函数析构函数扩容/预留空间push_back遍历operator[]迭代器 append任意位置插入数据和删除数据查找元…

PID控制算法学习笔记分享

目录 一、参数设定 二、PID计算公式 三、位置式PID代码实现 四、增量式PID代码实现 五、两种控制算法的优缺点 六、PID算法的改进 一、参数设定 比例系数&#xff08;kp&#xff09;&#xff1a;P项的作用是根据当前误差的大小来产生一个控制量。它直接与误差成正比&#…

Tensorflow入门实战 T05-运动鞋识别

目录 一、完整代码 二、训练过程 &#xff08;1&#xff09;打印2行10列的数据。 &#xff08;2&#xff09;查看数据集中的一张图片 &#xff08;3&#xff09;训练过程&#xff08;训练50个epoch&#xff09; &#xff08;4&#xff09;训练结果的精确度 三、遇到的问…

0618,0619 ,指针,指针与数组,字符串

目录 第八章&#xff08;指针&#xff09;&#xff0c;第九章&#xff08;指针和数组&#xff09;&#xff0c;第十章&#xff08;字符串&#xff09;思维导图 作业1 逆序打印 解答&#xff1a; 答案&#xff1a; 作业2 判断回文 解答&#xff1a; 答案&#xff1a; …

PCB设计隐藏的陷进

1、BGA芯片的开窗和过油设计。 加工工艺中&#xff0c;范式过孔都需要盖油设计&#xff0c;实心焊盘需要开窗设计&#xff0c;坚决不能盖油。 2、通孔设计的互联连通性 比如H3芯片的wifi设计&#xff0c;实际上是没有联通的&#xff0c;虽然四层板的中间层有焊盘&#xff0c;但…

【C++ | 移动构造函数】C++11的 移动构造函数 详解及例子代码

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a;2024-06-12 2…

Mamaba3--RNN、状态方程、勒让德多项式

Mamaba3–RNN、状态方程、勒让德多项式 一、简单回顾 在Mamba1和Mamba2中分别介绍了RNN和状态方程。 下面从两个图和两个公式出发&#xff0c;对RNN和状态方程做简单的回顾&#xff1a; R N N : s t W s t − 1 U x t &#xff1b; O t V s t RNN: s_t Ws_{t-1}Ux_t&…