折腾了好久,最后发送Android端也是能使用pfx格式的证书的,一直以为用不了,服务器端是c#或者netty。
证书准备:
服务器端用到的是server.pfx+ca.pfx
客户端用到的是client.pfx+ca.pfx
服务器端与Android端都是使用netty
获取sslcontex
public SSLContext getClientSSLContext(){
try {
SSLContext sslContext;
try {
String keyPassword = "***";
String trustPassword = "***";
// key store manager
KeyStore keyStore = KeyStore.getInstance("PKCS12");
InputStream keyInput = new FileInputStream("C:\\Users\\Desktop\\certificates1\\client.pfx");
keyStore.load(keyInput, keyPassword.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyPassword.toCharArray());
// trust store manager
KeyStore trustStore = KeyStore.getInstance("PKCS12");
InputStream trustInput = new FileInputStream("C:\\Users\\Desktop\\certificates1\\ca.pfx");
trustStore.load(trustInput, trustPassword.toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
return sslContext;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}catch (Exception er){
return null;
}
}
在7.0系统中出现一些问题。后面通过信任所有证书临时处理
sslContext.init(keyManagerFactory.getKeyManagers(), new TrustManager[]{ new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}}, null);
服务器端
ChannelPipeline pipeline = socketChannel.pipeline();
SSLEngine engine = new SSLUtils().getClientSSLContext().createSSLEngine();
engine.setUseClientMode(false);
engine.setNeedClientAuth(true);
pipeline.addFirst(new SslHandler(engine));
android 端
SSLEngine engine = new SSLUtils().getClientSSLContext().createSSLEngine();
engine.setUseClientMode(true);
pipeline.addFirst(new SslHandler(engine));
Android端使用的是mina
注意加setEnabledCipherSuites,这个坑我找了很久。必须设置这个加密方式,否则出现一发数据就会自动断开连接
SSLContext sslContext = new SSLUtils().getClientSSLContext();
if(sslContext!=null){
SslFilter sslFilter = new SslFilter(sslContext);
sslFilter.setUseClientMode(true);
//太坑了,需要加入这个才行,不然一握手就会失败
sslFilter.setEnabledCipherSuites(new String[]{"TLS_RSA_WITH_AES_128_CBC_SHA"});
connector.getFilterChain().addFirst("sslFilter", sslFilter);
}