07-HTTPS双向认证及Java案例

news2025/1/11 9:00:16

1.双向认证流程

  1. 客户端发起建立HTTPS连接请求,将SSL协议版本的信息发送给服务端;
  2. 服务器端将本机的公钥证书(server.crt)发送给客户端;
  3. 客户端读取公钥证书(server.crt),取出了服务端公钥;
  4. 客户端将客户端公钥证书(client.crt)发送给服务器端;
  5. 服务器端使用根证书(root.crt)解密客户端公钥证书,拿到客户端公钥;
  6. 客户端发送自己支持的加密方案给服务器端;
  7. 服务器端根据自己和客户端的能力,选择一个双方都能接受的加密方案,使用客户端的公钥加密后发送给客户端;
  8. 客户端使用自己的私钥解密加密方案,生成一个随机数R,使用服务器公钥加密后传给服务器端;
  9. 服务端用自己的私钥去解密这个密文,得到了密钥R
  10. 服务端和客户端在后续通讯过程中就使用这个密钥R进行通信了。

2. 证书准备

从上一章内容中,我们可以总结出来,整个双向认证的流程需要六个证书文件:

  • 服务器端公钥证书:server.crt
  • 服务器端私钥文件:server.key
  • 根证书:root.crt
  • 客户端公钥证书:client.crt
  • 客户端私钥文件:client.key
  • 客户端集成证书(包括公钥和私钥,用于浏览器访问场景):client.p12

所有的这些证书,我们都可以向证书机构去申请签发,一般需要收取一定的证书签发费用,此时我们需要选择大型的证书机构去购买。如果只是企业内部使用,不是给公众使用,也可以自行颁发自签名证书

3. 自签名证书

3.1 、根证书

(1)创建根证书私钥

openssl genrsa -out root.key 1024

(2)创建根证书请求文件:

openssl req -new -out root.csr -key root.key

后续参数请自行填写,下面是一个例子:

Country Name (2 letter code) [XX]:cn
State or Province Name (full name) []:bj
Locality Name (eg, city) [Default City]:bj
Organization Name (eg, company) [Default Company Ltd]:alibaba
Organizational Unit Name (eg, section) []:test
Common Name (eg, your name or your servers hostname) []:root
Email Address []:a.alibaba.com
A challenge password []:
An optional company name []:

(3)创建根证书

openssl x509 -req -in root.csr -out root.crt -signkey root.key -CAcreateserial -days 3650

在创建证书请求文件的时候需要注意三点,下面生成服务器请求文件和客户端请求文件均要注意这三点:

  • 根证书的Common Name填写root就可以,所有客户端和服务器端的证书这个字段需要填写域名,一定要注意的是,根证书的这个字段和客户端证书、服务器端证书不能一样;
  • 其他所有字段的填写,根证书、服务器端证书、客户端证书需保持一致
  • 最后的密码可以直接回车跳过。

经过上面三个命令行,我们最终可以得到一个签名有效期为10年的根证书root.crt,后面我们可以用这个根证书去颁发服务器证书和客户端证书。

3.2、 生成自签名服务器端证书

(1)生成服务器端证书私钥

openssl genrsa -out server.key 1024

(2) 生成服务器证书请求文件,过程和注意事项参考根证书,本节不详述:

openssl req -new -out server.csr -key server.key

(3) 生成服务器端公钥证书

openssl x509 -req -in server.csr -out server.crt -signkey server.key -CA root.crt -CAkey root.key -CAcreateserial -days 3650

经过上面的三个命令,我们得到:
server.key:服务器端的密钥文件 server.crt:有效期十年的服务器端公钥证书,使用根证书和服务器端私钥文件一起生成

3.3、 生成自签名客户端证书

(1)生成客户端证书密钥:

openssl genrsa -out client.key 1024
openssl genrsa -out client2.key 1024

(2) 生成客户端证书请求文件,过程和注意事项参考根证书,本节不详述:

openssl req -new -out client.csr -key client.key
openssl req -new -out client2.csr -key client2.key

(3) 生客户端证书

openssl x509 -req -in client.csr -out client.crt -signkey client.key -CA root.crt -CAkey root.key -CAcreateserial -days 3650
openssl x509 -req -in client2.csr -out client2.crt -signkey client2.key -CA root.crt -CAkey root.key -CAcreateserial -days 3650

