Android SSL 过程记录(证书的生成+例子代码)

在用Android平台上使用SSL,第一步就是生成证书。

1、证书的生成

1.1生成服务器端的证书

keytool -genkey -alias test -keystore test.jks
1.2 将keystore中的cert导出来,用来生成客户端的验证证书

keytool -exportcert -alias test -file test.cert -keystore test.jks
1.3 生成Android平台的证书

因为Android 要求要BC证书,而Java的keytool本身不提供BKS格式,因此要自己手动配置。个人在配置的过程到了文件正在使用中,保存失败的情况,我的做法是将文件备份一下,用unlocker删除后将修改好备份放到原位置就好了。

1.3.1 下载 bcprov-ext-jdk15on-146.jar 

可以选择到官网,也可以到我上传好的文件去下载,注意,用最新的149版本的会有证书版本号不对的异常,改用146的则没有这个问题

1.3.2 配置bcprov

在 jdk_home\jre\lib\security\目录中找到 java.security 在内容增加一行(数字可以自己定义)

security.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider
1.3.3 生成android平台的证书

keytool -importcert -keystore test.bks -file test.cert -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
2、编写服务器代码( 代码资源在这里

主要代码(代码不是我原写的,作者已经在注释中标注了,工程文件在这里

import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.net.ServerSocketFactory;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;

/**
 * @author  draem0507@gmail.com
 * @TODO    java线程开发之四 SSL加密
 * 开发步骤
 * 1.生成服务端密钥
 * 2.导出服务端证书
 * 3.生成客户端密钥
 * 4.程序开发测试
 * 关于证书的生成请参考readme.txt
 * 参考资料:http://chrui.iteye.com/blog/1018778
 * @version 1.0
 * @date 2013-5-7 23:22:45    
 * @update 2013-5-8 10:22:45    
 * @blgos http://www.cnblogs.com/draem0507
 */

public class Server {
    private ServerSocket serverSocket;
    private final static char[] password="1qaz2wsx".toCharArray();
    private SSLContext context;
    private InputStream inputStream;
    

    public Server() {
        inputStream=this.getClass().getResourceAsStream("/test.jks");
        initContext();
        try {
            //直接运行会报 javax.net.ssl.SSLException:
            //ServerSocketFactory factory=     SSLServerSocketFactory.getDefault();
            ServerSocketFactory factory=     context.getServerSocketFactory();
//            serverSocket = new ServerSocket(10000);
            serverSocket=factory.createServerSocket(10000);
            System.out.println("======启动安全SocektServer成功=========");
            while (true) {
                Socket socket = serverSocket.accept();
                new ReceiveSocket(socket).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    
    //ssl 上下文对象的初始化
    private void initContext() {
        try {
            KeyStore store=KeyStore.getInstance("JKS");
            store.load(inputStream, password);
            KeyManagerFactory factory=KeyManagerFactory.getInstance("SunX509");
            factory.init(store,password);
            KeyManager []keyManagers=factory.getKeyManagers();
            context=SSLContext.getInstance("SSL");
            context.init(keyManagers, null    , null);
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (UnrecoverableKeyException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        
    }

    public static void main(String[] args) {
        new Server();

    }

    private class ReceiveSocket extends Thread {
        private Socket socket;

        public ReceiveSocket(Socket socket) {
            this.socket = socket;
        }

        private ObjectInputStream reader;
        private ObjectOutputStream writer;

        @Override
        public void run() {

            try {
                reader=new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
                //writer=new ObjectOutputStream(socket.getOutputStream());
                // 开启无限循环 监控消息
                
                    //java.io.EOFException
                Object obj=    reader.readUTF();
                SocketAddress address = socket.getRemoteSocketAddress();
                System.out.println(address.toString() + ">\t" + obj);
//                Object obj=    reader.readObject();
//                    if(obj!=null)
//                    {
//                        User user =(User)obj;
//                        System.out.println("id=="+user.getPassword()+"\tname=="+user.getName());
//                    }
                //    while (true) {}

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (null != reader) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (null != writer) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }

}
3、Android端代码

主要是发送数据的代码

protected Void doInBackground(Void... params) {
			Log.i(TAG, "doInBackground");
			try {
				SSLContext context;
				KeyStore ts = KeyStore.getInstance("BKS");
				ts.load(getResources().openRawResource(R.raw.test),
						"1qaz2wsx".toCharArray());
				TrustManagerFactory tmf = TrustManagerFactory
						.getInstance("X509");
				tmf.init(ts);
				TrustManager[] tm = tmf.getTrustManagers();
				context = SSLContext.getInstance("SSL");
				context.init(null, tm, null);

				SocketFactory factory = context.getSocketFactory();
				SSLSocket socket = (SSLSocket) factory.createSocket(
						"192.168.70.249", 10000);

				ObjectOutputStream out = new ObjectOutputStream(
						socket.getOutputStream());

				out.writeUTF(UUID.randomUUID().toString());
				out.flush();
				System.out.println("========客户端发送成功=========");
				;

				socket.close();
			} catch (Exception ex) {
				ex.printStackTrace();
			}
			return null;
		}

《好了,全文完》

-----感谢http://stackoverflow.com/ -----


版权声明:本文为acnt3w原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。