HttpClient: SSL双向认证

拿到PPro支付的文档后,发现PPro需要客户端在与其交互的过程中,使用SSL双向认证。

也就是说,申请测试账户后,PPro会为测试账户生成一个ssl客户端证书,该证书是由PPro自签名CA签发的。

在PPro分配测试账号时,用户会得到

  • ca.crt – PPro自签名CA根证书
  • customer.crt – 用户证书
  • customer.key – 用户私钥

为了在Java中使用这些证书及私钥,需要将其导入到KeyStore中,需要创建两个KeyStore,分别存放CA证书,用户证书及私钥

1. 导入ca.crt至caKeyStore

keytool -importcert -alias pproca -file ca.crt -storetype jks -keystore caKeyStore.jks

需要指定别名、KeyStore类型(JKS),并指定KeyStore的访问密码

2. 导入customer.crt和customer至clientKeyStore

openssl pkcs12 -export -in customer.crt -out clientKeyStore.p12 -inkey customer.key -name customer

导入客户证书及密钥不能使用keytool命令,而需要使用openssl中的pkcs12 -export,并指定证书、密钥,以及别名(-name),并且需要根据提示输入export密码。keytool不能导入密钥。

openssl命令在此处生成的clientKeyStore.p12可以直接在Java中当作类型为PKCS12的KeyStore来使用。

加载KeyStore

InputStream keyStoreStream = loadKeyStoreIntoInputStream(keyStoreLocation);
KeyStore keyStore = KeyStore.getInstance("pkcs12"); // jks for CA
keyStore.load(keyStoreStream, keyStorePassword.toCharArray());

HttpClient调用KeyStore实现双向SSL认证

        HttpClient httpClient = new DefaultHttpClient();
 
        SSLSocketFactory sslSocketFactory = new SSLSocketFactory(clientKeyStore, clientKeyStorePassword, caKeyStore);
        Scheme protocolScheme = new Scheme("HTTPS", 443, sslSocketFactory);
 
        httpClient.getConnectionManager().getSchemeRegistry().register(protocolScheme);
 
        HttpPost httpPost = new HttpPost(url);

代码中的clientKeyStorePassword即是生成p12库时指定的export密码。

参考:OpenSSL设置、配置 及相关命令, KeyStore in Java