IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> OpenSSL 证书 -> 正文阅读

[网络协议]OpenSSL 证书

目录

证书标准

编码格式

PEM: Privacy Enhanced Mail

DER: Distinguished Encoding Rules

编码转换:

?文件扩展名

自签证书

签发根证书

?生成CA私钥

生成CA申请文件

签发根证书

?导出Java的CA证书

签发服务端证书

签发客户端证书


证书标准

X.509 数字证书标准,定义证书文件的结构和内容。

证数结构图:

编码格式

证书的编码格式:一般包括 PEM 和 DER 两种。

PEM: Privacy Enhanced Mail

DER: Distinguished Encoding Rules

编码转换:

PEM转DER
openssl x509 -in xxx.pem -outform der -out xxx.der

?DER转PEM
openssl x509 -in xxx.der -inform der -outform pem -out xxx.pem

文件扩展名

自签证书

签发根证书

?生成CA私钥

//生成CA私钥:
# openssl genrsa -des3 -out cakey.pem 2048
输入密码:Honeywell@654321

// 查看CA私钥
# openssl rsa -in cakey.pem -text

生成CA申请文件

//根据私钥生成CA申请文件:
# openssl req -new -key cakey.pem -out ca.csr -subj "/C=CN/O=Honeywell/CN=WCS Project(rabbitmq)"
 
//查看CA申请文件
# openssl req -noout -text -in ca.csr

签发根证书

//签发根证书:
# openssl x509 -req -days 3650 -sha1 -extfile /etc/pki/tls/openssl.cnf -extensions v3_ca -signkey cakey.pem -in ca.csr -out ca.cer
 
// 查看证书
# openssl x509 -in ca.cer -text -noout

?

导出p12的CA证书?

openssl pkcs12 -export -clcerts -in ca.cer -inkey cakey.pem -out ca.p12

?导出JKS的CA证书

//导出服务端java程序可用的CA证书:
keytool -import -v -trustcacerts -storepass Honeywell@654321 -alias root -file ca.cer -keystore ca.jks

签发服务端证书

//服务端私钥
openssl genrsa -des3 -out server-key.pem 2048

// 查看私钥
openssl rsa -in server-key.pem -text
 
//服务端申请文件
openssl req -new -key server-key.pem -out server.csr -subj "/C=CN/O=Honeywell/CN=WCS Project(rabbitmq)"
 
//使用根证书签发服务端证书
openssl x509 -req -days 3650 -sha1 -extfile /etc/pki/tls/openssl.cnf -extensions v3_req -CA ca.cer -CAkey cakey.pem -CAserial ca.srl -CAcreateserial -in server.csr -out server.cer
 
//导出服务端p12证书:
openssl pkcs12 -export -clcerts -inkey server-key.pem -in server.cer -out server.p12

//导出服务端java程序可用的JKS证书
keytool -import -v -trustcacerts -storepass Honeywell@654321 -alias server -file ca.cer -keystore server.jks

签发客户端证书

//私钥
openssl genrsa -des3 -out client-key.pem 2048
// 查看私钥
openssl rsa -in client-key.pem -text
 
//客户端申请文件:
openssl req -new -key client-key.pem -out client.csr -subj "/C=CN/O=Honeywell/CN=WCS Project(rabbitmq)"
//查看申请文件
openssl req -text -noout -verify -in client.csr
 
//使用根证书签发客户端证书:
openssl x509 -req -days 3650 -sha256 -extfile /etc/pki/tls/openssl.cnf -extensions v3_req -CA ca.cer -CAkey cakey.pem -CAserial ca.srl -in client.csr -out client.cer
//查看证书
openssl x509 -in client.cer -text -noout
 
导出客户端证书:
openssl pkcs12 -export -clcerts -name wcsclient -inkey client-key.pem -in client.cer -out client.p12
// 查看p12证书
openssl pkcs12 -info -in client.p12
 
//p12导入至keystore
keytool -import -v -trustcacerts -storepass Honeywell@654321 -alias client -file client.cer -keystore client.jks

//查看keystore
keytool -v -list -keystore client.jks

合并证书

合并server.crt和ca.crt

-----BEGIN CERTIFICATE-----

...ca.crt的内容

-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----

...server.crt的内容

-----END CERTIFICATE-----

转换为pkcs12格式

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

转换为jks格式

keytool -importkeystore -srckeystore server.p12 -destkeystore server.jks -srcstoretype pkcs12 -deststoretype jks

验证证书

keytool -list -v -keystore server.jks

KeyStore

KeyStore是一个存储库,可用于存储一系列密钥、密钥对或证书。

