SSL单_双向证书

openSSL 安装

下载地址

https://slproweb.com/products/Win32OpenSSL.html

# github地址
https://github.com/openssl/openssl/tags

Nginx

SSL 单向认证

# 生成加密的私钥[private.key/private.pem]
openssl genrsa -des3 -out [private.key/private.pem] 4096
# openssl genrsa:表示要执行 OpenSSL 的 RSA 密钥对生成操作。
# -des3:表示加密算法
# -out private.key/private.pem:指定了生成的私钥文件的输出路径和文件名,这里是 my-key.pem,表示当前目录是根目录,生成私钥文件的名字是my-key.pem。
# 4096:指定了生成的私钥的长度为 4096 位。RSA 密钥对的安全性与密钥长度密切相关。

# 生成证书签名请求 (CSR)[certificate.csr/certificate.pem]
openssl req -new -key [private.key/private.pem] -out [certificate.csr/certificate.pem] -passin pass:giraffe -subj "/C=CN/ST=ShangHai/L=ShangHai/O=MyCompany/OU=IT/CN=www.test.com/emailAddress=1183711908@qq.com"
# openssl req:表示要执行 OpenSSL 的证书请求(req)操作。
# -new:表示生成一个新的证书请求。
# -key private.key/private.pem:指定了私钥文件的路径和文件名,证书请求需要使用私钥进行加密,因此需要指定私钥文件的位置。
# -out certificate.csr/certificate.pem:指定了生成的证书签名请求(CSR)的输出文件路径和文件名,生成的 CSR 文件包含了公钥以及与证书相关的信息,用于向证书颁发机构申请签发数字证书。
# -passin pass:giraffe:表示需要验证的私钥的密码
# -subj:指定证书所有者的信息、证书颁发机构的信息

# 生成自签名证书[certificate.crt/certificate.pem]
openssl req -x509 -days 3650 -in [certificate.csr/certificate.pem] -key [private.key/private.pem] -passin pass:giraffe -out [certificate.crt/certificate.pem]
# openssl req:表示要执行 OpenSSL 的证书请求(req)操作。
# -x509:表示生成自签名证书而不是证书签名请求(CSR)。X.509是一种公钥基础设施(PKI)标准,用于数字证书的格式和结构。X.509证书包含了公钥、证书所有者的信息、证书颁发机构的信息以及数字签名等内容,用于实现安全通信和验证身份。
# -days 3650:指定证书的有效期为3650天,即十年。
# -key private.key/private.pem:指定了私钥文件的路径和文件名。
# -in certificate.csr/certificate.pem:指定了证书签名请求(CSR)文件的路径和文件名。
# -out certificate.crt/certificate.pem:指定了生成的自签名证书的输出文件路径和文件名。生成的自签名证书包含了公钥、证书信息以及使用私钥签名后的数字签名。


# 生成不带密码保护的私钥(移除证书中的密码)
openssl rsa -in private.key -passin pass:giraffe -out private_no_passphrase.key

# 验证生成的证书
openssl x509 -in certificate.crt -text -noout

# 验证私钥内容
openssl rsa -in private_no_passphrase.key -check

# 验证CSR内容
openssl req -text -noout -verify -in certificate.csr

# =================nginx 配置=================
http {
    server {
      listen       443 ssl; 
  		# ssl证书地址,指定文件路径和私钥路径
      ssl_certificate     /etc/cert/certificate.crt;
      ssl_certificate_key /etc/cert/private_no_passphrase.key;
  		ssl_session_timeout  30m;
  		ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
  		ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  		ssl_prefer_server_ciphers on;
    }
}
# =================apache httpd配置=================
listen 7443
<VirtualHost *:7443>
    ServerName 127.0.0.1
    SSLEngine on
    SSLProtocol all -SSLv2 -SSLv3
    SSLCipherSuite HIGH:3DES:!aNULL:!MD5:!SEED:!IDEA
    SSLCertificateFile          certificate.crt
    SSLCertificateKeyFile       private_no_passphrase.key
    DocumentRoot /home/admin/html
    
    <Proxy *>      
      Allow from all  
    </Proxy>
    
    <Directory /home/admin/html>
            Require all granted
    </Directory>
    
    <Location /-api/>
            Header unset x-frame-options
            Header always append x-frame-options SAMEORIGIN
            ProxyPass          https://localhost:17443/
            ProxyPassReverse   https://localhost:17443/
    </Location>
    
