Android客户端的SSLSocket通信实例源码(PC做服务器、BKS密库)
2017-06-12 22:28
253 查看
>基本知识
SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层对网络连接进行加密。
而默认情况下,java利用的是TLS和JKS密库。建议先看一下下方这篇PC-PC间SSLsocket通信的实例。
本文最终实例见文末。
>PC与PC间的SSL Socket通信
技术实现详见:http://blog.csdn.net/shenpibaipao/article/details/72984015
Attr:JKS密库,无证书自签名验证。
>安卓与PC间的SSL Socket通信
Attr:BKS密库,要求进行证书自签名验证
>“PC-PC”与“安卓-PC”这两种模式在实现上有何不同?
1.PC上必须使用JKS密库,安卓上必须使用BKS密库。
2.安卓对所有自签名证书都要求自检,否则可能会抛出下面这个异常:Trust anchor for certification path not found.
3.安卓的网络操作必须放在非主线程中:详见:http://blog.csdn.net/shenpibaipao/article/details/70304702
>如何构建BKS密库
Java自带的keytool并没有自带BKS密库,因此需要到Bouncy Castle的官网去下载对应JDK的包:
http://www.bouncycastle.org/latest_releases.html
1.5-1.8的包可以到这里下载:
http://download.csdn.net/detail/shenpibaipao/9868576
环境的搭建:
1. 把bcprov-xxxxx.jar放到jdk1.x.xx\jre\lib\ext目录下
2. 在jdk1.x.xx\jre\lib\security目录中的java.security文件里增加一行提供者信息:
接着,启动keytool(详见PC-PC中的那一篇),利用-storetype BKS指令构建BKS密库。
>构建秘钥库和Trust秘钥库的样例指令:
逻辑图建议参考“PC-PC”里的那个,便于理解。
再强调一遍,安卓端的密库必须是BKS,PC端的密库必须是JKS,否者会在握手阶段抛出异常。
>客户端自验证自签名证书
详见:http://blog.csdn.net/u013424496/article/details/51161647
可以先跳过,遇到异常再回来看看。(其实就是重写相关方法,把安卓强制验证写空了而已)
>实例代码:
服务端代码:
客户端代码:
如果想把证书导出到sdcard中做其他操作,见此:http://blog.csdn.net/shenpibaipao/article/details/73032148
服务端输出结果:
>其他参考文章:
http://blog.sina.com.cn/s/blog_792cc4290100syyf.html
http://kb.cnblogs.com/page/162080/
http://www.cnblogs.com/zhujiabin/p/5895079.html
SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层对网络连接进行加密。
而默认情况下,java利用的是TLS和JKS密库。建议先看一下下方这篇PC-PC间SSLsocket通信的实例。
本文最终实例见文末。
>PC与PC间的SSL Socket通信
技术实现详见:http://blog.csdn.net/shenpibaipao/article/details/72984015
Attr:JKS密库,无证书自签名验证。
>安卓与PC间的SSL Socket通信
Attr:BKS密库,要求进行证书自签名验证
>“PC-PC”与“安卓-PC”这两种模式在实现上有何不同?
1.PC上必须使用JKS密库,安卓上必须使用BKS密库。
2.安卓对所有自签名证书都要求自检,否则可能会抛出下面这个异常:Trust anchor for certification path not found.
3.安卓的网络操作必须放在非主线程中:详见:http://blog.csdn.net/shenpibaipao/article/details/70304702
>如何构建BKS密库
Java自带的keytool并没有自带BKS密库,因此需要到Bouncy Castle的官网去下载对应JDK的包:
http://www.bouncycastle.org/latest_releases.html
1.5-1.8的包可以到这里下载:
http://download.csdn.net/detail/shenpibaipao/9868576
环境的搭建:
1. 把bcprov-xxxxx.jar放到jdk1.x.xx\jre\lib\ext目录下
2. 在jdk1.x.xx\jre\lib\security目录中的java.security文件里增加一行提供者信息:
security.provider.X=org.bouncycastle.jce.provider.BouncyCastleProvider其中,X为优先级数字,顺着原来的数字往下,如图:
接着,启动keytool(详见PC-PC中的那一篇),利用-storetype BKS指令构建BKS密库。
>构建秘钥库和Trust秘钥库的样例指令:
//1.服务端密库(默认为JKS密库,也就是PC要用的密库) keytool -genkey -keystore ./server.ks -storepass server -keyalg RSA -keypass server //2.客户端密库 注意提供者信息和BKS keytool -genkey -keystore ./client.ks -storepass client -keyalg RSA -keypass client -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider //3.服务器导出证书server.crt keytool -exportcert -keystore ./server.ks -storepass server -file ./server.crt //4.客户端导出证书client.crt 注意提供提供者的信息和导出为BKS keytool -exportcert -keystore ./client.ks -storepass client -storetype BKS -file ./client.crt -provider org.bouncycastle.jce.provider.BouncyCastleProvider //5.把客户端证书导入到信任库中,该信任库由客户端持有。详见“PC-PC”那篇文章里的逻辑图 keytool -import -keystore ./tserver.bks -storetype BKS -storepass client -file ./server.crt //6.~略 keytool -import -keystore ./tclient.jks -storetype JKS -storepass server -file ./client.crt
逻辑图建议参考“PC-PC”里的那个,便于理解。
再强调一遍,安卓端的密库必须是BKS,PC端的密库必须是JKS,否者会在握手阶段抛出异常。
>客户端自验证自签名证书
详见:http://blog.csdn.net/u013424496/article/details/51161647
可以先跳过,遇到异常再回来看看。(其实就是重写相关方法,把安卓强制验证写空了而已)
>实例代码:
服务端代码:
import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.Socket; import javax.net.ServerSocketFactory; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; public class ServerSSLTest { static String keystorePath = "你的路径/server.ks"; static String trustKeystorePath = "你的路径/tclient.jks"; static String keystorePassword = "server"; public static void main(String args[]) throws Exception{ //System.setProperty("javax.net.debug", "ssl,handshake"); System.setProperty("javax.net.ssl.keyStore", keystorePath); System.setProperty("javax.net.ssl.keyStorePassword", keystorePassword); System.setProperty("javax.net.ssl.trustStore", trustKeystorePath); System.setProperty("javax.net.ssl.trustStorePassword",keystorePassword); ServerSocketFactory factory = SSLServerSocketFactory.getDefault(); SSLServerSocket serverSocket=(SSLServerSocket) factory.createServerSocket(9100); serverSocket.setNeedClientAuth(false); System.out.println("Server Open"); Socket socket =serverSocket.accept(); BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8")); System.out.println("Server Log:"+in.readLine()); } }
客户端代码:
public void initssl() { try { //取得SSL的SSLContext实例 SSLContext sslContext = SSLContext.getInstance("TLS"); //取得KeyManagerFactory和TrustManagerFactory的X509密钥管理器实例 KeyManagerFactory keyManager = KeyManagerFactory.getInstance("X509"); TrustManagerFactory trustManager = TrustManagerFactory.getInstance("X509"); //取得BKS密库实例 KeyStore ks= KeyStore.getInstance("BKS"); KeyStore tks = KeyStore.getInstance("BKS"); //加客户端载证书和私钥,通过读取资源文件的方式读取密钥和信任证书 ks.load(getBaseContext() .getResources() .openRawResource(R.raw.client),"client".toCharArray());//从raw中获取秘钥库 tks.load(getBaseContext() .getResources() .openRawResource(R.raw.tserver),"client".toCharArray());//从raw中获取信任库 //初始化密钥管理器 keyManager.init(ks,"client".toCharArray()); trustManager.init(tks); //初始化SSLContext sslContext.init(keyManager.getKeyManagers(),trustManager.getTrustManagers(),null); //获取SSLSocket sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket("192.168.1.103",9100); } catch (Exception e) { e.printStackTrace(); } } private SSLSocket sslSocket; Runnable runnable=new Runnable() { @Override public void run() { /* 会抛出信任库异常,不能这么写 System.setProperty("javax.net.ssl.keyStore", keystorePath); System.setProperty("javax.net.ssl.keyStorePassword", keystorePassword); System.setProperty("javax.net.ssl.trustStore", trustKeystorePath); System.setProperty("javax.net.ssl.trustStorePassword",keystorePassword); */ try{ initssl(); System.out.println("Client Connected"); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(sslSocket.getOutputStream(),"UTF-8")); System.out.println("Msg ready"); out.write("This is message:你好"+"\n"); out.flush(); System.out.println("Msg Sended"); }catch (Exception e){ e.printStackTrace(); } } };其中,client.ks和tserver.jks(这里是我命名失误,这两个都是BKS的库,可参见上面那六行命令,打的是bks)放于安卓工程里res/raw文件夹里(如果没有就自己创建一个),如图:
如果想把证书导出到sdcard中做其他操作,见此:http://blog.csdn.net/shenpibaipao/article/details/73032148
服务端输出结果:
>其他参考文章:
http://blog.sina.com.cn/s/blog_792cc4290100syyf.html
http://kb.cnblogs.com/page/162080/
http://www.cnblogs.com/zhujiabin/p/5895079.html
相关文章推荐
- Android客户端与PC服务器通过socket进行交互实例(转)
- Android客户端与PC服务器通过socket进行交互实例
- Android客户端与PC服务器通过socket进行交互实例
- Android客户端与PC服务器通过socket进行交互实例
- Android客户端与PC服务器通过socket进行交互实例
- Android客户端与PC服务器实现Socket通信
- 用Android搭建客户端 手机和服务器交互开发实例
- Android:手机做服务器控制多个手机客户端同时播放音乐(含源码)
- Android客户端与PC服务器实现Socket通信
- Android客户端与PC服务器实现Socket通信(wifi)
- Android客户端通过socket与服务器通信(解决源码使用出现的错误)
- Android客户端与PC服务器实现Socket通信(wifi)
- Android客户端与PC服务器实现Socket通信(wifi)
- python服务器与android客户端socket通信实例
- unity3d Android客户端与PC服务器实现Socket通信(wifi)
- Android笔记 Android客户端从服务器获取源码乱码demo
- unity3d Android客户端与PC服务器实现Socket通信(wifi)
- android客户端访问服务器登录实例
- Android做客户端,PC做服务器端,SSLSocket通信,双向认证
- python服务器与android客户端socket通信实例