先看原代码:
// 创建CertificateFactory对象
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
// 读取PEM证书文件并创建Certificate对象
FileInputStream certInputStream = new FileInputStream("pem文件的地址");
Certificate certificate = certificateFactory.generateCertificate(certInputStream);
certInputStream.close();
// 创建KeyStore对象并添加证书
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null); // 创建一个空的KeyStore,如果不指定密码,则此方法不需要密码参数
keyStore.setCertificateEntry(alias, certificate);
说明:这里在运用上有问题,因为java读取是从密钥库中读取证书,不是从pem中读取证书,需要先将pem文件的证书添加密钥库,程序再从秘钥库中读取数据
即是这种
byte[] certAndKey = Files.readAllBytes(Paths.get(PEM_PATH)); byte[] certBytes = parseDERFromPEM(certAndKey, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----"); byte[] keyBytes = parseDERFromPEM(certAndKey, "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----"); X509Certificate cert = generateCertificateFromDER(certBytes); PrivateKey key = generatePrivateKeyFromDER(keyBytes); KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); //KeyStore keystore = KeyStore.getInstance("PKCS12"); keystore.load(null); keystore.setCertificateEntry("alias", cert); keystore.setKeyEntry("alias", key, PASSWORD.toCharArray(), new Certificate[] {cert});//下面这里是上面的方法抽取出来的
private 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]); } private static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException { CertificateFactory factory = CertificateFactory.getInstance("X.509"); return (X509Certificate)factory.generateCertificate(new ByteArrayInputStream(certBytes)); } private static PrivateKey generatePrivateKeyFromDER(byte[] keyBytes) throws InvalidKeySpecException, NoSuchAlgorithmException { //PKCS#8 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory factory = KeyFactory.getInstance("RSA"); return factory.generatePrivate(spec); }
如上图,将内容读取到在设置keystore内容进去,而并非下面的这种
CertificateFactory.getInstance("X.509").generateCertificate(certInputStream);
二.对于jks类型的可以直接读取
如下面这种:
String keystorePassword = "<Your KeyStore Password Here>"; final String keyPassword = "<Your Key Password Here>"; final String keystorePath = "<Path to the KeyStore.jks>"; final KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); final FileInputStream fileInputStream = new FileInputStream(new File(keystorePath)); keyStore.load(fileInputStream, keystorePassword.toCharArray()); fileInputStream.close(); final TrustStrategy trustStrategy = new TrustStrategy() { public boolean isTrusted(final X509Certificate[] x509Certs, final String s) throws CertificateException { return true; } }; final SSLContext sslContext = SSLContexts.custom() .loadKeyMaterial(keyStore, keyPassword.toCharArray()) .loadTrustMaterial(keyStore, trustStrategy) .build(); final SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext);HttpClients.custom() .setSSLSocketFactory(sslConnectionSocketFactory) .build();
这里就是直接将jks文件加入到keystore上,jks与pem的格式不同,pem可以看出内容,jks编译后只能给机器读取.