近期,在做一个tomcat与andriod平台的SSL双向认证工程,经过2天努力,总算大功告成啊。
SSL协议是双向认证,因此首先要生存服务器与客户端的密钥对。(ps:由于andriod只支持BKS证书的读写,因此生成的证书类型必须是BKS文件)
生存服务器证书
服务器的证书,本文中采用JDK自带的keytool工具生成。
配置JAVA_HOME.本文这里略过。
1. 创建服务器的keystore文件。(-genkey指令这里生成了 服务器的 公钥,私钥,证书)
keytool -genkey -alias sslserver -keystore sslserver.keystore
2. 导出sslserver中的证书,作为客户端的就交换使用
keytool -export -alias sslserver -keystore sslserver.keystore -file sslserver.cer
生成客户端证书
由于客户端是android只支持BKS类型的密钥库,而java本身不支持BKS类型密钥库,所以我们需要手动的加上这个库,使java的keytool能够使用BKS:
将这个bcprov-jdk16-141.jar包放在%JAVA_HOME%的jre/lib/etx文件夹下,然后在%JAVA_HOME%的jre/lib/security/java.security 文件中的列表中添加一条
security.provider.n=org.bouncycastle.jce.provider.BouncyCastleProvider (n根据实际情况递增。)
1. 生成bks文件,改文件中包含客户端的公钥,私钥,证书
keytool -genkey -alias sslclient -keystore sslclient.keystore.bks
2. 导出bks中的证书,作为服务器交互使用
keytool -export -keystore sslclient.keystore.bks -storepass 123456 -file sslclient.cer -alias sslclient
将服务器与客户端的证书相互导入到各自信任证书中
1. 将客户端证书导入到服务器端受信任的 keystore 中
keytool -import -alias sslclient -keystore sslservertrust.keystore -file sslclient.cer
2. 将服务器端证书导入到客户端受信任的 keystore 中
keytool -import -alias sslserver -keystore sslclienttrust.bks -file sslserver.cer
以上工作完成后。客户端,服务器的证书文件生成完成。将sslclient.keystore.bks,sslclienttrust.bks 这2个文件拷贝到andriod工程中去。
配置tomcat服务器
本文中tomcat的版本为6.0.35(建议使用tomcat 5以上的版本)
找到tomcat_home下conf/server.xml。编辑该文件
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="..\sslserverkeys.keystore" keystorePass="123456"
truststoreFile="..\sslservertrust.keystore" truststorePass="123456"/>
到这里所以配置完成。
andriod部分端代码
//取得SSL的SSLContext实例
SSLContext sslContext = SSLContext.getInstance(CLIENT_AGREEMENT);
//取得KeyManagerFactory和TrustManagerFactory的X509密钥管理器实例
KeyManagerFactory keyManager = KeyManagerFactory.getInstance(CLIENT_KEY_MANAGER);
TrustManagerFactory trustManager = TrustManagerFactory.getInstance(CLIENT_TRUST_MANAGER);
//取得BKS密库实例
KeyStore kks= KeyStore.getInstance(CLIENT_KEY_KEYSTORE);
KeyStore tks = KeyStore.getInstance(CLIENT_TRUST_KEYSTORE);
//加客户端载证书和私钥,通过读取资源文件的方式读取密钥和信任证书
kks.load(getBaseContext() .getResources().openRawResource(R.drawable.kclient),CLIENT_KET_PASSWORD.toCharArray());
tks.load(getBaseContext().getResource().openRawResource(R.drawable.lt_client),CLIENT_TRUST_PASSWORD.toCharArray());
//初始化密钥管理器
keyManager.init(kks,CLIENT_KET_PASSWORD.toCharArray());
trustManager.init(tks);
//初始化SSLContext
sslContext.init(keyManager.getKeyManagers(),trustManager.getTrustManagers(),null);