Android客户端的SSLSocket通信实例源码(PC做服务器、BKS密库)
来源:互联网 发布:淘宝怎么出租游戏账号 编辑:程序博客网 时间:2024/05/11 21:24
>基本知识
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.客户端密库 注意提供者信息和BKSkeytool -genkey -keystore ./client.ks -storepass client -keyalg RSA -keypass client -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider//3.服务器导出证书server.crtkeytool -exportcert -keystore ./server.ks -storepass server -file ./server.crt//4.客户端导出证书client.crt 注意提供提供者的信息和导出为BKSkeytool -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客户端的SSLSocket通信实例源码(PC做服务器、BKS密库)
- Android做客户端,PC做服务器端,SSLSocket通信,双向认证
- android SSLsocket建立连接,不需要非要使用.bks类型的证书秘钥文件
- android如何使用bks和apache服务器进行https通信
- android客户端与服务器socket通信实例
- Android客户端与PC服务器实现Socket通信(wifi)
- Android客户端与PC服务器实现Socket通信(wifi)
- Android客户端与PC服务器实现Socket通信(wifi)
- Android客户端与PC服务器实现Socket通信(wifi)
- Android客户端与PC服务器实现Socket通信
- unity3d Android客户端与PC服务器实现Socket通信(wifi)
- unity3d Android客户端与PC服务器实现Socket通信(wifi)
- unity3d Android客户端与PC服务器实现Socket通信(wifi)
- Android客户端与PC服务器实现Socket通信(wifi)
- Android客户端与PC服务器实现Socket通信
- unity3d Android客户端与PC服务器实现Socket通信(wifi)
- Android客户端与PC服务器如何实现Socket通信
- Android作为服务器与PC作为客户端通过USB通信
- 修改和编译spring源码,构建jar(spring-context-4.0.2.RELEASE)
- 最长无重复字符子串
- VR系列——Oculus Rift 开发者指南:四、高级渲染配置(三)
- 初学数据结构---直接插入排序
- 一分钟了解“Matlab中求散度函数divergence”
- Android客户端的SSLSocket通信实例源码(PC做服务器、BKS密库)
- Error creating bean with name 'simpleUrlHandlerMapping' defined in ServletContext resource [/WEB-IN
- Java comparable和Comparator接口的区别
- 图像处理之图像分割之Snake算法简单梳理
- linux MMU
- sql基本增删改查
- AJAX异步请求
- java内存泄漏的定位与分析
- c语言练习(4)--逗号分割字符串形成二维数组