SSL连接的JAVA实现

2023-11-01

SSL连接分为双向认证和单向认证。其中双向认证表示服务器和客户端都需要分别校验对方的身份。单向认证则只需要客户端校验服务器的身份。

SSL的双向认证的流程如下图:

从以上流程可见,要完成双向认证,服务器端和客户端都需要验证对方的证书,然后再进行加密的协商。这里基于JAVA来实现一个服务器端和客户端的程序,可以实现双向认证。

首先需要准备服务器和客户端的相关证书:

1. 创建自签名的根密钥

openssl genrsa -out rootkey.pem 2048

2. 生成根证书

openssl req -x509 -new -key rootkey.pem -out root.crt -subj="/C=CN/ST=GD/L=GZ/O=RootCA/OU=RootCA/CN=RootCA"

3. 生成客户端密钥

openssl genrsa -out clientkey.pem 2048

4. 生成客户端证书请求文件,使用根证书进行签发

openssl req -new -key clientkey.pem -out client.csr -subj="/C=CN/ST=GD/L=GZ/O=BMW/OU=Vehicle/CN=Vehicle1"

5. 用根证书来签发客户端请求文件,生成客户端证书client.crt

openssl x509 -req -in client.csr -CA root.crt -CAkey rootkey.pem -CAcreateserial -days 3650 -out client.crt

6. 打包客户端资料为pkcs12格式(client.pkcs12)

openssl pkcs12 -export -in client.crt -inkey clientkey.pem -out client.pkcs12

7. 生成服务器端的密匙

openssl genrsa -out serverkey.pem 2048

8. 生成服务器端证书的请求文件。请求根证书来签发

openssl req -new -key serverkey.pem -out server.csr -subj="/C=CN/ST=GD/L=GZ/O=BMW/OU=IT/CN=Broker"

9. 用根证书来签发服务器端请求文件,生成服务器端证书server.crt

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

10. 打包服务器端资料为pkcs12格式(server.pkcs12 )

openssl pkcs12 -export -in server.crt -inkey serverkey.pem -out server.pkcs12

11. 生成信任客户端的keystore,把根证书以及需要信任的客户端的证书添加到这个keystore

keytool -importcert -alias ca -file root.crt -keystore clienttrust.jks

keytool -importcert -alias clientcert -file client.crt -keystore clienttrust.jks

12. 生成信任服务器端的keystore,把根证书以及需要信任的服务端的证书添加到这个keystore

keytool -importcert -alias ca -file root.crt -keystore servertrust.jks

keytool -importcert -alias servercert -file server.crt -keystore servertrust.jks

服务器程序

以下是服务器的程序

public class SSLServer 
{
    private SSLServerSocket sslServerSocket;
    public static void main( String[] args ) throws Exception
    {
        SSLServer server = new SSLserver();
        server.init();
        System.out.println( "Server initialted!" );
        server.process();
    }

    public void init() throws Exception {
        int port = 9999;
        String keystorePath = "/home/roy/projects/cert/server.pkcs12";
        String keystorePass = "123456";
        SSLContext context = SSLContext.getInstance("TLSv1.2");

        //加载服务器的证书和Private key
        KeyStore serverKeyStore = KeyStore.getInstance("pkcs12");
        FileInputStream keystoreFis = new FileInputStream(keystorePath);
        serverKeyStore.load(keystoreFis, keystorePass.toCharArray());
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");
        kmf.init(serverKeyStore, keystorePass.toCharArray());

        //加载要信任的客户端证书的keystore
        String trustClientKeystorePath = "/home/roy/projects/cert/clienttrust.jks";
        KeyStore trustKeyStore = KeyStore.getInstance("jks");
        FileInputStream trustKeystoreFis = new FileInputStream(trustClientKeystorePath);
        trustKeyStore.load(trustKeystoreFis, keystorePass.toCharArray());
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509");
        tmf.init(trustKeyStore);

        context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
        sslServerSocket = (SSLServerSocket)context.getServerSocketFactory().createServerSocket(port);
        sslServerSocket.setNeedClientAuth(true);
    }