(4) 生客户端p12格式证书,需要输入一个密码,选一个好记的,比如123456

openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12
openssl pkcs12 -export -clcerts -in client2.crt -inkey client2.key -out client2.p12

重复使用上面的命令,我们得到两套客户端证书:

  • client.key / client2.key:客户端的私钥文件
  • client.crt / client2.key:有效期十年的客户端证书
    使用根证书和客户端私钥一起生成 client.p12/client2.p12,这个证书文件包含客户端的公钥和私钥,主要用来给浏览器访问使用

4. keytool生成证书

使用双向认证的SSL/TLS协议通信,客户端和服务器端都要设置用于证实自己身份的安全证书,并且还要设置信任对方的哪些安全证书。
理论上一共需要准备四个文件,两个keystore文件和两个truststore文件。
通信双方分别拥有一个keystore和一个truststore,keystore用于存放自己的密钥和公钥,truststore用于存放所有需要信任方的公钥。

keytool -genkey -alias catserver -keyalg rsa -keysize 1024 -sigalg sha256withrsa -keypass huawei -keystore catserver.keystore -storepass huawei

keytool -genkey -alias foxclient -keyalg dsa -keysize 512 -sigalg sha1withdsa -keypass huawei -keystore foxclient.keystore -storepass huawei
keytool -export -alias catserver -keystore catserver.keystore -storepass huawei -file catserver.cer
keytool -export -alias foxclient -keystore foxclient.keystore -storepass huawei -file foxclient.cer
keytool -import -alias foxclient -keystore catservertrust.keystore -storepass huawei -file foxclient.cer
keytool -import -alias catserver -keystore foxclienttrust.keystore -storepass huawei -file catserver.cer

5. 使用Java调用

5.1、server代码

public class CatServer implements Runnable, HandshakeCompletedListener {

    public static final int SERVER_PORT = 11123;

    private final Socket _s;
    private String peerCerName;

    public CatServer(Socket s) {
        _s = s;
    }

    public static void main(String[] args) throws Exception {
        String serverKeyStoreFile = "D:\\code\\mycode\\java-study\\https\\src\\main\\resources\\double\\catserver.keystore";
        String serverKeyStorePwd = "huawei";
        String catServerKeyPwd = "huawei";
        String serverTrustKeyStoreFile = "D:\\code\\mycode\\java-study\\https\\src\\main\\resources\\double\\catservertrust.keystore";
        String serverTrustKeyStorePwd = "huawei";

        KeyStore serverKeyStore = KeyStore.getInstance("JKS");
        serverKeyStore.load(new FileInputStream(serverKeyStoreFile), serverKeyStorePwd.toCharArray());

        KeyStore serverTrustKeyStore = KeyStore.getInstance("JKS");
        serverTrustKeyStore.load(new FileInputStream(serverTrustKeyStoreFile), serverTrustKeyStorePwd.toCharArray());

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(serverKeyStore, catServerKeyPwd.toCharArray());

        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(serverTrustKeyStore);

        SSLContext sslContext = SSLContext.getInstance("TLSv1");
        sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
        SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(SERVER_PORT);
        sslServerSocket.setNeedClientAuth(true);

        while (true) {
            SSLSocket s = (SSLSocket) sslServerSocket.accept();
            CatServer cs = new CatServer(s);
            s.addHandshakeCompletedListener(cs);
            new Thread(cs).start();
        }
    }

    @Override
    public void run() {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(_s.getInputStream()));
            PrintWriter writer = new PrintWriter(_s.getOutputStream(), true);

            writer.println("Welcome~, enter exit to leave.");
            String s;
            while ((s = reader.readLine()) != null && !s.trim().equalsIgnoreCase("exit")) {
                writer.println("Echo: " + s);
            }
            writer.println("Bye~, " + peerCerName);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                _s.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void handshakeCompleted(HandshakeCompletedEvent event) {
        try {
            X509Certificate cert = (X509Certificate) event.getPeerCertificates()[0];
            peerCerName = cert.getSubjectX500Principal().getName();
                } catch (SSLPeerUnverifiedException ex) {
                ex.printStackTrace();
                }
                }

                }

5.2、client代码

