本文只提到pem类型的证书导入SSL套接类
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.69</version>
</dependency>
package com.bob.ibeelink.apple.mfi.application.utils;
import cn.hutool.core.io.FileUtil;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.xml.bind.DatatypeConverter;
import java.io.ByteArrayInputStream;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
/**
* httpClient 证书加载工具类
*
* @author Pierce.Cai
*/
public class HttpClientCertificateUtils
{
private HttpClientCertificateUtils()
{
}
/**
* 获取含有Pem证书与key密钥的SSL套接类
*
* @param pemPath pem类型证书地址
* @param keyPath key类型密钥地址
* @param keyPassword 密钥密钥,不用密码请传空字符串
* @return SSLSocketFactory类 包含Pem文件与key文件的内容
* @throws Exception 报错类型
*/
public static SSLSocketFactory getSocketFactoryPEM(String pemPath, String keyPath, String keyPassword)
throws Exception
{
byte[] pem = FileUtil.readBytes(pemPath);
byte[] pemKey = FileUtil.readBytes(keyPath);
byte[] certBytes = parseDERFromPEM(pem, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
X509Certificate cert = generateCertificateFromDER(certBytes);
byte[] keyBytes = parseDERFromPEM(pemKey, "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----");
RSAPrivateKey key = generatePrivateKeyFromDER(keyBytes);
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(null);
keystore.setCertificateEntry(cert.getSubjectX500Principal()
.getName(), cert);
//生成证书的密码,修改为自己的
keystore.setKeyEntry("key-alias", key, keyPassword.toCharArray(), new Certificate[]{cert});
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keystore, keyPassword.toCharArray());
KeyManager[] km = kmf.getKeyManagers();
//根据你的jdk版本决定是TLS、TLSv1.1、TLSv1.2
SSLContext context = SSLContext.getInstance("TLSv1.2");
context.init(km, null, null);
return context.getSocketFactory();
}
/**
* 将PEM格式转换为DER二进制数据
*
* @param pem PEM格式内容
* @param beginDelimiter 开头分隔符
* @param endDelimiter 结尾分隔符
* @return DER二进制数据
*/
public static byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter)
{
String data = new String(pem);
String[] tokens = data.split(beginDelimiter);
tokens = tokens[1].split(endDelimiter);
return DatatypeConverter.parseBase64Binary(tokens[0]);
}
/**
* 将密钥的DER格式的二进制数据转换为RSA私钥对象
*
* @param keyBytes 密钥的DER格式内容
* @return RSA私钥对象
* @throws InvalidKeySpecException 无效的密钥规范
* @throws NoSuchAlgorithmException 表示请求的加密算法在当前的计算机环境中不可用
*/
public static RSAPrivateKey generatePrivateKeyFromDER(byte[] keyBytes)
throws InvalidKeySpecException, NoSuchAlgorithmException
{
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
return (RSAPrivateKey) factory.generatePrivate(spec);
}
/**
* 将证书DER格式的二进制数据转换为RSA私钥对象
*
* @param certBytes 证书DER格式内容
* @return RSA私钥对象
* @throws CertificateException 证书数据存在错误或不合法
*/
public static X509Certificate generateCertificateFromDER(byte[] certBytes)
throws CertificateException
{
CertificateFactory factory = CertificateFactory.getInstance("X.509");
return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes));
}
}