    public void process() throws Exception {
        String bye = "Bye!";
        byte[] buffer = new byte[50];
        while(true) {
            Socket socket = sslServerSocket.accept();
            InputStream in = socket.getInputStream();
            in.read(buffer);
            System.out.println("Received: " + new String(buffer));
            OutputStream out = socket.getOutputStream();
            out.write(bye.getBytes());
            out.flush();
        }
    }
}

客户端程序

如以下代码:

public class SSLClient
{
    private SSLSocket sslSocket;
    public static void main( String[] args ) throws Exception
    {
        SSLClient client = new SSLClient();
        client.init();
        System.out.println( "Client initiated." );
        client.process();
    }

    public void init() throws Exception {
        String host = "127.0.0.1";
        int port = 9999;
        String keystorePath = "/home/roy/projects/cert/client.pkcs12";
        String keystorePass = "123456";

        SSLContext context = SSLContext.getInstance("TLSv1.2");

        //加载客户端的证书和private key
        KeyStore clientKeyStore = KeyStore.getInstance("pkcs12");
        FileInputStream keystoreFis = new FileInputStream(keystorePath);
        clientKeyStore.load(keystoreFis, keystorePass.toCharArray());

        KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");
        kmf.init(clientKeyStore, keystorePass.toCharArray());

        //加载信任的服务器证书的keystore
        String trustServerKeystorePath = "/home/roy/projects/cert/servertrust.jks";
        KeyStore trustKeyStore = KeyStore.getInstance("jks");
        FileInputStream trustKeystoreFis = new FileInputStream(trustServerKeystorePath);
        trustKeyStore.load(trustKeystoreFis, keystorePass.toCharArray());
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509");
        tmf.init(trustKeyStore);

        context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
        sslSocket = (SSLSocket)context.getSocketFactory().createSocket(host, port);
    }

    public void process() throws Exception {
        String hello = "Hello World";
        OutputStream out = sslSocket.getOutputStream();
        out.write(hello.getBytes(), 0, hello.getBytes().length);
        out.flush();
        Thread.sleep(1000);
        InputStream in = sslSocket.getInputStream();
        byte [] buffer = new byte[50];
        in.read(buffer);
        System.out.println(new String(buffer));
    }
}

之后分别运行服务器和客户端程序,可以见到SSL的双向认证通过,建立连接并成功收发信息。

如果要实现单向认证,那么客户端的代码不需要改动,服务器端的代码改动如下:

public class SSLServer 
{
    private SSLServerSocket sslServerSocket;
    public static void main( String[] args ) throws Exception
    {
        SSLServer server = new SSLserver();
        server.init();
        System.out.println( "Server initialted!" );
        server.process();
    }

    public void init() throws Exception {
        int port = 9999;
        String keystorePath = "/home/roy/projects/cert/server.pkcs12";
        String keystorePass = "123456";
        SSLContext context = SSLContext.getInstance("TLSv1.2");

        //加载服务器的证书和Private key
        KeyStore serverKeyStore = KeyStore.getInstance("pkcs12");
        FileInputStream keystoreFis = new FileInputStream(keystorePath);
        serverKeyStore.load(keystoreFis, keystorePass.toCharArray());
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");
        kmf.init(serverKeyStore, keystorePass.toCharArray());

        context.init(kmf.getKeyManagers(), null, null);
        sslServerSocket = (SSLServerSocket)context.getServerSocketFactory().createServerSocket(port);
        sslServerSocket.setNeedClientAuth(false);
    }

