Java s2s 使用 p12 证书和基本授权连接到 https

Posted

技术标签:

【中文标题】Java s2s 使用 p12 证书和基本授权连接到 https【英文标题】:Java s2s connect to https with p12 certificate and basic authorization 【发布时间】:2017-03-01 12:52:52 【问题描述】:

我尝试在 Java 类上实现,该类将使用 p12 证书和“基本授权”连接到 https 服务器。您能否概述一下如何将这两者结合起来,包括安装 p12 证书?

更新。下面是我使用的类:

public static void main(String[] args) 
    try 
        KeyStore clientStore = KeyStore.getInstance("PKCS12");
        clientStore.load(new FileInputStream("d:\\certs\\api\\xx.p12"), "W*53as_G".toCharArray());

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(clientStore, "W*53as_G".toCharArray());
        KeyManager[] kms = kmf.getKeyManagers();

        KeyStore trustStore = KeyStore.getInstance("JKS");
        trustStore.load(new FileInputStream("c:\\jdk1.8.0_51\\jre\\lib\\security\\cacerts"), "changeit".toCharArray());

        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustStore);
        TrustManager[] tms = tmf.getTrustManagers();

        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(kms, tms, new SecureRandom());

        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
        URL url = new URL("https://apis2s.ee/test");

        HttpsURLConnection urlConn = (HttpsURLConnection) url.openConnection();
        urlConn.setRequestProperty("Authorization", "Basic " + Base64.encode("andrey:pass_1".getBytes()));
        urlConn.setUseCaches(false);
        urlConn.setAllowUserInteraction(true);
        urlConn.setRequestProperty("Pragma", "no-cache");
        urlConn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
        urlConn.setRequestProperty("Content-length", Integer.toString("id=1288210&ip=127.0.0.1".length()));

        StringBuilder builder = new StringBuilder();
        builder.append(urlConn.getResponseCode())
                .append(" ")
                .append(urlConn.getResponseMessage())
                .append("\n");

        System.out.println(builder);
     catch (Exception e) 
        e.printStackTrace();
    

结果是

SunCertPathBuilderException:无法找到到所请求目标的有效认证路径

并带有 SSL 调试

%% Invalidated: [Session-1, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA]
pool-2-thread-1, SEND TLSv1 ALERT: fatal, description = certificate_unknown
pool-2-thread-1, WRITE: TLSv1 Alert, length = 2
[Raw write]: length = 7
0000: 15 03 01 00 02 02 2E .......
pool-2-thread-1, called closeSocket()
pool-2-thread-1, handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: 

sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification

我还安装了 p12 证书。和命令 keytool -list -v -keystore c:\jdk1.8.0_51\jre\lib\security\cacerts 显示证书。信息:


Alias name: 1
Creation date: 28.02.2017
Entry type: PrivateKeyEntry
Certificate chain length: 2
Certificate[1]:
Owner: CN=xx, O=APIs2s Sandbox Api
Issuer: CN=apis2s.ee
Serial number: 12
Valid from: Thu Feb 23 18:57:05 CST 2017 until: Fri Feb 23 18:57:05 CST 2018
Certificate fingerprints:
MD5:  E0:E0:1E:8F:09:R3:82:6C:D9:A0:7C:FD:B3:D7:7B:76
SHA1: A0:8A:87:03:7A:14:CD:3A:C6:48:4B:98:8C:89:EK:EB:73:B7:BC:BD
SHA256:          31:1B:2E:98:66:8C:F3:53:6C:FA:4E:BC:48:67:C1:DE:02:4D:71:E8:46:CE:2B:7C:B1:9F:EA    :86:69:D6:97:15    Signature algorithm name: MD5withRSA
Version: 1
Certificate[2]:
Owner: CN=apis2s.ee
Issuer: CN=apis2s.ee
Serial number: bc7428f41765c74e
Valid from: Fri Jun 24 14:52:01 CST 2016 until: Sat Jun 24 14:52:01 CST 2017
Certificate fingerprints:
MD5:  21:F3:46:A8:30:B2:1B:D6:0C:2D:E6:2F:4F:4F:8G:B    SHA1: 1C:F0:FE:4E:94:70:5E:6E:2C:5D:E6:B1:24:77:2H:0F:72:DB:F6:01
SHA256:     51:14:82:5B:80:63:57:5B:B7:6B:CB:C9:EC:FB:C3:96:07:89:A0:4E:B5:51:B7:6D:34:08:CA    :B4:B3:2F:E6
Signature algorithm name: SHA256withRSA
Version: 3

