android与mqtt双向SSL认证
04 Mar 2016Android与MQTT实现双向认证。
需要的工具:
- bcprov-ext-jdk14-1.54.jar
- portecle-1.9
- UnlimitedJCEPolicyJDK8
生成ca.bks
完成对服务器的自签名单向认证
$ keytool -import \
-alias mqtt.broker \
-file ca.crt \
-keypass passw0rd \
-keystore ca.bks \
-storetype BKS \
-storepass passw0rd \
-providerClass org.bouncycastle.jce.provider.BouncyCastleProvider \
-providerpath bcprov-ext-jdk14-1.54.jar
MqttAndroidClient clint = ...
MqttConnectOptions options = new MqttConnectOptions();
InputStream input = this.getApplicationContext().getAssets().open("ca.bks");
options.setSocketFactory(client.getSSLSocketFactory(input, "passw0rd"));
生成client.bks
完成对客户端的认证,需要借portecle工具把pfx转成bks
$ openssl pkcs12 -export -inkey client.key -in client.crt -out client.pfx
$ java -jar portecle.jar
File -> New Keystore -> BKS-V1 -> Tools -> Import Key Pair -> choose -> client.pfx
如果提示错误就安装UnlimitedJCEPolicyJDK8
private SSLSocketFactory getSSLSocketFactory(Context context, String password) throws MqttSecurityException {
try {
InputStream keyStore = context.getResources().getAssets().open("client.bks");
KeyStore km = KeyStore.getInstance("BKS");
km.load(keyStore, password.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
kmf.init(km, password.toCharArray());
InputStream trustStore = context.getResources().getAssets().open("ca.bks");
KeyStore ts = KeyStore.getInstance("BKS");
ts.load(trustStore, password.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(ts);
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
return ctx.getSocketFactory();
} catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException | KeyManagementException | UnrecoverableKeyException e) {
throw new MqttSecurityException(e);
}
}
options.setSocketFactory(getSSLSocketFactory(context, "passw0rd"));
参考: