在Android上实现SSL握手(客户端需要密钥和证书),实现服务器和客户端之间Socket交互

Android的私钥和信任证书的格式必须是BKS格式的,通过配置本地JDK,让keytool可以生成BKS格式的私钥和信任证书,java本身没有BouncyCastle密库

服务端:

Java代码

  1. public class SSLServer {
  2. private static final int SERVER_PORT = 50030;
  3. private static final String SERVER_KEY_PASSWORD = "123456";
  4. private static final String SERVER_AGREEMENT = "TLS";//使用协议
  5. private static final String SERVER_KEY_MANAGER = "SunX509";//密钥管理器
  6. private static final String SERVER_KEY_KEYSTORE = "JKS";//密库,这里用的是Java自带密库
  7. private static final String SERVER_KEYSTORE_PATH = "src/data/kserver.keystore";//密库路径
  8. private SSLServerSocket serverSocket;
  9. public static void main(String[] args) {
  10. SSLServer server = new SSLServer();
  11. server.init();
  12. server.start();
  13. }
  14. //由于该程序不是演示Socket监听,所以简单采用单线程形式,并且仅仅接受客户端的消息,并且返回客户端指定消息
  15. public void start() {
  16. if (serverSocket == null) {
  17. System.out.println("ERROR");
  18. return;
  19. }
  20. while (true) {
  21. try {
  22. System.out.println("Server Side......");
  23. Socket s = serverSocket.accept();
  24. InputStream input = s.getInputStream();
  25. OutputStream output = s.getOutputStream();
  26. BufferedInputStream bis = new BufferedInputStream(input);
  27. BufferedOutputStream bos = new BufferedOutputStream(output);
  28. byte[] buffer = new byte[20];
  29. bis.read(buffer);
  30. System.out.println(new String(buffer));
  31. bos.write("This is Server".getBytes());
  32. bos.flush();
  33. s.close();
  34. } catch (Exception e) {
  35. System.out.println(e);
  36. }
  37. }
  38. }
  39. public void init() {
  40. try {
  41. //取得SSLContext
  42. SSLContext ctx = SSLContext.getInstance(SERVER_AGREEMENT);
  43. //取得SunX509私钥管理器
  44. KeyManagerFactory kmf = KeyManagerFactory.getInstance(SERVER_KEY_MANAGER);
  45. //取得JKS密库实例
  46. KeyStore ks = KeyStore.getInstance(SERVER_KEY_KEYSTORE);
  47. //加载服务端私钥
  48. ks.load(new FileInputStream(SERVER_KEYSTORE_PATH), SERVER_KEY_PASSWORD.toCharArray());
  49. //初始化
  50. kmf.init(ks, SERVER_KEY_PASSWORD.toCharArray());
  51. //初始化SSLContext
  52. ctx.init(kmf.getKeyManagers(),null, null);
  53. //通过SSLContext取得ServerSocketFactory,创建ServerSocket
  54. serverSocket = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket(SERVER_PORT);
  55. } catch (Exception e) {
  56. System.out.println(e);
  57. }
  58. }
  59. }

客户端:

Java代码

    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. }
时间: 2024-10-03 08:23:49

在Android上实现SSL握手(客户端需要密钥和证书),实现服务器和客户端之间Socket交互的相关文章

SSL握手流程

一.SSL是什么? 安全套接字(SSL)协议是Web浏览器和Web服务器之间安全交换信息的协议. SSL介于应用层和TCP层之间,应用层数据不再直接传递给传输层,而是传递给SSL层,SSL层对从应用层收到的数据进行加密,并增加自己的SSL头. History: 1994年,NetScape公司设计了SSL协议(Secure Sockets Layer)的1.0版,但是未发布. 1995年,NetScape公司发布SSL 2.0版,很快发现有严重漏洞. 1996年,SSL 3.0版问世,得到大规模

加密、签名和SSL握手机制细节

