【转帖】android平台ssl单双向验证


原文出自:http://blog.csdn.net/hfeng101/article/details/10163627http://blog.csdn.net/hfeng101/article/details/10163627

android平台ssl单双向验证

分类:             JAVA             android开发              2013-08-21 23:51     4672人阅读     评论(16)     收藏     举报

AndroidSSL

最近做android平台ssl通信研究,被坑了好些,最后历经磨难,终于搞定它了,得到的结论:实践才是检验坑有多深的最佳途径!!

看网上的中文资料,提到android ssl通信的也有,但都是零零碎碎,提到双向的实现更少,国外有些资料还可以,推荐stackoverflow,里面有不少探讨android ssl的好帖子,不过是英文的,这个(~~!)就不解释了!

话不多说,开始了。

环境:

服务器:apache服务器,openssl。

客户端:PC、java平台、android平台。

思路:

1、先搞定ssl单向验证,再解决双向。

2、先PC,再java平台,再android,不一定非得这样,自由选择,个人是为了弄清整个流程,多走了些路。

过程步骤:

1、在pc上用apache搭建了一个http服务器,用openssl建立自签名的CA证书ca.crt,签发服务器证书server.crt,签发客户端证书client.crt。(apache+openssl配置ssl通信网上资料很多)

2、安装ca.crt,配置服务器,开启单向验证,用浏览器测试验证单向ssl通信。

3、将client.crt和client.key打包生成pkcs12格式的client.pfx文件。

4、配置服务器,开启双向验证,通过浏览器导入client.pfx文件,测试验证双向ssl通信。

重点:

Java平台默认识别jks格式的证书文件,但是android平台只识别bks格式的证书文件,需要在java中配置BC库,个人推荐参考:http://hi.baidu.com/yaming/item/980f253e17f585be124b142d,配置好BC库,看看有没有keytool工具,没有自己弄个,这个网上资料多。

