如何实现Java不信任的证书

1. 流程图

flowchart TD;
    A[生成密钥对] --> B[生成证书签名请求(CSR)]
    B --> C[向CA申请证书]
    C --> D[下载CA签发的证书]
    D --> E[使用证书进行HTTPS通信]

2. 生成密钥对

通过Java的密钥库(KeyStore)生成密钥对,密钥对包括私钥和公钥。

import java.security.*;

public class KeyPairGeneratorExample {
    public static void main(String[] args) throws Exception {
        // 使用KeyPairGenerator生成密钥对
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        // 获取私钥
        PrivateKey privateKey = keyPair.getPrivate();
        // 获取公钥
        PublicKey publicKey = keyPair.getPublic();
    }
}

3. 生成证书签名请求(CSR)

生成证书签名请求(Certificate Signing Request,CSR)包含了公钥信息和证书主题信息,用于向证书颁发机构(CA)申请证书。

import sun.security.pkcs.PKCS10;

import java.io.FileOutputStream;
import java.security.*;
import java.security.cert.Certificate;

public class CSRGeneratorExample {
    public static void main(String[] args) throws Exception {
        // 生成CSR
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PublicKey publicKey = keyPair.getPublic();

        PKCS10 pkcs10 = new PKCS10(publicKey);
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(keyPair.getPrivate());
        pkcs10.encodeAndSign(signature);

        // 将CSR保存到文件
        byte[] csrBytes = pkcs10.getEncoded();
        FileOutputStream fos = new FileOutputStream("csr.csr");
        fos.write(csrBytes);
        fos.close();
    }
}

4. 向CA申请证书

将生成的CSR文件发送给证书颁发机构(CA),并申请签发证书。CA会对CSR进行验证,并签发相应的证书。

5. 下载CA签发的证书

从CA获取签发的证书,并将证书保存到密钥库中。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;

public class CertificateDownloaderExample {
    public static void main(String[] args) throws Exception {
        // 从CA下载证书
        FileInputStream fis = new FileInputStream("certificate.cer");
        Certificate certificate = CertificateFactory.getInstance("X.509").generateCertificate(fis);
        fis.close();

        // 保存证书到密钥库
        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(null, null);
        keyStore.setCertificateEntry("alias", certificate);

        FileOutputStream fos = new FileOutputStream("keystore.jks");
        keyStore.store(fos, "password".toCharArray());
        fos.close();
    }
}

6. 使用证书进行HTTPS通信

使用密钥库中的证书进行HTTPS通信,Java会自动验证服务器返回的证书是否由受信任的CA签发。

import java.io.FileInputStream;
import java.net.URL;
import java.security.KeyStore;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;

public class HttpsExample {
    public static void main(String[] args) throws Exception {
        // 加载密钥库
        KeyStore keyStore = KeyStore.getInstance("JKS");
        FileInputStream fis = new FileInputStream("keystore.jks");
        keyStore.load(fis, "password".toCharArray());
        fis.close();

        // 创建KeyManagerFactory,并初始化密钥库
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(keyStore, "password".toCharArray());

        // 创建TrustManagerFactory,并使用系统默认的信任管理器
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init((KeyStore) null);

        // 创建SSL上下文,并设置密钥管理器和信任管理器
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        // 发送HTTPS请求
        URL url = new URL("
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
        conn.setSSLSocketFactory(sslContext.getSocketFactory());