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 ...
随机推荐
- Numpy通用函数及向量化计算
Python(Cpython)对于较大数组的循环操作会比较慢,因为Python的动态性和解释性,在做每次循环时,必须做数据类型的检查和函数的调度. Numpy为很多类型的操作提供了非常方便的.静态类型 ...
- 构筑立体世界,AR Engine助力B站会员购打造沉浸式营销
随着购物场景的逐渐多元化,越来越多电商平台把线下购物体验搬到线上,运用AR技术,跨越空间距离,帮助用户在购买前"体验"商品,增强购买意愿. 哔哩哔哩会员购(后称会员购)是B站于20 ...
- Vue保持用户登录状态(各种token存储方式)
目录 怎么设置Cookie Cookie的缺点: LocalStorage与SessionStorage存储Token LocalStorage与SessionStorage的主要区别: Vuex存储 ...
- nginx重新整理——————http请求的11个阶段中的find_config[十三]
前言 简单介绍一下find_config 与 preaccess 阶段. 正文 find_config 很大一部分工作是进行location的匹配. 来一张图看下location指令和merge_sl ...
- redis 简单整理——redis 的哈希基本结构和命令[三]
前言 简单介绍一下哈希基本结构和命令. 正文 什么是hash呢? hash也可以叫做字典.关联数组. 哈希类型是键本身又是一个键值对结构: value={{field1,value1},...{fie ...
- 一个.NET内置依赖注入的小型强化版
前言 .NET生态中有许多依赖注入容器.在大多数情况下,微软提供的内置容器在易用性和性能方面都非常优秀.外加ASP.NET Core默认使用内置容器,使用很方便. 但是笔者在使用中一直有一个头疼的问题 ...
- @EnableDiscoveryClient 注解如何实现服务注册与发现
@EnableDiscoveryClient 是如何实现服务注册的?我们首先需要了解 Spring-Cloud-Commons 这个模块,Spring-Cloud-Commons 是 Spring-C ...
- C#的基于.net framework的Dll模块编程(一) - 编程手把手系列文章
从此博文开始分几篇介绍C#的开发.这次讲讲C#的.net framework的Dll文件类库模块的编程方法. 对于Windows来说,要运行应用程序要基于Dll类库和Exe执行文件.对于笔者来说,模块 ...
- 通过ORPO技术微调 llama3大模型(Fine-tune Llama 3 with ORPO)
1f45bd1e8577af66a05f5e3fadb0b29 通过ORPO对llama进行微调 前言 ORPO是一种新颖的微调技术,它将传统的监督微调和偏好对齐阶段整合到一个过程中.这减少了训练所需 ...
- 力扣1083(MySQL)-销售分析Ⅲ(简单)
题目: Table: Product Table: Sales 编写一个SQL查询,报告2019年春季才售出的产品.即仅在2019-01-01至2019-03-31(含)之间出售的商品. 以 任意顺序 ...