代码参考:http://momoch1314.iteye.com/blog/540613,由于服务端有apache,上面的代码就不用了,此处列出客户端,此文中是通过socket通信的,建议改成https通信,效果会更好,因为和apache服务器打交道,处理起来会更方便。(里面有些东西需要微调的,希望各位自己改一下,对于某些人来说,可能会有些坑,有疑问,请留言,本屌尽力解答)

  1. public class MySSLSocket extends Activity {
  2. private static final int SERVER_PORT = 50030;//端口号
  3. private static final String SERVER_IP = "218.206.176.146";//连接IP
  4. private static final String CLIENT_KET_PASSWORD = "123456";//私钥密码
  5. private static final String CLIENT_TRUST_PASSWORD = "123456";//信任证书密码
  6. private static final String CLIENT_AGREEMENT = "TLS";//使用协议
  7. private static final String CLIENT_KEY_MANAGER = "X509";//密钥管理器
  8. private static final String CLIENT_TRUST_MANAGER = "X509";//
  9. private static final String CLIENT_KEY_KEYSTORE = "BKS";//密库,这里用的是BouncyCastle密库
  10. private static final String CLIENT_TRUST_KEYSTORE = "BKS";//
  11. private static final String ENCONDING = "utf-8";//字符集
  12. private SSLSocket Client_sslSocket;
  13. private Log tag;
  14. private TextView tv;
  15. private Button btn;
  16. private Button btn2;
  17. private Button btn3;
  18. private EditText et;
  19. /** Called when the activity is first created. */
  20. @Override
  21. public void onCreate(Bundle savedInstanceState) {
  22. super.onCreate(savedInstanceState);
  23. setContentView(R.layout.main);
  24. tv = (TextView) findViewById(R.id.TextView01);
  25. et = (EditText) findViewById(R.id.EditText01);
  26. btn = (Button) findViewById(R.id.Button01);
  27. btn2 = (Button) findViewById(R.id.Button02);
  28. btn3 = (Button) findViewById(R.id.Button03);
  29. btn.setOnClickListener(new Button.OnClickListener(){
  30. @Override
  31. public void onClick(View arg0) {
  32. if(null != Client_sslSocket){
  33. getOut(Client_sslSocket, et.getText().toString());
  34. getIn(Client_sslSocket);
  35. et.setText("");
  36. }
  37. }
  38. });
  39. btn2.setOnClickListener(new Button.OnClickListener(){
  40. @Override
  41. public void onClick(View arg0) {
  42. try {
  43. Client_sslSocket.close();
  44. Client_sslSocket = null;
  45. } catch (IOException e) {
  46. e.printStackTrace();
  47. }
  48. }
  49. });
  50. btn3.setOnClickListener(new View.OnClickListener(){
  51. @Override
  52. public void onClick(View arg0) {
  53. init();
  54. getIn(Client_sslSocket);
  55. }
  56. });
  57. }
  58. public void init() {
  59. try {
  60. //取得SSL的SSLContext实例
  61. SSLContext sslContext = SSLContext.getInstance(CLIENT_AGREEMENT);
  62. //取得KeyManagerFactory和TrustManagerFactory的X509密钥管理器实例
  63. KeyManagerFactory keyManager = KeyManagerFactory.getInstance(CLIENT_KEY_MANAGER);
  64. TrustManagerFactory trustManager = TrustManagerFactory.getInstance(CLIENT_TRUST_MANAGER);
  65. //取得BKS密库实例
  66. KeyStore kks= KeyStore.getInstance(CLIENT_KEY_KEYSTORE);
  67. KeyStore tks = KeyStore.getInstance(CLIENT_TRUST_KEYSTORE);
  68. //加客户端载证书和私钥,通过读取资源文件的方式读取密钥和信任证书
  69. kks.load(getBaseContext()
  70. .getResources()
  71. .openRawResource(R.drawable.kclient),CLIENT_KET_PASSWORD.toCharArray());
  72. tks.load(getBaseContext()
  73. .getResources()
  74. .openRawResource(R.drawable.lt_client),CLIENT_TRUST_PASSWORD.toCharArray());
  75. //初始化密钥管理器
  76. keyManager.init(kks,CLIENT_KET_PASSWORD.toCharArray());
  77. trustManager.init(tks);
  78. //初始化SSLContext
  79. sslContext.init(keyManager.getKeyManagers(),trustManager.getTrustManagers(),null);
  80. //生成SSLSocket
  81. Client_sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket(SERVER_IP,SERVER_PORT);
  82. } catch (Exception e) {
  83. tag.e("MySSLSocket",e.getMessage());
  84. }
  85. }
  86. public void getOut(SSLSocket socket,String message){
  87. PrintWriter out;
  88. try {
  89. out = new PrintWriter(
  90. new BufferedWriter(
  91. new OutputStreamWriter(
  92. socket.getOutputStream()
  93. )
  94. ),true);
  95. out.println(message);
  96. } catch (IOException e) {
  97. e.printStackTrace();
  98. }
  99. }
  100. public void getIn(SSLSocket socket){
  101. BufferedReader in = null;
  102. String str = null;
  103. try {
  104. in = new BufferedReader(
  105. new InputStreamReader(
  106. socket.getInputStream()));
  107. str = new String(in.readLine().getBytes(),ENCONDING);
  108. } catch (UnsupportedEncodingException e) {
  109. e.printStackTrace();
  110. } catch (IOException e) {
  111. e.printStackTrace();
  112. }
  113. new AlertDialog
  114. .Builder(MySSLSocket.this)
  115. .setTitle("服务器消息")
  116. .setNegativeButton("确定", null)
  117. .setIcon(android.R.drawable.ic_menu_agenda)
  118. .setMessage(str)
  119. .show();
  120. }
  121. }

单向:

1、用keytool将ca.crt导入到bks格式的证书库ca.bks,用于验证服务器的证书,命令如下:

keytool -import -alias ca -file ca.crt -keystore ca.bks -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider

2、服务器配置成单向验证,将ca.bks放到android工程的assets或raw下,对应的读取就是代码中的

  1. kks.load(getBaseContext()
  2. .getResources()
  3. .openRawResource(R.drawable.kclient),CLIENT_KET_PASSWORD.toCharArray());

不一定是R.drawable.kclient,自己根据实际做修改,读取文件,不懂网上查,不啰嗦了。

