openssl 生成多域名 多IP 的数字证书
openssl.cnf 文件内容:
[req]
default_bits = 2048
distinguished_name = req_distinguished_name
copy_extensions = copy
req_extensions = req_ext
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
countryName = CN
stateOrProvinceName = GuangDong
localityName = ShenZhen
organizationName = lc
commonName = CA
[req_ext]
basicConstraints = CA:FALSE
subjectAltName = @alt_names
[v3_req]
basicConstraints = CA:FALSE
subjectAltName = @alt_names
[alt_names]
IP.1 = 192.168.10.31
IP.2 = 192.168.10.32
IP.3 = 192.168.10.33
DNS.1 = 192.168.10.2
DNS.2 = 202.96.134.133
生成证书
工具是用的:windows平台 Win64OpenSSL-3_2_0.exe 或 Win64OpenSSL_Light-3_2_0.exe (建议用:Win64OpenSSL-3_2_0.exe )
OpenSSL 3.2.0 23 Nov 2023 (Library: OpenSSL 3.2.0 23 Nov 2023)
根证书:
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.pem -subj "/C=CN/ST=GuangDong/O=EMQX/CN=Client"
服务端证书:
openssl genrsa -out emqx.key 2048
openssl req -new -key emqx.key -config openssl.cnf -out emqx.csr
openssl x509 -req -in emqx.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out emqx.pem -days 3650 -sha256 -extensions v3_req -extfile openssl.cnf
客户端证书:
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr -subj "/C=CN/ST=GuangDong/O=EMQX/CN=Client"
openssl x509 -req -days 3650 -in client.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out client.pem
校验证书的有效性:
openssl verify -CAfile ca.pem emqx.pem
openssl verify -CAfile ca.pem client.pem
常见错误:
Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: IP: 192.168.10.32 is not in the cert's list:
Error: self signed certificate in certificate chain
Error: Connection refused: Not authorized # 没有设置用户名密码
Error: unable to verify the first certificate
加密认证算法:
package com.lc.common.mqtt.utils; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import java.io.*;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory; /**
* @author Charley
* @date 2022/12/05
* @description
*/
@Component
public class SSLUtils { @javax.annotation.Resource
private ResourceLoader resourceLoader; public SSLSocketFactory getSingleSocketFactory(InputStream caCrtFileInputStream) throws Exception {
Security.addProvider(new BouncyCastleProvider());
X509Certificate caCert = null; BufferedInputStream bis = new BufferedInputStream(caCrtFileInputStream);
CertificateFactory cf = CertificateFactory.getInstance("X.509"); while (bis.available() > 0) {
caCert = (X509Certificate) cf.generateCertificate(bis);
}
KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
caKs.load(null, null);
caKs.setCertificateEntry("cert-certificate", caCert);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(caKs);
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, tmf.getTrustManagers(), null);
return sslContext.getSocketFactory();
} public SSLSocketFactory getSocketFactory(final String caCrtFile,
final String crtFile, final String keyFile, final String password)
throws Exception { Security.addProvider(new BouncyCastleProvider()); // load CA certificate
X509Certificate caCert = null; // FileInputStream fis = new FileInputStream(caCrtFile);
BufferedInputStream bis = new BufferedInputStream(resourceLoader.getResource(caCrtFile).getInputStream()); CertificateFactory cf = CertificateFactory.getInstance("X.509"); while (bis.available() > 0) {
caCert = (X509Certificate) cf.generateCertificate(bis);
} // load client certificate //bis = new BufferedInputStream(new FileInputStream(crtFile));
bis = new BufferedInputStream(resourceLoader.getResource(crtFile).getInputStream());
X509Certificate cert = null;
while (bis.available() > 0) {
cert = (X509Certificate) cf.generateCertificate(bis);
} // load client private key
// PEMParser pemParser = new PEMParser(new FileReader(keyFile));
// Object object = pemParser.readObject();
// JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
// KeyPair key = converter.getKeyPair((PEMKeyPair) object);
// pemParser.close(); // PEMParser pemParser =new PEMParser(new InputStreamReader(new FileInputStream(keyFile))); PEMParser pemParser =new PEMParser(new InputStreamReader(resourceLoader.getResource(keyFile).getInputStream())); Object obj = pemParser.readObject();
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
PrivateKey privateKey = converter.getPrivateKey((PrivateKeyInfo) obj); // CA certificate is used to authenticate server
KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
caKs.load(null, null);
caKs.setCertificateEntry("ca-certificate", caCert);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(caKs); // client key and certificates are sent to server, so it can authenticate
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
ks.setCertificateEntry("certificate", cert);
ks.setKeyEntry("private-key", privateKey, password.toCharArray(),
new java.security.cert.Certificate[]{cert});
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
.getDefaultAlgorithm());
kmf.init(ks, password.toCharArray()); // finally, create SSL socket factory
SSLContext context = SSLContext.getInstance("TLSv1.2");
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); return context.getSocketFactory();
}
}
mqq5:
package com.lc.common.mqtt.mqttv5; import cn.hutool.core.util.IdUtil;
import com.lc.common.mqtt.config.MqttConfig;
import com.lc.common.mqtt.utils.SSLUtils;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.mqttv5.client.MqttConnectionOptions;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.outbound.Mqttv5PahoMessageHandler;
import org.springframework.integration.mqtt.support.MqttHeaderMapper;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import javax.annotation.Resource; @Configuration
@Slf4j
public class Mqtt5Client { @Resource
MqttConfig mc;
@Resource
private SSLUtils sslUtils;
@Resource
private Mqtt5MessageReceiver mqttMessageReceiver; /**
* (生产者) mqtt消息出站通道,用于发送出站消息
* @return
*/
@Bean
public MessageChannel mqttOutputChannel5() {
return new DirectChannel();
} /**
* (消费者) mqtt消息入站通道,订阅消息后消息进入的通道。
* @return
*/
@Bean
public MessageChannel mqttInputChannel5() {
return new DirectChannel();
} public MqttConnectionOptions getOptions() {
MqttConnectionOptions options = new MqttConnectionOptions();
options.setServerURIs(mc.getServices());
options.setUserName(mc.getUser());
options.setPassword(mc.getPassword().getBytes());
options.setReceiveMaximum(mc.getMaxInflight());
options.setKeepAliveInterval(mc.getKeepAliveInterval());
// 重连设置
options.setAutomaticReconnect(mc.isAutomaticReconnect());
options.setMaxReconnectDelay(mc.getMaxReconnectDelay());
options.setAutomaticReconnectDelay(mc.getV5AutomaticReconnectMinDelay(), mc.getV5AutomaticReconnectMaxDelay());
// 会话设置
options.setCleanStart(mc.isV5CleanStart());
options.setSessionExpiryInterval(mc.getV5SessionExpiryInterval());
// 超时设置
options.setConnectionTimeout(mc.getConnectionTimeout());
try {
options.setSocketFactory(sslUtils.getSocketFactory(
"classpath:ca.pem",
"classpath:client.pem",
"classpath:client.key",
""));
} catch (Exception e) {
e.printStackTrace();
}
return options;
} /**
* 生产者
* @return
*/
@Bean
@ServiceActivator(inputChannel = "mqttOutputChannel5")
public MessageHandler mqttOutbound5() {
String clientId = mc.getV5ProducerId() + "_" + IdUtil.getSnowflakeNextId();;
Mqttv5PahoMessageHandler messageHandler = new Mqttv5PahoMessageHandler(getOptions(), clientId);
messageHandler.setHeaderMapper(new MqttHeaderMapper());
// 设置异步不阻塞
messageHandler.setAsync(false);
// 设置Qos
messageHandler.setDefaultQos(mc.getQos());
return messageHandler;
} /**
* MQTT消息订阅绑定(消费者)
* @return
*/
@Bean
public MessageProducer channelInbound5(MessageChannel mqttInputChannel5) {
String clientId = mc.getV5ConsumerId() + "_" + IdUtil.getSnowflakeNextId();;
MyMqttv5PahoMessageDrivenChannelAdapter adapter = new MyMqttv5PahoMessageDrivenChannelAdapter(getOptions(), clientId, mc.getV5DefaultTopic());
adapter.setCompletionTimeout(mc.getCompletionTimeout());
adapter.setPayloadType(String.class);
adapter.setQos(mc.getQos());
adapter.setOutputChannel(mqttInputChannel5);
return adapter;
} /**
* MQTT消息处理器(消费者)
* @return
*/
@Bean
@ServiceActivator(inputChannel = "mqttInputChannel5")
public MessageHandler mqttMessageHandler5() {
return mqttMessageReceiver;
}
}
mqtt3
package com.lc.common.mqtt.mqttv3; import cn.hutool.core.util.IdUtil;
import com.lc.common.mqtt.utils.SSLUtils;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import com.lc.common.mqtt.config.MqttConfig;
import javax.annotation.Resource; @Configuration
@Slf4j
public class Mqtt3Client {
@Resource
private MqttConfig mc; @Resource
private SSLUtils sslUtils; @Resource
private Mqtt3MessageReceiver mqttMessageReceiver; /**
* (生产者) mqtt消息出站通道,用于发送出站消息
* @return
*/
@Bean
public MessageChannel mqttOutputChannel3() {
return new DirectChannel();
} /**
* (消费者) mqtt消息入站通道,订阅消息后消息进入的通道。
* @return
*/
@Bean
public MessageChannel mqttInputChannel3() {
return new DirectChannel();
} public MqttConnectOptions getOptions() {
MqttConnectOptions options = new MqttConnectOptions();
options.setServerURIs(mc.getServices());
options.setUserName(mc.getUser());
options.setPassword(mc.getPassword().toCharArray());
options.setMaxInflight(mc.getMaxInflight());
options.setKeepAliveInterval(mc.getKeepAliveInterval());
// 重连设置
options.setAutomaticReconnect(mc.isAutomaticReconnect());
options.setMaxReconnectDelay(mc.getMaxReconnectDelay());
// options.setAutomaticReconnectDelay(automaticReconnectMinDelay, automaticReconnectMaxDelay);
// 会话设置
options.setCleanSession(mc.isV3CleanSession()); // 超时设置
options.setConnectionTimeout(mc.getConnectionTimeout());
// 设置遗嘱消息 qos 默认为 1 retained 默认为 false
options.setWill("willTopic","与服务器断开连接".getBytes(),0,false);
try {
options.setSocketFactory(sslUtils.getSocketFactory(
"classpath:ca.pem",
"classpath:client.pem",
"classpath:client.key",
""));
} catch (Exception e) {
e.printStackTrace();
}
return options;
} /**
* 生产者
* @return
*/
@Bean
@ServiceActivator(inputChannel = "mqttOutputChannel3")
public MessageHandler mqttOutbound3() {
String clientId = mc.getV3ProducerId() + "_" + IdUtil.getSnowflakeNextId();
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory() ;
factory.setConnectionOptions(getOptions());
MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(clientId, factory);
// 设置异步不阻塞
messageHandler.setAsync(true);
// 设置Qos
messageHandler.setDefaultQos(mc.getQos());
return messageHandler;
} /**
* MQTT消息订阅绑定(消费者)
* @return
*/
@Bean
public MessageProducer channelInbound3(MessageChannel mqttInputChannel3) {
String clientId = mc.getV3ConsumerId() + "_" + IdUtil.getSnowflakeNextId();;
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
factory.setConnectionOptions(getOptions());
MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(clientId, factory, mc.getV3DefaultTopic());
adapter.setCompletionTimeout(mc.getCompletionTimeout());
adapter.setRecoveryInterval(mc.getV3RecoveryInterval());
adapter.setConverter(new DefaultPahoMessageConverter());
adapter.setQos(mc.getQos());
adapter.setOutputChannel(mqttInputChannel3);
return adapter;
} /**
* MQTT消息处理器(消费者)
* @return
*/
@Bean
@ServiceActivator(inputChannel = "mqttInputChannel3")
public MessageHandler mqttMessageHandler3() {
return mqttMessageReceiver;
}
}
openssl 生成多域名 多IP 的数字证书的更多相关文章
- openssl生成iis需要的pfx格式的证书
合成.pfx证书 将私钥文件(server.key)和服务器crt证书文件(server.crt ),放到openssl安装目录的bin目录下. 控制台也进到此目录下,然后执行下面指令. openss ...
- [openssl] 使用openssl生成证书
使用openssl生成带域名的证书,SAN,subjectAltName, subject alternative name, DNS. 1. 生成私钥 openssl genrsa - 2. 编写配 ...
- 免费CA数字证书的申请、安装、导入、导出
http://wenku.baidu.com/link?url=oDUw50eCE5zX8tmg4N3-ddYGLt1U5aJYGEN7rk_z7t6LuMHL3M4oBstYBI_dQ1UnCtcK ...
- 公私钥 SSH 数字证书
公私钥 SSH 数字证书 小菜鸟今天买了华为云一台服务器,在使用公私钥远程登录服务器的时候,忘记了相关公钥私钥的原理和一些应用了,今天复习一波做个记录. 相关概念 公钥:公钥用来给数据加密,用公钥加密 ...
- 用Keytool和OpenSSL生成和签发数字证书
一)keytool生成私钥文件(.key)和签名请求文件(.csr),openssl签发数字证书 J2SDK在目录%JAVA_HOME%/bin提供了密钥库管理工具Keytool,用于管理密 ...
- OpenSSL生成公钥私钥***
证书标准 X.509 - 这是一种证书标准,主要定义了证书中应该包含哪些内容.其详情可以参考RFC5280,SSL使用的就是这种证书标准. 编码格式 同样的X.509证书,可能有不同的编码格式,目前有 ...
- Golang(十一)TLS 相关知识(二)OpenSSL 生成证书
0. 前言 接前一篇文章,上篇文章我们介绍了数字签名.数字证书等基本概念和原理 本篇我们尝试自己生成证书 参考文献:TLS完全指南(二):OpenSSL操作指南 1. OpenSSL 简介 OpenS ...
- OpenSSL - 网络安全之数据加密和数字证书
功能应用: 消息摘要,给文件或数据生成消息摘要,消息摘要只能校验数据的完整性,如SHA.MD5 数据加密和解密:对数据进行加密解密,OpenSSL实现了所有加密算法 数字证书:可以通过命令行或代码生成 ...
- IIS 使用OpenSSL 生成的自签名证书,然后使用SingalR 客户端访问Https 站点通信
使用SignalR 的客户端去发送消息给使用 https 部署的站点,官方文档目前并没有详细的教程,所以在此记录下步骤: 使用管理员身份打开cmd 窗口,选择一个整数保存文件夹的地址,切换到对应的文件 ...
- OPENSSL生成SSL自签证书
OPENSSL生成SSL自签证书 目前,有许多重要的公网可以访问的网站系统(如网银系统)都在使用自签SSL证书,即自建PKI系统颁发的SSL证书,而不是部署支持浏览器的SSL证书. 支持浏览器的SSL ...
随机推荐
- Seaborn线性关系数据可视化
regplot() 绘制两个变量的线性拟合图. sns.regplot( x, y, data=None, x_estimator=None, x_bins=None, x_ci='ci', scat ...
- Kalman滤波器的原理与实现
Kalman滤波器的原理与实现 卡尔曼滤波器(Kalman Filter)是一个十分强大滤波器,虽然叫做滤波器,卡尔曼滤波器其实可以起到到两个作用,即预测与更新,这与我们在其运行时所关注的环节有关.当 ...
- HDC2021技术分论坛:DevEco Testing,新增分布式测试功能
作者:lixiao,华为终端软件测试首席架构师:mindelong,华为终端软件测试工程师 HarmonyOS自诞生以来,致力于提供全场景智慧解决方案,打造分布式流转.多设备协同的分布式体验.全新解决 ...
- CentOS 编译安装golang
一.下载go wget https://studygolang.com/dl/golang/go1.16.4.linux-amd64.tar.gz 二.解压到指定目录 tar -xvf go1.16. ...
- 文本溢出显示省略号css
项目中常常有这种需要我们对溢出文本进行"..."显示的操作,单行多行的情况都有(具体几行得看设计师心情了),这篇随笔是我个人对这种情况解决办法的归纳,欢迎各路英雄指教. 单行 语法 ...
- 容器基础-- namespace,Cgroup 和 UnionFS
Namespace 什么是 Namespace ? 这里的 "namespace" 指的是 Linux namespace 技术,它是 Linux 内核实现的一种隔离方案.简而言之 ...
- 【Oracle】 管道函数pipelined function简单的使用
Oracle 管道函数pipelined function简单的使用 如果在函数(function)中加关键字 pipelined,就表明这是一个oracle管道函数,其返回值类型必为 集合,体现出来 ...
- 力扣596(MySQL)-超过5名学生的课(简单)
题目: 表: Courses 编写一个SQL查询来报告 至少有5个学生 的所有班级. 以 任意顺序 返回结果表. 查询结果格式如下所示 示例1: 解题思路: 使用group by按 班级 进行分组后 ...
- 力扣278(java&python)-第一个错误的版本(简单)
题目: 你是产品经理,目前正在带领一个团队开发新的产品.不幸的是,你的产品的最新版本没有通过质量检测.由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的. 假设你有 n 个版本 ...
- 一文剖析PolarDB HTAP的列存数据压缩
简介: PolarDB MySQL是阿里云自研的云原生数据库,主要处理在线事务负载(OLTP, OnLine Transactional Processing),深受企业用户的青睐. 前言 数据库迁移 ...