如何实现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());