</VirtualHost>

SSL 双向认证生成

#步骤1:创建根证书
#步骤1.1:创建根证书私钥: 				root.key: 根证书私钥文件
openssl genrsa -out root.key 2048
#步骤1.2:创建根证书请求文件:		root.csr: 根证书请求文件
openssl req -new -out root.csr -key 	root.key	-subj "/C=CN/CN=server.demo.com"


#步骤1.3:创建根证书:						root.crt : 签名有效期为10年的根证书
openssl x509 -req -in root.csr -out 	root.crt -signkey root.key -CAcreateserial -days 3650 

#步骤2:根据根证书创建服务端证书
#步骤2.1:生成服务器端证书私钥:		server.key:服务器端的秘钥文件
openssl genrsa -out server.key 2048
#步骤2.2:生成服务器证书请求文件  	server.csr : 服务端证书请求文件(请求证书时使用, 后续配置无用)
openssl req -new -out server.csr -key server.key  -subj "/C=CN/CN=server.demo.com"
#步骤2.3:生成服务器端公钥证书		server.crt:有效期十年的服务器端公钥证书,使用根证书和服务器端私钥文件一起生成
openssl x509 -req -in server.csr -out server.crt -CA root.crt -CAkey root.key  -CAcreateserial -days 3650
root.srl: CA签发证书的序列号记录文件,全名是 root.Serial 。

#步骤3:根据根证书创建客户端证书
#步骤3.1:生成客户端证书秘钥:		client.key:客户端的私钥文件
openssl genrsa -out client.key 2048
#步骤3.2:生成客户端证书请求文件		clinet.csr : 客户端证书请求文件(请求证书时使用, 后续配置无用)
openssl req -new -out client.csr -key client.key -subj "/C=CN/CN=server.demo.com"
#步骤3.3:生客户端证书						client.crt:有效期十年的客户端证书,使用根证书和客户端私钥一起生成
openssl x509 -req -in client.csr -out client.crt -CA root.crt -CAkey root.key -CAcreateserial -days 3650
#步骤3.4:生客户端p12格式证书			client.p12:客户端p12格式,这个证书文件包含客户端的公钥和私钥,主要用来给浏览器或postman访问使用
openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12 -password pass:'123456'

# 检查证书链
openssl x509 -in server.crt -text -noout
openssl x509 -in client.crt -text -noout

# nginx配置
server {
        listen       443 ssl;
        server_name  server.demo.com;# 无域名可填写ip
        ssl                  on;  
        ssl_certificate      /data/sslKey/server.crt;  #server公钥证书
        ssl_certificate_key  /data/sslKey/server.key;  #server私钥
        ssl_client_certificate /data/sslKey/root.crt;  #根证书,可以验证所有它颁发的客户端证书
        ssl_verify_client on;  #开启客户端证书验证  
 
		    # 反向代理eg: 作用是通过https(443端口)访问, 则会直接去请求本机的8991端口
		    location / {
           	proxy_pass http://127.0.0.1:8991/;
    		}
}

SSL对称加密

方式 1:keytool

# 生成自签名证书
keytool -genkeypair -keyalg RSA -keysize 2048 -keystore server.jks -alias server -validity 365 -keypass 123456 -storepass 123456 -dname "CN=localhost" -ext san=IP:192.168.1.9

# 从服务器端证书秘钥库中导出Cer证书
keytool -export -alias server -keystore server.jks -storepass 123456 -file server.cer

# 生成客户端自签名证书
keytool -genkeypair -keyalg RSA -keysize 2048 -keystore client.jks -alias client -validity 365 -keypass 123456 -storepass 123456 -dname "CN=localhost" -ext san=IP:192.168.1.9

# 从服务器端证书秘钥库中导出Cer证书
keytool -export -alias client -keystore client.jks -storepass 123456 -file client.cer

# 将客户端证书导入到服务器端证书秘钥库
keytool -import -trustcacerts -alias server -file server.cer -keystore client.jks -storepass 123456
# 将服务器端证书导入到客户端证书秘钥库
keytool -import -trustcacerts -alias client -file client.cer -keystore server.jks -storepass 123456