1.1 背景知识 对称加密     :加密解密使用同一密钥,加解密速度快.随着人数增多,密钥数量急增n(n-1)/2. 非对称加密 :使用公私钥配对加解密,速度慢.公钥是从私钥中提取出来的,一般拿对方公钥加密来保证数据安全性,拿自己的私钥加密来证明数据来源的身份. 单向加密     :不算是加密,也常称为散列运算,用于生成独一无二的校验码(或称为指纹.特征码)来保证数据的完整性和一致性,如MD5.SHA.具有雪崩效应,任何一点数据的改变,生成的校验码值变化非常大. 互联网数据安全可靠的条件: 1

SSL握手过程详解

转载自http://xeseo.blog.163.com/blog/static/5632431620132843532672/ 1. 客户端发送一个Hello消息给服务器,该消息包含以下参数: * 客户端支持的SSL的版本列表 * 客户端所支持的加密算法列表 * 随机数 ClientHello.random 2.1 服务器端回应一个Hello消息给客户端,该消息包含以下内容: * 握手期间使用的SSL的版本 * 握手期间将使用的密钥交换算法 (Deffie-Hellman算法,基于RSA的密钥

JavaFX打包到Android上

让JavaFX运行到移动平台一直是社区努力完成的事. 当然,目前已经可以让JavaFX运行到Android和IOS平台了,下面我们来看看如何打包自己的JavaFX项目到Android平台. 首先下载下面这个示例: http://pan.baidu.com/s/1bnwIYrP 这个示例是我从打包官方示例的例子里修改而来,用于打包一个简单的JavaFX程序. 示例结构如下: 由目录结构可以看到,示例是采用gradle来构建的.gradle也是国外非常火的自动化构建工具. 在第一次打包的时候,需要双

node.js中通过dgram数据报模块创建UDP服务器和客户端

node.js中 dgram 模块提供了udp数据包的socket实现,可以方便的创建udp服务器和客户端. 一.创建UDP服务器和客户端 服务端: const dgram = require('dgram'); //创建upd套接字 //参数一表示套接字类型,'udp4' 或 'udp6' //参数二表示事件监听函数,'message' 事件监听器 let server = dgram.createSocket('udp4'); //绑定端口和主机地址 server.bind(8888, '1

HTTP服务器与客户端-05

先给各位打个预防针,这篇博客比较长需要各位静下心来看.同时这片博客也是最重要的一个环节.服务和客户端的请求响应方式 HTTP服务器与客户端 Node.js 标准库提供了 http 模块,其中封装了一个高效的 HTTP 服务器和一个简易的HTTP客户端.http.Server 是一个基于事件的 HTTP服务器,它的核心由 Node.js 下层 C++部分实现,而接口由 JavaScript 封装,兼顾了高性能与简易性. http.request 则是一个HTTP 客户端工具,用于向 HTTP 服务

OkHttp还处理了代理服务器问题和SSL握手失败问题

Android系统提供了两种HTTP通信类,HttpURLConnection和HttpClient,HttpURLConnection相对来说比HttpClient难用,google自从2.3版本之后一直推荐使用HttpURLConnection,并且在6.0版本的sdk中直接删掉了HttpClient类. 但是, 上面两个类库和OkHttp比起来就弱爆了, 因为OkHttp不仅具有高效的请求效率,并且节省宽带, 还提供了很多开箱即用的网络疑难杂症解决方案.(据说Android4.4的源码中可

SSL握手过程

一.SSL握手有三个目的:1. 客户端与服务器需要就一组用于保护数据的算法达成一致:2. 它们需要确立一组由那些算法所使用的加密密钥:3. 握手还可以选择对客户端进行认证. 二.SSL握手过程:1. 客户端将它所支持的算法列表和一个用作产生密钥的随机数发送给服务器:2. 服务器从算法列表中选择一种加密算法,并将它和一份包含服务器公用密钥的证书发送给客户端:该证书还包含了用于认证目的的服务器标识,服务器同时还提供了一个用作产生密钥的随机数:3. 客户端对服务器的证书进行验证(有关验证证书,可以参考

Android上发送带附件的邮件

准备工作-下载最新版本的JMail https://java.net/projects/javamail/pages/Home#Download_JavaMail_1.5.2_Release http://www.oracle.com/technetwork/java/javase/downloads/index-135046.html 在android上发送邮件方式: 第一种:借助GMail APP客户端,缺点是必须使用GMail帐号,有点是比较方便 不需要写很多代码,但是不是很灵活. 第二种