KeyStore的实现方式:JKS(Java Key Store)、PKCS12、JCEKS
JKS:? ? ? ? 可以存储密钥对、证书,不能存储密钥。
PKCS12: 可以存储密钥对、证书、密钥。
JCEKS:? ?可以存储密钥对、证书、密钥。

keytool

keytool是JDK的Keystore管理工具。

JAVA代码

服务端:

package com.xxx.yyy.common.socket.utils;

import cn.hutool.json.JSONUtil;
import com.xxx.yyy.common.socket.config.SocketServerTLSConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.*;
import java.security.cert.CertificateException;

/**
 * keystore用于存放自己的密钥和公钥,
 * truststore用于存放所有需要信任方的公钥
 * SSLContext:SSLContext类可以创建SSLSocket实例,在这个类中配置自己的证书和自己所信任的证书。
 * KeyManagerFactory:加载自己的证书文件,并且生成KeyManager[]数据,配置到SSLContext。
 * TrustManagerFactory:加载自己信任的客户端证书,双向认证的时候配置自己信任哪些服务端证书。
 * KeyStore:加载证书的类。
 * TrustManager[]:信任的证书信任的Manager数组。
 * Manager[]:自己的证书的Manager数组。
 *
 * @author H443745
 */
public class SslSocketServerUtil {
    private static final Logger logger = LoggerFactory.getLogger(SslSocketServerUtil.class);

    private static final String PROTOCOL = "TLSv1.2";
    public static final String KEYSTORE_TYPE = "JKS";
    //KeyStore的类型
    private static final String PROVIDER = "SunX509";

    private SslSocketServerUtil() {
    }

    /**
     * 创建服务端socket
     *
     * @param tlsConfig
     * @return
     * @throws Exception
     */
    public static SSLServerSocket createSslServerSocket(SocketServerTLSConfig tlsConfig) throws IOException {
        SSLContext sslContext = createContext(tlsConfig);
        if (sslContext == null) {
            return null;
        }
        SSLServerSocketFactory serverSocketFactory = sslContext.getServerSocketFactory();
        // 绑定服务端口
        SSLServerSocket serverSocket = (SSLServerSocket) serverSocketFactory.createServerSocket(tlsConfig.getPort());
        // 设置加密算法套件
        String[] supported = serverSocketFactory.getSupportedCipherSuites();
        serverSocket.setEnabledCipherSuites(supported);
        logger.info("服务端可支持的加密算法套件有:{}", supported);

        //设置这个SSLServerSocket需要授权的客户端访问, 是否开启双向验证
        serverSocket.setNeedClientAuth(tlsConfig.isServerModeEnabled());

        return serverSocket;
    }

