openssl 生成多域名 多IP 的数字证书

news/2024/9/19 5:10:06 标签: tcp/ip, microsoft, 网络协议

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;
    }
}

复制代码

 0

 0

« 上一篇: SSL/TSL 总结
» 下一篇: npm 错误,ERESOLVE unable to resolve dependency tree 解决方案


http://www.niftyadmin.cn/n/5665052.html

相关文章

Linux标准IO-系统调用详解

1.1 系统调用 系统调用(system call)其实是 Linux 内核提供给应用层的应用编程接口(API),是 Linux 应用层进入内核的入口。不止 Linux 系统,所有的操作系统都会向应用层提供系统调用,应用程序通…

深入探索Docker核心原理:从Libcontainer到runC的演化与实现

随着容器技术的发展,Docker从早期的Libcontainer逐步演化到runC,推动了容器运行时的标准化进程。Libcontainer是Docker容器的核心管理工具,而runC则在此基础上发展成为符合OCI(Open Container Initiative)标准的轻量级…

Vue2知识点

注意:笔记内容来自网络 1Vue指令 指令是指&#xff1a;带有v-前缀的特殊标签属性 1.1 v-html v-html&#xff08;类似 innerHTML&#xff09; 使用语法&#xff1a;<p v-html"intro">hello</p>&#xff0c;意思是将 intro 值渲染到 p 标签中 类似 i…

Oracle SQL injection(SQL注入)

Oracle SQL注入是一种网络安全漏洞&#xff0c;它允许攻击者在Oracle数据库驱动的Web应用程序中插入或“注入”恶意的SQL代码。这种攻击通常发生在应用程序未能正确验证或清理用户输入的数据时&#xff0c;从而允许攻击者操纵数据库查询&#xff0c;进而获取、修改或删除敏感信…

下拉框QComboBox

文本 // 获取和设置当前条目的索引 int currentIndex() const void setCurrentIndex(int index)// 获取和设置当前条目的文本 QString currentText() const void setCurrentText(const QString &text)// 获取和设置指定索引条目的文本 QString itemText(int index) co…

Maven的高级特性

目录 1. 分模块开发与设计 2. 依赖管理 3. 聚合与继承 4. 多环境配置 5. 使用私服 1. 分模块开发与设计 分模块开发的意义&#xff1a;将一个大的项目拆分成多个子模块&#xff0c;每个模块负责一个单独的功能&#xff0c;可以增加项目的可维护性和可重用性。例如&#xf…

出厂非澎湃OS手机解BL锁

脚本作者&#xff1a;酷安mlgmxyysd 脚本项目链接&#xff1a;https://github.com/MlgmXyysd/Xiaomi-HyperOS-BootLoader-Bypass/ 参考 B站作者&#xff1a;蓝空穹 https://www.bilibili.com/read/cv33210124/ 其他参考&#xff1a;云墨清风、水墨青竹、Magisk中文网 决定解BL…

浅谈Tair缓存的三种存储引擎MDB、LDB、RDB

文章目录 什么是TairTair的三种引擎对比1.MDB2.LDB3.RDB 什么是Tair Tair是阿里巴巴自主研发的高性能、分布式、可扩展、高可靠的 key/value 存储系统。 一般我们可能会认为是阿里开发的加强版Redis&#xff0c;支持双向数据同步&#xff0c;能够很好的支持缓存异地多中心&…