    public void process() throws Exception {
        String bye = "Bye!";
        byte[] buffer = new byte[50];
        while(true) {
            Socket socket = sslServerSocket.accept();
            InputStream in = socket.getInputStream();
            in.read(buffer);
            System.out.println("Received: " + new String(buffer));
            OutputStream out = socket.getOutputStream();
            out.write(bye.getBytes());
            out.flush();
        }
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SSL连接的JAVA实现 的相关文章

  • Web 客户端异常:底层连接已关闭:无法建立 SSL/TLS 安全通道的信任关系

    我有一个简单的应用程序 它使用 C Web 客户端类来下载网站 HTML 这是我正在使用的代码的精简示例 WebClient wc new WebClient wc Headers Add user agent Mozilla 4 0 co
  • 如果Jetty的密钥库中有多个证书,它如何选择?

    我们的系统中有一些代码用于自动将自签名证书生成到密钥库中 然后由 Jetty 使用 如果给定主机的密钥已经存在 那么什么也不会发生 但如果它不存在 我们会生成一个新密钥 如下所示 public void generateKey String
  • 如何通过 SSL 将文件直接上传到 S3?

    我已经使用基于浏览器的 Amazon S3 直接 POST 上传有一段时间了 最 近想开始通过 HTTPS 发布 普通的 HTTP 帖子就可以正常工作 但是 当我将相同的表格发布到https s3 amazonaws com https s
  • Node.js 中的 HTTPS 代理服务器

    我正在开发一个node js代理服务器应用程序 我希望它支持HTTP and HTTPS SSL 协议 作为服务器 我目前正在使用node http proxy https github com nodejitsu node http pr
  • 信任所有将文件发送到 https Web 服务的 java 类

    我需要编写自己的类来告诉 mule 与服务 wsdl 的 https 连接已验证 我的 mule 项目已经接近完成 但最后一块丢失了 在特定的 url 发送文件 我想要实现的目标 建立连接并将 xml 发送到目标 url 读取 xml 格式
  • 如何将 OpenSSL 与 WinSock 一起使用?

    我在网上搜索过 但没有找到任何与此相关的内容 有谁有使用 WinSock 和 OpenSSL 的简单代码示例吗 我正在寻找一个简单的 Visual C 2005 或更高版本的代码示例 它创建并打开一个 Winsock 连接 并使用 Open
  • OkHttp javax.net.ssl.SSLPeerUnverifiedException:主机名domain.com未验证

    我几天来一直在努力让它发挥作用 我正在尝试通过以下方式连接到我的服务器https带有自签名证书 我认为现在没有任何页面或示例是我未读过的 我做了什么 按照本教程创建了 bks 密钥库 http blog crazybob org 2010
  • 如何使用 rustls 库建立 TLS 连接?

    The 文档 https docs rs rustls 0 10 0 rustls 提供了一个例子 不幸的是它不能编译 很多东西都被重命名了 界面也被重命名了ClientSession构造函数改变了 我设法将错误修复到可以编译的程度 但没有
  • 如何识别我的证书是否包含私钥?

    根据这个服务器故障问题的答案 https serverfault com questions 9708 what is a pem file and how does it differ from other openssl generat
  • Curl 和 Php 5.3.3 中的 SSL 连接错误

    我的网站自 3 年来一直运行良好 代码如下 现在突然从 2 天开始出现以下错误 SSL 连接错误 在 Curl error 中 下面是我的代码
  • 同时使用 SSL 加密和 NTLM 身份验证的 HttpClient 失败

    我尝试在使用 SSL 加密 https 以及 NTLM 身份验证的 Sharepoint 2010 服务器上执行简单的 REST 调用 当服务器设置为不需要 SSL 仅用于测试时 服务器在生产中将需要 SSL 时 我的 NTLM 身份验证和
  • 双向 SSL 说明

    我对双向 SSL 的工作原理有些困惑 客户端如何创建其证书以发送到服务器 是从服务器生成并分发给客户端吗 另外 双向 SSL 相对于单向 SSL 有何优势 两个证书在连接之前都应该存在 它们通常由证书颁发机构创建 不一定相同 在其他情况下
  • Tomcat 托管具有多个 SSL 证书的多个虚拟主机

    例如 我有一台使用 Tomcat 7 托管多个网站的服务器 a abc com b abc com c def com d def com 使用tomcat的虚拟主机功能 因此它们各自可能属于不同的webapps文件夹 我们现在正在尝试为每
  • Web 应用程序的 Spring Boot 和 Comodo https 配置

    我是 https 配置的新手 并尝试配置 spring boot 和 Comodo SSL 经过几次电话和尝试后 我已经弄清楚如何为您的 spring boot 网站正确配置 https 下面的答案是详细步骤 希望它可以帮助人们生成更安全的
  • if 不是 localhost 语句 htaccess

    我目前强迫访问者通过 https 访问我的所有网站 主要是 Wordpress 我使用以下代码 RewriteEngine On RewriteCond HTTPS on RewriteRule https SERVER NAME REQU
  • 使用 TLS/SSL 保护 Cassandra 通信

    我们希望保护 Cassandra 免受中间人攻击 有没有办法配置 Cassandra 使客户端 服务器和服务器 服务器 复制 通信采用 SSL 加密 谢谢 简短的回答 不 对于客户端 服务器 节俭 151 https issues apac
  • 通过 HTTPS 加载页面但请求不安全的 XMLHttpRequest 端点

    我有一个页面 上面有一些 D3 javascript 该页面位于 HTTPS 网站内 但证书是自签名的 当我加载页面时 我的 D3 可视化效果不显示 并且出现错误 混合内容 页面位于 https integration jsite com
  • OpenSSL DH 密钥太小错误

    我正在尝试使用简单的 PERL 脚本连接到封闭的服务器 空调 usr bin perl use 5 10 1 use warnings use strict use IO Socket SSL use IO Socket SSL qw de
  • .NET-MVC - 通过 SSL 重写 URL + 某些 URL?

    我有一个运行 IIS 6 NET MVC 和单个域名的网络服务器 该网站使用 URL 重写来生成如下 URL 域名 com controller action 我愿意强行一 1 个控制器 to use SSL 其他的应该无需 SSL 即可工
  • Google Chrome 中的 ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED

    我有一个使用 SSL 客户端证书授权的网站 所有客户端证书都是使用 OpenSSL 生成的并且是自签名的 一切都适用于所有网络浏览器 但推荐的是 Google Chrome 因为它使用与 IE 相同的 SSL 仓库 因此证书安装非常简单 点

随机推荐

  • 企业如何才能真正实现MES落地?

    MES是一种用于管理和控制制造过程的信息系统 可以帮助企业实现数字化转型 它提供了多种功能以支持企业的生产操作和决策 下面是一些常见的MES功能 生产计划排程 MES可以帮助制定生产计划 并根据订单 库存和资源等因素进行排程 以实现生产资源
  • 【凯子哥带你夯实应用层】滚来滚去,滚来滚去...Scroller相关类使用大揭秘!!!

    转载请注明出处 http blog csdn net zhaokaiqiang1992 话接上文 在前一篇文章里面 咱们一起分析了 知乎 的回答详情页的需求 然后顺便用代码实现了下 忘了的可以再去看看 凯子哥带你夯实应用层 都说 知乎 逼格
  • Dell PowerEdge R710配置raid磁盘阵列

    现有6块硬盘 一块15000转的SAS硬盘做系统盘 三块7500转的SATA硬盘做成raid5 两块7500转的SATA硬盘做成raid0 1 开机按Ctrl R进入BIOS Configuration页面 按Ctrl N切到VD Mgmt
  • 正则表达式匹配任意字符(包括换行符)的写法

    使用 s S 来表示 同理 也可以用 d D 或 w W 来表示
  • Linux下的磁盘克隆、磁盘备份、磁盘还原、分区克隆、分区备份、分区还原

    这里主要介绍一个deepin出大杀器软件 深度备份还原工具是深度科技开发的一款备份还原工具 包括磁盘克隆 磁盘备份 磁盘还原 分区克隆 分区备份 分区还原功能 还可以配合深度Live系统进行修复引导 修复分区等操作 其实这个工具的使用场景是
  • 《Programming in Lua 3》读书笔记(十四)

    日期 2014 7 22Programming in Lua 3 的第二部分已经看完了 现在进入第三部分 标准库的阅读Part The Standard Libraries18 The Mathematical Library标准数学库ma
  • 前后端分离实现审核功能

    一 前言 在实际开发中 审核功能是一个非常常用的功能 例如管理后台的文章审核等等 本篇博文将介绍如何基于SpringBoot Vue的前后端分离技术实现审核功能 二 项目准备 本项目使用的技术栈为 前端 Vue ElementUI 后端 S
  • 【Web3 系列开发教程——创建你的第一个 NFT(6)】为 NFT 设置价格

    我想作为 NFT 的创建者 你可能有意将你的 NFT 出售给你的 NFT 爱好者 为此 我们需要为 NFT 定价 一般有两种主要的定价方式 在智能合约内定价 本文所讲 在 NFT 市场或平台上列出你的 NFT 更流行的方法 在智能合约内设置
  • 03-Mybatis增删改查的简单功能实现

    增删改查的实现 在上文中已经建立了mybatis的环境 并且创建了UserMapper xml userMapper 并且完成了一个简单的查询操作 已经可以成功的运行 环境可以正常的跑起来了 下面对整个数据库的基础操作 增删改查的代码进行编
  • elementUI+Vue+json-server做简单的文章后台管理

    elementUI Vue json server做简单的文章后台管理 最近刚接触elementUI不久 为了加深学习理解 便利用elementUI做了个简单练习 在CSDN上写记录一下学习过程 顺便整理回顾一下整个过程 创建项目 vue
  • Android Broadcast注册、发送、接收流程随笔

    Broadcast的注册过程 要动态注册广播 需要调用registerReceiver方法 它在ContextWrapper中实现 会调用mBase registerReceiver方法 mBase具体指向ContextImpl regis
  • java技术总结

    1 js 中正则表达式写法 var 注意不要加引号 加了引号就是一个字符串 不加引号才是正则对象 var new RegExp 此处不可以有 等效于Java写法 2 关于jquery中的 1 是jquery类 的别称 相当于java中的ob
  • 攻防世界web新手-simple_php

    文章目录 XCTF simple php 知识点 源码分析 解题思路 XCTF simple php 题目编号 GFSJ0485 知识点 本题主要考察php的弱类型比较 源码分析
  • 华为鸿蒙系统无缝更新,华为鸿蒙系统已陆续推送! 安卓系统可无缝升级: 升级包容量高达6GB...

    相信大家都知道 自从华为手机业务遭受到芯片断供危机以后 也是直接将会把重点放在软件系统层面 很多花粉们都纷纷期待 华为鸿蒙OS系统早日转正的一天 而华为终端CEO余承东表示 华为鸿蒙OS系统将会在四月份迎来首次推送升级 而华为Mate X2
  • python split(),os.path.split()和os.path.splitext()函数用法

    文章来源 https blog csdn net T1243 3 article details 80170006 coding utf 8 author lei import os os path join 将分离的部分合成一个整体 fi
  • 订单枚举实例

    摘要 订单状态 public enum OrderState 摘要 不限制 All 0 摘要 待付款 UnPaid 1 摘要 已取消 Cancel 2 摘要 待确认 Process 3
  • 【Linux】网络层 — IP协议

    Linux 博客主页 一起去看日落吗 分享博主的在Linux中学习到的知识和遇到的问题 博主的能力有限 出现错误希望大家不吝赐教 分享给大家一句我很喜欢的话 看似不起波澜的日复一日 一定会在某一天让你看见坚持的意义 祝我们都能在鸡零狗碎里找
  • ServerSocket实现超简单HTTP服务器

    1 相关知识简介 HTTP协议 HTTP是常用的应用层协议之一 是面向文本的协议 HTTP报文传输基于TCP协议 TCP协议包含头部与数据部分 而HTTP则是包含在TCP协议的数据部分 如下图 HTTP报文本质上是一个TCP报文 数据部分携
  • librdkafka的安装和使用

    安装 下载https github com edenhill librdkafka 预备环境 The GNU toolchain GNU make pthreads zlib optional for gzip compression su
  • SSL连接的JAVA实现

    SSL连接分为双向认证和单向认证 其中双向认证表示服务器和客户端都需要分别校验对方的身份 单向认证则只需要客户端校验服务器的身份 SSL的双向认证的流程如下图 从以上流程可见 要完成双向认证 服务器端和客户端都需要验证对方的证书 然后再进行