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 的数字证书的更多相关文章

  1. openssl生成iis需要的pfx格式的证书

    合成.pfx证书 将私钥文件(server.key)和服务器crt证书文件(server.crt ),放到openssl安装目录的bin目录下. 控制台也进到此目录下,然后执行下面指令. openss ...

  2. [openssl] 使用openssl生成证书

    使用openssl生成带域名的证书,SAN,subjectAltName, subject alternative name, DNS. 1. 生成私钥 openssl genrsa - 2. 编写配 ...

  3. 免费CA数字证书的申请、安装、导入、导出

    http://wenku.baidu.com/link?url=oDUw50eCE5zX8tmg4N3-ddYGLt1U5aJYGEN7rk_z7t6LuMHL3M4oBstYBI_dQ1UnCtcK ...

  4. 公私钥 SSH 数字证书

    公私钥 SSH 数字证书 小菜鸟今天买了华为云一台服务器,在使用公私钥远程登录服务器的时候,忘记了相关公钥私钥的原理和一些应用了,今天复习一波做个记录. 相关概念 公钥:公钥用来给数据加密,用公钥加密 ...

  5. 用Keytool和OpenSSL生成和签发数字证书

    一)keytool生成私钥文件(.key)和签名请求文件(.csr),openssl签发数字证书      J2SDK在目录%JAVA_HOME%/bin提供了密钥库管理工具Keytool,用于管理密 ...

  6. OpenSSL生成公钥私钥***

    证书标准 X.509 - 这是一种证书标准,主要定义了证书中应该包含哪些内容.其详情可以参考RFC5280,SSL使用的就是这种证书标准. 编码格式 同样的X.509证书,可能有不同的编码格式,目前有 ...

  7. Golang(十一)TLS 相关知识(二)OpenSSL 生成证书

    0. 前言 接前一篇文章,上篇文章我们介绍了数字签名.数字证书等基本概念和原理 本篇我们尝试自己生成证书 参考文献:TLS完全指南(二):OpenSSL操作指南 1. OpenSSL 简介 OpenS ...

  8. OpenSSL - 网络安全之数据加密和数字证书

    功能应用: 消息摘要,给文件或数据生成消息摘要,消息摘要只能校验数据的完整性,如SHA.MD5 数据加密和解密:对数据进行加密解密,OpenSSL实现了所有加密算法 数字证书:可以通过命令行或代码生成 ...

  9. IIS 使用OpenSSL 生成的自签名证书,然后使用SingalR 客户端访问Https 站点通信

    使用SignalR 的客户端去发送消息给使用 https 部署的站点,官方文档目前并没有详细的教程,所以在此记录下步骤: 使用管理员身份打开cmd 窗口,选择一个整数保存文件夹的地址,切换到对应的文件 ...

  10. OPENSSL生成SSL自签证书

    OPENSSL生成SSL自签证书 目前,有许多重要的公网可以访问的网站系统(如网银系统)都在使用自签SSL证书,即自建PKI系统颁发的SSL证书,而不是部署支持浏览器的SSL证书. 支持浏览器的SSL ...

随机推荐

  1. MFC程序隐藏托盘+右键关闭菜单

    背景介绍: 我的程序是启动后,默认就隐藏到托盘中,等待http请求后,显示界面.所以最小化到托盘的代码,我是写在初始化里面.     正文: 一.自定义消息 WM_SHOWTASK #define W ...

  2. failed to push some refs to xxxx

    ***************ssh  秘钥上传远程仓库 1. 添加远程仓库ssh 命令   git remote add origin  git@github.com:ThreeNut/zou.gi ...

  3. HDD杭州站•ArkUI让开发更灵活

    原文:https://mp.weixin.qq.com/s/cX48CPs61daKOC2J5znyJw,点击链接查看更多技术内容. 7月15日的HUAWEI Developer Day(简称HDD) ...

  4. 鸿蒙HarmonyOS实战-ArkUI组件(Navigation)

    一.Navigation Navigation组件通常作为页面的根容器,支持单页面.分栏和自适应三种显示模式.开发者可以使用Navigation组件提供的属性来设置页面的标题栏.工具栏.导航栏等. 在 ...

  5. c# .net缓存(旧)

    前言 是迁移以前的blog. 关于c# 缓存在web应用中的一个引导,能够建立起一个缓存的基本思路. System.Web.Caching 这个真的是老生常谈了,我们只需要key和iv,然后我们就可以 ...

  6. c# 优化代码的一些规则——判断null值得不同写法[六]

    前言 先来看一个例子: 假设updated 是一个委托: if(updated!=null) { updated(); } 请问上面写法在多线程中安全吗?如果不安全会抛出什么异常呢? 正文 上面的答案 ...

  7. 【转】Java程序员常用工具类库 - 目录

    原文地址:http://rensanning.iteye.com/blog/1553076 有人说当你开始学习Java的时候,你就走上了一条不归路,在Java世界里,包罗万象,从J2SE,J2ME,J ...

  8. gitee基于webhooks实现前端简单自动化部署

    1.为什么采用自动化部署 简而言之,程序员优秀传统:懒 =>高级生产力. 基于gitee进行的自动化部署,服务器环境为Ubuntu 基于webhooks进行的自动化部署更加轻快便捷 2.部署步骤 ...

  9. 1.css的初认识

    1.什么是CSS? Cascading Style Sheet 层叠级联样式表 CSS:表现层(美化网页) 字体.颜色.边距.高度.宽度.背景图片.网页定位.网页浮动.... 2.CSS发展史 CSS ...

  10. 力扣119(java)-杨辉三角Ⅱ(简单)

    题目: 给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex 行. 在「杨辉三角」中,每个数是它左上方和右上方的数的和. 示例 1: 输入: rowIndex = 3输出: [1 ...