[完结] 生成单向/双向SSL证书

1.Nginx

1.1 SSL 单向认证

# 生成加密的私钥
openssl genrsa -des3 -out private.key 2048
# 生成证书签名请求 (CSR)
openssl req -new -key private.key -out certificate.csr -passin pass:giraffe -subj "/C=CN/ST=ShangHai/L=ShangHai/O=MyCompany/OU=IT/CN=www.test.com/emailAddress=1183711908@qq.com"
# 生成自签名证书
openssl x509 -req -days 3650 -in certificate.csr -signkey private.key -passin pass:giraffe -out certificate.crt
# 生成不带密码保护的私钥
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;
    }
}

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

2. SSL对称加密

2.1 方式 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.2 方式 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'

2.3 springBoot 集成

2.3.1 服务端配置

# 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

2.3.2客户端配置

# 引入 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、付费专栏及课程。

余额充值