至此,单向ssl通信应该是OK了。

(PS: 针对2中的操作不一定非得这么做,也可以把ca.bks导入到android平台下的cacerts.bks文件中,然后从这个文件读取认证,怎么导入,网上资料很多,如:http://blog.csdn.net/haijun286972766/article/details/6247675

调试中遇到的问题,提一下:

一般在模拟器中能通过,在真实平台上就没问题了。

个人遇到一个最蛋疼的问题是模拟器上通过了,但真实平台就是报错,卡了好几天,查了好多资料没查到,网上也有类似的提问,但没有靠谱的解答,最后硬着头皮终于查出来是真实平台的时间不对,2007年,不在证书的有效期内,就一个感受:坑!!

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

双向:

双向在单向的基础上实现,不过要先生成android平台能识别的客户端证书,这个玩意也伤脑筋,网上提到生成bks格式客户端证书的资料很少,鲜有借鉴之用。

在这个点上,太伤脑筋了,估计很多伙计也在这儿卡得蛋疼,一开始是毫无头绪,在PC、JAVA平台上生成客户端证书,都能测通,但是转到android平台就傻眼了,用keytool将其它工具生成的crt证书,导成bks格式,不通;用keytool工具新生成bks格式证书,也不通;

各种能想的方法试尽,一度怀疑自己是不是哪个细节出错了,理论上肯定能做的东西,怎么看不到一点可实现性,找资料连续几天,一点进展都没。

后面看国外的资料上提到先用openssl生成pkcs12的.pfx格式证书,然后用工具portecle转换成BKS格式,在android平台上使用,一开始是直接强制性转换,出错,怎么转都转不成功,但是转换成jks格式又没问题,只能根据提示错误,找解决方案,试了好多还是不行,又迷茫了;

1、最后看到国外的资料上的一句话,顿悟灵光,用portecle工具,先建立一个bks格式的keystore,然后将client.pfx中的key pair导入(import key pair),再保存bks文件,测试成功,事实证明:二了一点。

PS:用portecle直接转应该是可以的,只是我一直没转成功过,可能是我的java环境有问题,老提示illegal key size。

2、将服务器配置成双向验证,将ca.bks放到android工程的assets或raw下,对应的读取就是代码中的

  1. tks.load(getBaseContext()
  2. .getResources()
  3. .openRawResource(R.drawable.lt_client),CLIENT_TRUST_PASSWORD.toCharArray());

至此,问题基本搞定,不过个人还有个心瘤,理论上用keytool生成bks格式的证书再使用,但是个人各种方法试尽,仍旧没有结果,网上也没找到资料,原谅我的无能,如果有能实现的,麻烦分享一下,感激不尽!!!

太晚了,洗洗睡鸟,写得有点糙,如有疑问:留言解答!!

http://momoch1314.iteye.com/blog/540613

时间: 2024-10-07 04:11:03

【转帖】android平台ssl单双向验证的相关文章

Android平台实现SSL单双向验证

环境:服务器:apache服务器,openssl. 客户端:PC.java平台.android平台. 思路: 1.先搞定ssl单向验证,再解决双向. 2.先PC,再java平台,再android,不一定非得这样,自由选择,个人是为了弄清整个流程,多走了些路. 过程步骤: 1.在pc上用apache搭建了一个http服务器,用openssl建立自签名的CA证书ca.crt,签发服务器证书server.crt,签发客户端证书client.crt.(apache+openssl配置ssl通信网上资料很

java实现ssl单/双向认证通信[推荐]

有关SSL的原理和介绍在网上已经有不少,对于Java下使用keytool生成证书,配置SSL通信的教程也非常多.但如果我们不能够亲自动手做一个SSL Sever和SSL Client,可能就永远也不能深入地理解Java环境下,SSL的通信是如何实现的.对SSL中的各种概念的认识也可能会仅限于可以使用的程度.本文通过构造一个简单的SSL Server和SSL Client来讲解Java环境下SSL的通信原理. 首先我们先回顾一下常规的Java Socket编程.在Java下写一个Socket服务器

ssl/https双向验证的配置与证书库的生成

1.SSL认证 不需要特别配置,相关证书库生成看https认证中的相关部分 2.HTTPS认证 一.基本概念 1.单向认证,就是传输的数据加密过了,但是不会校验客户端的来源 2.双向认证,如果客户端浏览器没有导入客户端证书,是访问不了web系统的,找不到地址 如果只是加密,我感觉单向就行了. 如果想要用系统的人没有证书就访问不了系统的话,就采用双向 二.服务器配置: 打开Tomcat 根目录下的 /conf/server.xml 修改server.xml 客户端证书注册名称必须与域名一致,否则无

Apache SSL单双向证书认证

要求目标用户(系统)安装自己的CA根证书,效果是一样的,还可以省下请权威CA签发证书的费用下面就介绍如何创建自己的CA 1.准备工作 先在/etc/httpd/conf创建子目录: private certificates 其中private放的是私钥和CSR(后面会介绍),certificates里放的就是证书了 2.创建CA私钥 Openssl代码   openssl genrsa -out private/ca.key.pem 2048 通过这个命令,私钥就创建好了,文件名是ca.key.

tomcat https/ssl 服务配置(带有双向验证,windows,linux平台验证通过)

1. 创建服务器密钥,其密钥库为 /home/gr/server.ks PS1: 注意keypass和storepass保持一致,它们分别代表 密钥密码和密钥库密码, PS2: 注意 CN=localhost 中,localhost表示要配置SSL的主机名,不能任意指定 ~$keytool -genkey -v -alias serverKey -dname "CN=192.168.10.101" -keyalg RSA -keypass 123456 -keystore server

[转帖]nginx配置ssl加密(单/双向认证、部分https)

nginx配置ssl加密(单/双向认证.部分https) https://segmentfault.com/a/1190000002866627 nginx下配置ssl本来是很简单的,无论是去认证中心买SSL安全证书还是自签署证书,但最近公司OA的一个需求,得以有个机会实际折腾一番.一开始采用的是全站加密,所有访问http:80的请求强制转换(rewrite)到https,后来自动化测试结果说响应速度太慢,https比http慢慢30倍,心想怎么可能,鬼知道他们怎么测的.所以就试了一下部分页面h

Loadrunner对https协议(单双向SSL)的web端性能测试

1.项目背景 1.1 单双向SSL的含义及部署 单向SSL即我们说到的https协议. 特点是,浏览器需要请求验证服务器证书: 基本含义是:一个安全通信通道,它基于HTTP开发,用于在客户计算机和服务器之间交换信息.它使用安全套接字层(SSL)进行信息交换,简单来说它是HTTP的安全版. 双向SSL顾名思义就是双方都需要验证证书的协议,浏览器首先向服务端请求证书,然后服务器端需要向浏览器请求目前登陆用户的个人证书验证. 1.2 系统的基本部署 单向SSL交互过程: 使用单向SSL时,仅通过虚拟主

使用loadrunner对https协议(单双向SSL)的web端性能测试 (转)

1.项目背景 1.1 单双向SSL的含义及部署 单向SSL即我们说到的https协议. 特点是,浏览器需要请求验证服务器证书: 基本含义是:一个安全通信通道,它基于HTTP开发,用于在客户计算机和服务器之间交换信息.它使用安全套接字层(SSL)进行信息交换,简单来说它是HTTP的安全版. 双向SSL顾名思义就是双方都需要验证证书的协议,浏览器首先向服务端请求证书,然后服务器端需要向浏览器请求目前登陆用户的个人证书验证. 1.2 系统的基本部署 单向SSL交互过程: 使用单向SSL时,仅通过虚拟主

[转帖] cocos2dx项目移植android平台使用第三方so库被删掉的问题

原文地址: http://www.2cto.com/kf/201408/329559.html cocos2dx项目android平台在编译的时候会把libs/armeabi目录清空,这就是为什么我们编译的时候导入的第三方so库会被删掉的原因. 解决方案: 1. 在jni目录下新建prebuilt目录,并把要使用的第三方so库复制到该目录: 2.修改jni/Android.mk文件如下: ok!搞定!