#1 Android只支持.bks格式的证书,要生成.bks证书,可以通过keytools的adb命令将.cer格式的数字证书导入到.bak文件中
#2 预备工具“bcprov-jdk16-145.jar”(下载地址(放了两个jdk版本的jar文件):
http://download.csdn.net/detail/baopengjian/9528444
)
#3 将“bcprov-jdk16-145.jar”拷贝到 jre\lib\ext目录下 (注意jdk环境是16)
获取cacerts.bks文件到你的计算机中,可使用Android模式器,也可USB连接你的手机。
>adb pull /system/etc/security/cacerts.bks cacerts.bks
如果是你是使用国行版的Android手机,可访问https://www.enum.cn 检查是否内置了CNNIC的CA,如果有的话,你可以使用原版cacerts.bks,这个文件所有android系统通用。(可以直接百度cacerts.bks ,下载)
>adb pull /system/etc/security/cacerts.bks cacerts.bks
如果是你是使用国行版的Android手机,可访问https://www.enum.cn 检查是否内置了CNNIC的CA,如果有的话,你可以使用原版cacerts.bks,这个文件所有android系统通用。(可以直接百度cacerts.bks ,下载)
#5 将cacerts.bks文件和.cer文件(服务端哥们提供)拷贝到jre/bin/目录下(和keytool.exe,也可以配置环境变量)
#6 cmd -> 进入到jre/bin目录下,
>keytool -keystore cacerts.bks -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider -storepass changeit -importcert -trustcacerts -alias 存放别名(如111.crt) -file 要导入的根证书.crt
# 7 按确定y,提示添加到.bks文件中去了
# 7 按确定y,提示添加到.bks文件中去了
#8 将cacerts.bks拷贝到项目目录下
#9
客户端代码
(加载key的代码:kks.load(context.getAssets().open("cacerts.bks"), "123456".toCharArray()); 没有密码就填null,两个参数都是null则默认所以证书都信任)
private DefaultHttpClient createHttpClient() {
SSLSocketFactory sf = null;
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
sf = new MySSLSocketFactory(keyStore,context);
} catch (Exception e) {
e.printStackTrace();
}
BasicHttpParams httpParams = new BasicHttpParams();
ConnManagerParams.setMaxTotalConnections(httpParams,
max_total_connections);
ConnPerRouteBean perRoute = new ConnPerRouteBean(max_route_connections);
ConnManagerParams.setMaxConnectionsPerRoute(httpParams, perRoute);
ConnManagerParams.setTimeout(httpParams, wait_timeout);
HttpConnectionParams.setConnectionTimeout(httpParams, timeOut);
HttpConnectionParams.setSoTimeout(httpParams, timeOut);
HttpConnectionParams.setLinger(httpParams, 30000);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ThreadSafeClientConnManager connectionManager = new ThreadSafeClientConnManager(
httpParams, registry);
DefaultHttpClient client = new DefaultHttpClient(connectionManager,
httpParams);
return client;
}
private static class MySSLSocketFactory extends SSLSocketFactory{
SSLContext sslContext = SSLContext.getInstance("TLS");
public MySSLSocketFactory(KeyStore truststore, Context context)
throws NoSuchAlgorithmException, KeyManagementException,
KeyStoreException, UnrecoverableKeyException, CertificateException, IOException {
super(truststore);
KeyManagerFactory keyManager = KeyManagerFactory .getInstance("X509");
TrustManagerFactory trustManager = TrustManagerFactory
.getInstance("X509");
// 取得BKS密库实例
KeyStore kks = KeyStore.getInstance("BKS");
KeyStore tks = KeyStore.getInstance("BKS");
// 加客户端载证书和私钥,通过读取资源文件的方式读取密钥和信任证书
kks.load(context.getAssets().open("cacerts.bks"), "123456".toCharArray());
tks.load(context.getAssets().open("client.bks"),
"123456".toCharArray());
// 初始化密钥管理器
keyManager.init(kks, "123456".toCharArray());
trustManager.init(tks);
// 初始化SSLContext
sslContext.init(keyManager.getKeyManagers(),
trustManager.getTrustManagers(), null);
}
@Override
public Socket createSocket() throws IOException {
// TODO Auto-generated method stub
return sslContext.getSocketFactory().createSocket();
}
@Override
public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host,
port, autoClose);
}
}
private DefaultHttpClient createHttpClient() {
SSLSocketFactory sf = null;
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
sf = new MySSLSocketFactory(keyStore,context);
} catch (Exception e) {
e.printStackTrace();
}
BasicHttpParams httpParams = new BasicHttpParams();
ConnManagerParams.setMaxTotalConnections(httpParams,
max_total_connections);
ConnPerRouteBean perRoute = new ConnPerRouteBean(max_route_connections);
ConnManagerParams.setMaxConnectionsPerRoute(httpParams, perRoute);
ConnManagerParams.setTimeout(httpParams, wait_timeout);
HttpConnectionParams.setConnectionTimeout(httpParams, timeOut);
HttpConnectionParams.setSoTimeout(httpParams, timeOut);
HttpConnectionParams.setLinger(httpParams, 30000);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ThreadSafeClientConnManager connectionManager = new ThreadSafeClientConnManager(
httpParams, registry);
DefaultHttpClient client = new DefaultHttpClient(connectionManager,
httpParams);
return client;
}
private static class MySSLSocketFactory extends SSLSocketFactory{
SSLContext sslContext = SSLContext.getInstance("TLS");
public MySSLSocketFactory(KeyStore truststore, Context context)
throws NoSuchAlgorithmException, KeyManagementException,
KeyStoreException, UnrecoverableKeyException, CertificateException, IOException {
super(truststore);
KeyManagerFactory keyManager = KeyManagerFactory .getInstance("X509");
TrustManagerFactory trustManager = TrustManagerFactory
.getInstance("X509");
// 取得BKS密库实例
KeyStore kks = KeyStore.getInstance("BKS");
KeyStore tks = KeyStore.getInstance("BKS");
// 加客户端载证书和私钥,通过读取资源文件的方式读取密钥和信任证书
kks.load(context.getAssets().open("cacerts.bks"), "123456".toCharArray());
tks.load(context.getAssets().open("client.bks"),
"123456".toCharArray());
// 初始化密钥管理器
keyManager.init(kks, "123456".toCharArray());
trustManager.init(tks);
// 初始化SSLContext
sslContext.init(keyManager.getKeyManagers(),
trustManager.getTrustManagers(), null);
}
@Override
public Socket createSocket() throws IOException {
// TODO Auto-generated method stub
return sslContext.getSocketFactory().createSocket();
}
@Override
public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host,
port, autoClose);
}
}
注意: #1 .jar文件放到jre/lib/ext/目录下
#2 注意jre和bcprov-jdk16-146.jar的版本要一致,bcprov-jdk16-146.jar的版本要1.46的,其他版本可能报错:java.io.IOException: Wrong version of key store