本文章在CentOS7下操作通過.
多域名證書 , 有兩種配置方式 :
1 . 使用openssl.cnf進行配置
2 . 直接命令行內內置生成
下面使用一個例子 , 來具體說明一下兩種方式的做法 .
一 . 復制並修改openssl配置文件(openssl.cnf)
#CentOS的配置文件在/etc/pki/tls/下 mv /etc/pki/tls/openssl.cnf ./
修改配置文件並保存.
#這3個是取消注釋並修改 copy_extensions = copy req_extensions = v3_req subjectAltName = @alt_names #新增alt_names節點並配置需要的域名和IP [alt_names] DNS.1 = *.org.example.com DNS.2 = *.abc.com IP.1 = 127.0.0.1 IP.2 = 2.0.12.10
二 . 生成根證書(CA) - 使用配置文件方式生成
#生成CA key文件 openssl genrsa -out ca.key 2048 #使用配置文件生成自簽名CA證書 openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \ -subj "/C=CN/ST=ZHEJIANG/L=HANGZHOU/O=WANMA/OU=COMPANY/CN=127.0.0.1" \ -config ./openssl.cnf -extensions v3_req \ -out ca.pem
# 直接命令行生成ca.pem , 該命令可以不用復制openssl.cnf openssl req -x509 -new -nodes -key ./ca.key -sha256 -days 3650 \ -subj "/C=CN/ST=ZHEJIANG/L=HANGZHOU/O=WANMA/OU=COMPANY/CN=127.0.0.1" \ -reqexts SAN \ -config <(cat /etc/pki/tls/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:*.abc.com,IP:0.0.0.0")) \ -out ca.pem
#使用這個命令可以查看生成的CA證書是否支持多域名 openssl x509 -text -in ca.pem -noout
三 . 生成服務器端證書 - 使用配置文件方式生成
#生成Server端 Key文件 openssl genrsa -out server.key 2048 #生成簽名請求 openssl req -new -key ./server.key \ -subj "/C=CN/ST=ZHEJIANG/L=HANGZHOU/O=WANMA/OU=COMPANY/CN=127.0.0.1" \ -config ./openssl.cnf -extensions v3_req \ -out server.csr #使用CA證書簽名Server端證書 openssl x509 -req -in ./server.csr -CA ca.pem -CAkey ca.key -CAcreateserial \ -extfile ./openssl.cnf -extensions v3_req \ -days 3650 -sha256 -out server.pem
#使用這個命令可以查看生成的Server端證書是否支持多域名 openssl x509 -text -in server.pem -noout
四 . 生成客戶端證書 - 使用命令行直接生成
注意 : 配置中的DNS和IP,沒有配置文件中的.1 .2
#生成Client端 Key文件 openssl genrsa -out client.key 2048 #生成簽名請求 - 直接嵌入命令方式 openssl req -new -key ./client.key \ -subj "/C=CN/ST=ZHEJIANG/L=HANGZHOU/O=WANMA/OU=COMPANY/CN=127.0.0.1" \ -reqexts SAN \ -config <(cat /etc/pki/tls/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:*.org.example.com,DNS:*.abc.com,IP:127.0.0.1,IP:2.0.12.10")) \ -out client.csr #使用CA證書簽名Client端證書 openssl x509 -req -in ./client.csr -CA ca.pem -CAkey ca.key -CAcreateserial \ -extensions SAN \ -extfile <(cat /etc/pki/tls/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:*.org.example.com,DNS:*.abc.com,IP:127.0.0.1,IP:2.0.12.10")) \ -days 3650 -sha256 -out client.pem
#使用這個命令可以查看生成的Server端證書是否支持多域名 openssl x509 -text -in client.pem -noout
五 . 轉成jks證書(Java相關的程序使用 , 帶密碼,安全一點)
#CA根證書生成 , 相當於把 ca.pem > ca.jks keytool -import -noprompt -file ca.pem -keystore ca.jks -storepass capassword
#Client證書生成 , 相當於 client.key + client.pem > client.jks #首先需要先轉成p12格式的證書 openssl pkcs12 -export -in client.pem -inkey client.key -out client.p12 -passout pass:clientpassword #把p12證書轉成jks證書 , 密碼就不改了 keytool -importkeystore -srckeystore client.p12 -srcstoretype PKCS12 -destkeystore client.jks -srcstorepass clientpassword -deststorepass clientpassword
六 . Java中調用jks證書例子(以paho.client.mqttv3.MqttClient為例子)
package test.mqtt; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.internal.security.SSLSocketFactoryFactory; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; import java.util.Properties; /** * @author kreo * @description * @date 2020-6-23 23:15:16 */ public class MqttConnection { private final static String broker = "ssl://2.0.12.10:8883"; private final static String clientId = "LOCAL_JAVA_CLIENT"; private final static MemoryPersistence persistence = new MemoryPersistence(); private static MqttClient client; public static MqttClient getClient() { try { if (client == null) { client = new MqttClient(broker, clientId, persistence); // MQTT 連接選項 MqttConnectOptions connOptions = new MqttConnectOptions(); connOptions.setUserName("guest"); connOptions.setPassword("123456".toCharArray()); Properties sslProperties = new Properties(); sslProperties.put(SSLSocketFactoryFactory.KEYSTORE, "/usr/var/certs/client.jks"); sslProperties.put(SSLSocketFactoryFactory.KEYSTOREPWD, "client.wanmagroup.com"); sslProperties.put(SSLSocketFactoryFactory.KEYSTORETYPE, "JKS"); sslProperties.put(SSLSocketFactoryFactory.TRUSTSTORE, "/usr/var/certs/ca.jks"); sslProperties.put(SSLSocketFactoryFactory.TRUSTSTOREPWD, "wanmagroup.com"); sslProperties.put(SSLSocketFactoryFactory.TRUSTSTORETYPE, "JKS"); sslProperties.put(SSLSocketFactoryFactory.CLIENTAUTH, true); connOptions.setSSLProperties(sslProperties); // 保留會話 connOptions.setCleanSession(true); // 設置回調 client.setCallback(new OnMessageCallback()); // 建立連接 System.out.println("嘗試建立連接... Broker >> " + broker); client.connect(connOptions); System.out.println("建立連接成功"); } } catch (MqttException me) { System.out.println("原因代碼 " + me.getReasonCode()); System.out.println("信息 " + me.getMessage()); System.out.println("LOC " + me.getLocalizedMessage()); System.out.println("原因 " + me.getCause()); me.printStackTrace(); } return client; } public static void close() { try { client.disconnect(); System.out.println("斷開連接"); client.close(); System.out.println("連接關閉"); } catch (MqttException me) { System.out.println("原因代碼 " + me.getReasonCode()); System.out.println("信息 " + me.getMessage()); System.out.println("LOC " + me.getLocalizedMessage()); System.out.println("原因 " + me.getCause()); me.printStackTrace(); } } }
-sha256 -days 3650