為https請求配置ssl(不用keystore,直接用證書,java程式碼)
阿新 • • 發佈:2020-06-29
參考連結:
https://stackoverflow.com/questions/12501117/programmatically-obtain-keystore-from-pem
https://stackoverflow.com/questions/6559272/algid-parse-error-not-a-sequence
http://www.bouncycastle.org/latest_releases.html
生成SSLSocketFactory程式碼(核心):
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.io.File; import java.nio.file.Files;import java.nio.file.Paths; 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; public class KeyTest { public static SSLSocketFactory getSocketFactoryPEM(String certPath, String keyPath) throws Exception { byte[] certByte = Files.readAllBytes(Paths.get(certPath)); byte[] keyByte = Files.readAllBytes(Paths.get(keyPath)); byte[] certBytes = parseDERFromPEM(certByte, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----"); byte[] keyBytes = parseDERFromPEM(keyByte, "-----BEGIN RSA PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----"); X509Certificate cert = generateCertificateFromDER(certBytes); RSAPrivateKey key = generatePrivateKeyFromDER(keyBytes); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(null); keystore.setCertificateEntry("cert-alias", cert); keystore.setKeyEntry("key-alias", key, "<password>".toCharArray(), new Certificate[] {cert}); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(keystore, "<password>".toCharArray()); KeyManager[] km = kmf.getKeyManagers(); SSLContext context = SSLContext.getInstance("TLS"); context.init(km, null, null); return context.getSocketFactory(); } 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 RSAPrivateKey generatePrivateKeyFromDER(byte[] keyBytes) throws InvalidKeySpecException, NoSuchAlgorithmException { java.security.Security.addProvider( new org.bouncycastle.jce.provider.BouncyCastleProvider() ); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory factory = KeyFactory.getInstance("RSA"); return (RSAPrivateKey)factory.generatePrivate(spec); } private static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException { CertificateFactory factory = CertificateFactory.getInstance("X.509"); return (X509Certificate)factory.generateCertificate(new ByteArrayInputStream(certBytes)); } }
後續https請求程式碼:
okhttp:
private void test()throws Exception { JSONObject jsonObject = new JSONObject(); jsonObject.put("test", "123"); OkHttpClient client = new OkHttpClient.Builder() .sslSocketFactory(KeyTest.getSocketFactoryPEM("","")) .build(); Request request = new Request.Builder() .url("") .post(RequestBody.create(MediaType.parse("application/json"), jsonObject.toJSONString())) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { System.out.println("--------------onFailure--------------" + e.toString()); } @Override public void onResponse(Call call, Response response) throws IOException { System.out.println("--------------onResponse--------------" + response.body().string()); } }); }