# 将客户端导出浏览器可安装的证书
keytool -importkeystore -srckeystore client.jks -destkeystore client.p12 -srcstoretype JKS -deststoretype PKCS12 -srcstorepass 123456 -deststorepass 123456 -srckeypass 123456 -destkeypass 123456 -srcalias client -destalias client -noprompt

# 将服务端导出浏览器可安装的证书
keytool -importkeystore -srckeystore server.jks -destkeystore server.p12 -srcstoretype JKS -deststoretype PKCS12 -srcstorepass 123456 -deststorepass 123456 -srckeypass 123456 -destkeypass 123456 -srcalias server -destalias server -noprompt

# 查看颁发证书
keytool -list -v -keystore server.jks -storepass 123456
keytool -list -v -keystore client.jks -storepass 123456

方式 2:openSSL

# 步骤1:创建CA证书
# 1.1. 创建CA私钥 RootCaKey@2024 生成 rootca.key
openssl genpkey -aes256 -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out rootca.key -pass pass:'RootCaKey@2024'
# 1.2. 创建CA证书请求 生成 rootca.crt
openssl req -x509 -days 3650 -sha256 -key rootca.key -passin pass:'RootCaKey@2024' -out rootca.crt -subj "/C=CN/CN=demorootca.demo.com"
# 1.3 生成并导入信任证书库 PKCS12 生成 rootca.p12 TrustStore@2024
keytool -import -noprompt -trustcacerts -alias rootca -file rootca.crt -keystore rootca.p12 -storetype PKCS12 -storepass 'TrustStore@2024'
# 查看 PKCS12 证书
keytool -list -v -keystore rootca.p12 -storetype PKCS12 -storepass 'TrustStore@2024'
## 生成并导入信任证书库 JKS 生成 rootca.jks
keytool -import -noprompt -trustcacerts -alias rootca -file rootca.crt -keystore rootca.jks -storetype JKS -storepass 'TrustStore@2024'
### 查看 JKS 证书
keytool -list -v -keystore rootca.jks -storetype JKS -storepass 'TrustStore@2024'


# 步骤2: 签发服务端证书
openssl genpkey -aes256 -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out server.key -pass pass:'ServerKey@2024'
openssl req -new -key server.key -passin pass:'ServerKey@2024' -out server.csr -subj "/C=CN/CN=server.demo.com"
openssl x509 -req -in server.csr -CA rootca.crt -CAkey rootca.key -passin pass:'RootCaKey@2024' -CAcreateserial -out server.crt -days 3650 -sha256
# 使用CA证书验证服务端证书
openssl verify -verbose -CAfile rootca.crt server.crt
# 生成PKCS12服务端证书
openssl pkcs12 -export -inkey server.key -passin pass:'ServerKey@2024' -in server.crt -chain -CAfile rootca.crt -out server.p12 -password pass:'ServerKeyStore@2024'
# 查看 server.p12证书
keytool -list -v -keystore server.p12 -storepass 'ServerKeyStore@2024'
# 将证书导入到 JKS 信任库
keytool -importkeystore -destkeystore server.jks -srckeystore server.p12  -deststoretype pkcs12 -storepass 'ServerKeyStore@2024'
# 查看 JKS 证书
keytool -list -v -keystore server.jks -storetype JKS -storepass 'ServerKeyStore@2024'

# 步骤3:签发客户端证书
openssl genpkey -aes256 -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out client.key -pass pass:'ClientKey@2024'
openssl req -new -key client.key -passin pass:'ClientKey@2024' -out client.csr -subj "/C=CN/CN=client.demo.com"
openssl x509 -req -in client.csr -CA rootca.crt -CAkey rootca.key -passin pass:'RootCaKey@2024' -CAcreateserial -out client.crt -days 3650 -sha256
# 使用CA证书验证客户端证书
openssl verify -verbose -CAfile rootca.crt client.crt
# 生成PKCS12客户端证书
openssl pkcs12 -export -inkey client.key -passin pass:'ClientKey@2024' -in client.crt -chain -CAfile rootca.crt -out client.p12 -password pass:'ClientKeyStore@2024'
# 查看 client.p12 证书
keytool -list -v -keystore client.p12 -storepass 'ClientKeyStore@2024'
# 将证书导入到 JKS 信任库
keytool -importkeystore -destkeystore client.jks -srckeystore client.p12  -deststoretype pkcs12 -storepass 'ClientKeyStore@2024'
# 查看 JKS 证书
keytool -list -v -keystore client.jks -storetype JKS -storepass 'ClientKeyStore@2024'