Extensions:

#1: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 89 A1 81 25 17 41 EB E6   DD 7A B6 D2 23 2E 4B 40  ...%.A...z..#.K@
0010: 54 50 58 58                                        TXXX
]
]

#2: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
  CA:true
  PathLen:2147483646
]

#3: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 89 A2 81 25 17 41 EB E6   DD 7A B6 D2 23 2E 4B 40  ...%.A...z..#.K@
0010: 54 51 58 58                                        TXXX
]
]

*******************************************

【问题讨论】:

请提供您的代码并说明您遇到的问题。这个问题现在太宽泛了 我在上面添加了我的代码。 您需要在 cacerts 中包含 https://apis2s.ee 中 SSL 服务器证书的根 CA,而不是私钥。基本授权似乎没问题 我使用浏览器从apis2s.ee 导入了根CA,并保存在.cer 文件中。然后我导入了它 keytool -import -alias ca -file d:\certs\api\xx.cer -keystore c:\jdk1.8.0_51\jre\lib\security\cacerts -storepass changeit 但结果是相同 - 异常 SunCertPathBuilderException:无法找到请求目标的有效证书路径 【参考方案1】:

最后通过要求服务器 apis2s.ee 团队提供有效的根 CA 证书解决了问题。他们发送后,我使用命令将其导入

keytool -import -alias ca -file d:\certs\api\api\Serv_CA_SSL.cer -keystore c:\jdk1.8.0_51\jre\lib\security\cacerts -storepass changeit

一切正常(无需重新启动)。我稍微更改了结果类以显示服务器输出`

public static void main(String[] args) 
    try 

        KeyStore clientStore = KeyStore.getInstance("PKCS12");
        clientStore.load(new FileInputStream("d:\\certs\\api\\xx.p12"), "W*53as_G".toCharArray());

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(clientStore, "W*53as_G".toCharArray());
        KeyManager[] kms = kmf.getKeyManagers();

        KeyStore trustStore = KeyStore.getInstance("JKS");
        trustStore.load(new FileInputStream("c:\\jdk1.8.0_51\\jre\\lib\\security\\cacerts"), "changeit".toCharArray());

        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustStore);
        TrustManager[] tms = tmf.getTrustManagers();

        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(kms, tms, new SecureRandom());

        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
        URL url = new URL("https://apis2s.ee/test");

        HttpsURLConnection urlConn = (HttpsURLConnection) url.openConnection();
        urlConn.setRequestProperty("Authorization", "Basic " + Base64.encode("andrey:pass_1".getBytes()));
        urlConn.setUseCaches(false);
        urlConn.setAllowUserInteraction(true);
        urlConn.setRequestProperty("Pragma", "no-cache");
        urlConn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
        urlConn.setRequestProperty("Content-length", Integer.toString("id=1288210&ip=127.0.0.1".length()));

        urlConn.setDoOutput( true );
        urlConn.setRequestProperty( "Content-Length", Integer.toString( jsonParams.length() ));
        PrintStream out = new PrintStream(urlConn.getOutputStream());
        out.print("id=1288210&ip=127.0.0.1");
        out.flush();
        out.close();

        StringBuilder builder = new StringBuilder();
        int responseCode = urlConn.getResponseCode();
        builder.append(responseCode)
                .append(" ")
                .append(urlConn.getResponseMessage())
                .append("\n");

        InputStream res = urlConn.getInputStream();
        Scanner in = new Scanner(res);
        String responseStr = "";
        while(in.hasNextLine()) 
            String s = in.nextLine();
            responseStr+=s;
        
        System.out.println(builder);
        System.out.println("responseStr: " + responseStr);
     catch (KeyStoreException e) 
        e.printStackTrace();
     catch (IOException e) 
        e.printStackTrace();
     catch (NoSuchAlgorithmException e) 
        e.printStackTrace();
     catch (CertificateException e) 
        e.printStackTrace();
     catch (UnrecoverableKeyException e) 
        e.printStackTrace();
     catch (KeyManagementException e) 
        e.printStackTrace();
    

`

感谢 pedrofb 审核代码和建议。

【讨论】:

以上是关于Java s2s 使用 p12 证书和基本授权连接到 https的主要内容,如果未能解决你的问题,请参考以下文章

一个苹果证书怎么多次使用——导出p12文件

将证书链添加到 p12(pfx) 证书

如何在 Eclipse 中使用 p12 证书?

openssl pem证书 转换为p12类型证书

需要帮助将 P12 证书转换为 JKS

苹果证书导出p12文件