    /**
     * 创建上下文环境,主要用于保存安全通信的基本信息,如协议版本、证书管理方式
     *
     * @param tlsConfig
     * @return
     * @throws Exception
     */
    public static SSLContext createContext(SocketServerTLSConfig tlsConfig) {
        logger.info("开始服务端创建sslContext上下文......");

        //服务端证书库
        KeyStore serverKeystore = null;
        FileInputStream fileInputStream = null;

        KeyStore trustKeystore = null;
        FileInputStream trustFileInputStream = null;

        try {
            serverKeystore = KeyStore.getInstance(KEYSTORE_TYPE);
            fileInputStream = new FileInputStream(tlsConfig.getServerKeystorePath());
            serverKeystore.load(fileInputStream, tlsConfig.getServerKeystorePassword().toCharArray());

            /// KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            //生成秘钥的manager
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(PROVIDER);
            // 管理本端 的密钥(发送本端的证书用于对方认证我的身份)
            logger.info(KeyManagerFactory.getDefaultAlgorithm());

            //秘钥初始化
            kmf.init(serverKeystore, tlsConfig.getServerKeystorePassword().toCharArray());

            SSLContext sslContext = SSLContext.getInstance(PROTOCOL);
            logger.info("缺省安全套接字使用的协议:{} ", sslContext.getProtocol());

            //是否双向验证
            boolean serverModeEnabled = tlsConfig.isServerModeEnabled();
            if(serverModeEnabled){
                // 管理对端证书的信任证书,用于认证对方的身份
                trustKeystore = KeyStore.getInstance(KEYSTORE_TYPE);
                trustFileInputStream = new FileInputStream(tlsConfig.getServerTrustKeystorePath());
                trustKeystore.load(trustFileInputStream, tlsConfig.getServerTrustKeystorePassword().toCharArray());

                // 信任库
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(PROVIDER);
                // 信任证书和服务端私钥 放在同一个库里
                tmf.init(trustKeystore);
                // 上下文初始化,双向,两端证书的加载
                sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
            } else {
                // 上下文初始化,单向
                sslContext.init(kmf.getKeyManagers(), null, null);
            }

            logger.info("上下文信息:{}", sslContext.getProtocol());
            logger.info("支持的协议:{}", JSONUtil.toJsonStr(sslContext.getSupportedSSLParameters().getProtocols()));


            return sslContext;
        } catch (KeyStoreException | KeyManagementException | NoSuchAlgorithmException | UnrecoverableKeyException |
                 CertificateException | IOException e) {
            logger.info("Exception");
            e.printStackTrace();
        } finally {
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (trustFileInputStream != null) {
                try {
                    trustFileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }

}

客户端:

package com.xxx.yyy.common.socket.utils;

import com.xxx.yyy.common.socket.config.SocketClientTLSConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;

/**
 * @author H443745
 */
public class SslSocketClientUtil {
    private static final Logger logger = LoggerFactory.getLogger(SslSocketClientUtil.class);

    public static final String PROTOCOL = "TLSv1.2";
    public static final String KEYSTORE_TYPE = "JKS";

    private static final String PROVIDER = "SunX509";

    private SslSocketClientUtil() {
    }

    public static SSLContext createSslContext(SocketClientTLSConfig tlsClientConfig) {

        //客户端证书库
        FileInputStream fileInputStream = null;
        KeyStore clientKeystore = null;

        //信任证书库
        FileInputStream trustFileInputStream = null;
        KeyStore trustKeystore = null;

        try {
            //信任证书库
            trustKeystore = KeyStore.getInstance(KEYSTORE_TYPE);
            trustFileInputStream = new FileInputStream(tlsClientConfig.getClientTrustKeystorePath());
            trustKeystore.load(trustFileInputStream, tlsClientConfig.getClientTrustKeystorePassword().toCharArray());

            //信任库
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(PROVIDER);
            tmf.init(trustKeystore);

            //初始化SSL上下文
            SSLContext ctx = SSLContext.getInstance(PROTOCOL);
            logger.info("缺省安全套接字使用的协议:{} ", ctx.getProtocol());

            //是否双向验证
            boolean clientModeEnabled = tlsClientConfig.isClientModeEnabled();
            if(clientModeEnabled){
                //客户端证书库
                clientKeystore = KeyStore.getInstance(KEYSTORE_TYPE);
                fileInputStream = new FileInputStream(tlsClientConfig.getClientKeystorePath());
                clientKeystore.load(fileInputStream, tlsClientConfig.getClientKeystorePassword().toCharArray());

                // 密钥库
                /// KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
                KeyManagerFactory kmf = KeyManagerFactory.getInstance(PROVIDER);
                kmf.init(clientKeystore, tlsClientConfig.getClientKeystorePassword().toCharArray());

                ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
            } else{
                ctx.init(null, tmf.getTrustManagers(), null);
            }

            return ctx;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("failed to load KeyStore.", e);
        } finally {
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (trustFileInputStream != null) {
                try {
                    trustFileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }

    @SuppressWarnings("unchecked")
    public static SSLSocketFactory createSocketFactory(SocketClientTLSConfig tlsClientConfig) {
        SSLContext sslContext = createSslContext(tlsClientConfig);
        if (sslContext == null) {
            logger.error("failed to create SSLSocketFactory.");
            return null;
        }
        logger.info("Protocol:{}", sslContext.getProtocol());
        return sslContext.getSocketFactory();
    }

    public static SSLSocket createSocket(SocketClientTLSConfig tlsClientConfig, String host, int port, HostnameVerifier hostnameVerifier) throws SSLException {
        SSLSocketFactory ssf = createSocketFactory(tlsClientConfig);
        if (ssf == null) {
            logger.error("SSLSocketFactory should not be null.");
            return null;
        }

        SSLSocket socket = null;
        try {
            socket = (SSLSocket) ssf.createSocket(host, port);
            // TODO-WANG later need TLSv1.3
            // socket.setEnabledProtocols(new String[]{"TLSv1.3"});
            socket.setSoTimeout(10000);
        } catch (IOException e) {
            logger.error("failed to createSocket, host={}, port={}", host, port, e);
        }

        if (socket == null) {
            logger.error("SSLSocketFactory not created.");
            return null;
        }
        if (hostnameVerifier != null && !hostnameVerifier.verify(socket.getInetAddress().getHostName(), socket.getSession())) {
            throw new SSLException("\"" + socket.getInetAddress().getHostName() + "\" identity was not confirmed");
        }

        return socket;
    }
}

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 13:08:02  更:2022-10-17 13:11:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 7:06:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码