springBoot 集成

服务端配置

  • pom 配置
# pom 添加依赖
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk18on</artifactId>
    <version>1.78.1</version>
</dependency>
# 启动类添加
@SpringBootApplication
public class ServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServerApplication.class, args);
    }
    //添加
    static {
        Security.addProvider(new BouncyCastleProvider());
    }
}

# =====双向认证配置:application.yml配置=================================
server:
# server.jks方式
  ssl:
    enabled: true
    #是否需要进行认证
    client-auth: need
    key-store: classpath:cert/server.jks
    key-store-password: 123456
    key-alias: server
    trust-store: classpath:cert/server.jks
    trust-store-password: 123456
# server.p12方式
server:
  ssl:
    enabled: true
    key-store: classpath:cert/server.p12
    key-store-password: 'ServerKeyStore@2024'
    key-store-type: PKCS12
    key-store-provider: BC
    enabled-protocols: TLSv1.2,TLSv1.3
    trust-store: classpath:cert/rootca.jks
    trust-store-password: 'TrustStore@2024'
    trust-store-type: JKS
    trust-store-provider: SUN
    client-auth: need
# =====单向认证配置:application.yml配置=================================
server:
# server.jks方式
  ssl:
    enabled: true
    key-store: classpath:cert/server.jks
    key-store-password: 123456
    key-store-type: JKS
# server.p12方式
server:
  ssl:
    enabled: true
    key-store: classpath:cert/server.p12
    key-store-password: 'ServerKeyStore@2024'
    key-store-type: PKCS12

客户端配置

# 引入 pom 添加依赖
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>2.0.50</version>
</dependency>


/**
 * 获取TLS/SSL套节字工厂
 * @return
 */
private static SSLConnectionSocketFactory getSslConnectionSocketFactory() {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    java.net.URL resourceUrl = classLoader.getResource("cert/client.jks");
    try (InputStream keyInput = new FileInputStream(resourceUrl.getPath())) {
        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(keyInput, "123456".toCharArray());
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, "123456".toCharArray());
        // 创建一个空的 TrustManager,绕过java jre 证书信任库认证
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    public void checkClientTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                    }

                    public void checkServerTrusted(
                            java.security.cert.X509Certificate[] certs, String authType) {
                    }
                }
        };
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCerts, new java.security.SecureRandom());
        // 创建 SSL 连接套接字工厂
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslContext,
                NoopHostnameVerifier.INSTANCE // 注意:在生产环境中,你应该使用更安全的 HostnameVerifier
        );
        return sslsf;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

/**
 * 测试HTTPS POST请求
 */
@Test
void httpsRequest() {
    try {
        // 加载 JKS 文件
        SSLConnectionSocketFactory sslsf = getSslConnectionSocketFactory();
        // 创建 HttpClient 实例
        CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();
        // 创建 HttpPost 实例
        HttpPost httpPost = new HttpPost("https://127.0.0.1:8081/api/user/post");
        // 设置请求体(这里以 JSON 为例)
        UserVO userVO = new UserVO();
        userVO.setUsername("123456");
        StringEntity entity = new StringEntity(JSON.toJSONString(userVO), "UTF-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        // 发送请求并获取响应
        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
            HttpEntity responseEntity = response.getEntity();
            System.out.println(EntityUtils.toString(responseEntity));
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

验证请求

#使用curl命令和使用postman均可以验证,需要配置客户端证书。
# 使用命令验证
curl -k --cert-type P12 --cert client.p12:'ClientKeyStore@2024' --location --request GET 'https://127.0.0.1:8081/api/user/get'
# 使用postman的时候
# 需要将 Settings->General->REQUEST->SSL certificate verification 开关关掉,即不校验SSL服务端证书。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咚个里个咚咚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值