public class FoxClient {
    public static void main(String[] args) throws Exception {
        String clientKeyStoreFile = "D:\\code\\mycode\\java-study\\https\\src\\main\\resources\\double\\foxclient.keystore";
        String clientKeyStorePwd = "huawei";
        String foxclientKeyPwd = "huawei";
        String clientTrustKeyStoreFile = "D:\\code\\mycode\\java-study\\https\\src\\main\\resources\\double\\foxclienttrust.keystore";
        String clientTrustKeyStorePwd = "huawei";

        KeyStore clientKeyStore = KeyStore.getInstance("JKS");
        clientKeyStore.load(new FileInputStream(clientKeyStoreFile), clientKeyStorePwd.toCharArray());

        KeyStore clientTrustKeyStore = KeyStore.getInstance("JKS");
        clientTrustKeyStore.load(new FileInputStream(clientTrustKeyStoreFile), clientTrustKeyStorePwd.toCharArray());

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(clientKeyStore, foxclientKeyPwd.toCharArray());

        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(clientTrustKeyStore);

        SSLContext sslContext = SSLContext.getInstance("TLSv1");
        sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        SSLSocketFactory socketFactory = sslContext.getSocketFactory();
        Socket socket = socketFactory.createSocket("localhost", CatServer.SERVER_PORT);

        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

        send("hello", out);
        send("exit", out);
        receive(in);
        socket.close();
    }

    public static void send(String s, PrintWriter out) throws IOException {
        System.out.println("Sending: " + s);
        out.println(s);
    }

    public static void receive(BufferedReader in) throws IOException {
        String s;
        while ((s = in.readLine()) != null) {
            System.out.println("Reveived: " + s);
        }
    }
}

参考文章:

更多内容关注微信公众号 ”前后端技术精选“,或者语雀,里面有更多知识:https://www.yuque.com/riverzmm/uu60c9?# 《安全》

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

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

相关文章

wordpress的手工迁移

我的场景 将某个在阿里云服务器(windows操作系统)上apache容器下的wordpress服务迁移到另一个linux主机上的apache上。 迁移要点 1、迁移源主机下的wordpress文件夹,在apache容器下的htdocs文件夹中 2、迁移数据库 3、根据目标&#xff0…

表弟大学毕业要学前端,我给他制定了一份亲属自学计划

表弟也终于到了马上要大学毕业的时间,然后听说我在做前端开发工作,就想着能不能和我一起搞一搞。 我说这又不是小时候一起去地里抓兔子,说走就一起走,拿上工具一起走了,这得学啊。看着表弟期待的眼神,他问了…

Scientific Reports|比较转录组分析揭示了杀菌剂氰烯菌酯对尖孢镰刀菌的抗性调控机制和杀菌活性

TITLE:Comparative transcriptome analysis reveals the resistance regulation mechanism and fungicidal activity of the fungicide phenamacril in Fusarium oxysporum 译名:比较转录组分析揭示了杀菌剂氰烯菌酯对尖孢镰刀菌的抗性调控机制和杀菌活性…

Java代码审计——文件操作漏洞

目录 (一)、 文件操作漏洞简介 (二) 、漏洞发现与修复案例 2.1 文件包含漏洞 2.2 文件上传漏洞 (三) 文件下载/读取漏洞 (四).文件写入漏洞 (五&…

Arcgis建筑面shp由DSM和DEM获取高度拉伸并可视化

效果 1、准备数据 DEM、DSM数据精度尽量高一些 1)DEM 2)DSM 3)建筑shp 所有数据坐标统一,而且加载后位置能对上,DEM和DSM具有相同的像元大小 2、准备数据前的一些操作 1)矢量shp裁剪

C#实现最大公约数和最小公倍数

最大公约数: 最大公因数,也称最大公约数、最大公因子,指两个或多个整数共有约数中最大的一个。a,b的最大公约数记为(a,b),同样的,a,b,c的最大公约…

net.sf.json.JSONObject 类的日常使用,非阿里巴巴的JSONObject,附上作者的jsonDemo

文章目录Json介绍作者的Demo项目地址常见的转化使用测试json的添加属性,打印bean与json互转deepBean与json互转list与json互转map与json互转demo所用到的实体类StudentGrade个人使用的依赖常用方法其他参考文档Json介绍 1、JSONObject只是一种数据结构,可…

DJYGUI系列文章七:GDD窗口系统

目录 1 窗口分类及关系 2 窗口的客户区与非客户区 3 坐标系统 4 窗口句柄与窗口ID的作用与区别 5 窗口的关闭、销毁、退出过程 6 API说明 6.1 ScreenToClient: 屏幕坐标转换为客户区坐标 6.2 ClientToScreen: 客户区坐标转换为屏幕坐标 6.3 Scre…

linux篇【11】:linux下的线程

目录 一.linux下的线程 1.linux下的线程概念 (1)教材上粗略的 线程 定义 (2)线程的引入 (3)线程真正定义 以及 示意图 (4)linux 和 windows等其他操作系统的线程对比 2.重新定…

22-python异常

异常一. 了解异常二. 异常的写法2.1 语法2.2 快速体验2.3 捕获指定异常2.3.1 语法2.3.2 体验2.3.3 捕获多个指定异常2.3.4 捕获异常描述信息2.3.5 捕获所有异常2.4 异常的else2.5 异常的finally三. 异常的传递四. 自定义异常五. 总结一. 了解异常 当检测到一个错误时&#xff…

Hibernate多表的关联关系、懒加载

一、一对多关系:插入: “一”的一方为主表,“多”的一方为副表,主表关联副表,应该在主表中加入副表对象作为属性。 根据顾客ID插入顾客信息 (一) ,同时将顾客名下所有订单插入 &…

Python实现人脸识别检测,对主播进行颜值排行

前言 嗨嗨,我亲爱的家人们 今天来整点不一样的,嘿嘿 用Python简单实现对人脸识别的检测,对某平台主播照片进行评分排名 应该对女主播这个词不陌生吧,怎么说应该还是蛮多人看过一些女主播吧 我无聊的时候也会看看,…

2009年数学二真题复盘

选择题: 间断点的判断的前置芝士: 间断点的定义 设函数f(x)在点的去心领域内有定义,若f(x)满足以下条件之一: 在x=没有定义在x=有定义,但是不存在,或者存在,但是极限值不等于函数值。 类型定义 相关概念第一类间断点

CMS垃圾回收器

概述 CMS(Concurrent Mark-Sweep)是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器。对于要求服务器响应速度的应用上,这种垃圾回收器非常适合。在启动JVM参数加上-XX:UseConcMarkSweepGC,这个参数表示对于老年代的回收采用CMS。CMS采用的基础算…

SpringBoot SpringBoot 开发实用篇 5 整合第三方技术 5.13 j2cache 相关配置

SpringBoot 【黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇5 整合第三方技术5.13 j2cache 相关配置5.13.1 j2cache 相关配置5.13…

直播绿幕抠图的例子(绿幕抠图直播实例参考)

阿酷TONY / 2022-11-21 / 长沙 什么是绿幕抠图: 设定绿幕或绿布,做直播软件抠图,这时绿幕绿布就可以被实时的抠掉,绿色就变成透明了,只剩下绿幕外的人物,此时添加上直播的背景画质,就实现了绿…

Git——Git常用命令

目录 常用命令概览 1. 设置用户签名 2. 初始化本地库 2.1 初始化本地库 2.2 查看文件 2.3 查看隐藏文件 2.4 进入到下一个目录 3. 查看本地库状态 4.添加暂存区 4.1 删除文件 5. 提交本地库 5.1 将暂存区的文件提交到本地库 6. 查看版本信息的命令 7.修改文件 8. 历史版本…

【Python入门指北】服务器信息清洗

服务器信息清洗 文章目录服务器信息清洗一、 subprocess 执行本机命令二、 获取服务器的硬件基础信息1. 基础信息2. 厂家和产品信息3. CPU 信息3.1 查看物理CPU型号3.2 查看物理CPU颗数3.3 查看每颗物理 CPU 的核心数4. 内存信息练习内存处理参考代码一、 subprocess 执行本机命…

智云通CRM:如何提前识别哪些客户爱说“不”?

有人说,做业务是最好的锻炼意志力方法,因为做业务的人经常会被客户拒绝甚至会扫地出门。被拒绝时,业务员一定要擦亮眼睛,善于察言观色,洞察客户的心理活动。透过观察了解客户为什么说“不”,客户拒绝情况有…

聚观早报 | 推特临时培训员工应对世界杯;世界杯足球内置传感器

今日要闻:推特临时培训员工应对世界杯;京东靠降本增效实现转亏为盈;世界杯足球内置传感器;艾格重返迪士尼CEO职位;特斯拉明年或开启收购计划 推特临时培训员工应对世界杯 据消息, 2022年世界杯拉开帷幕,推特的使用量即将激增,其维…