SSL+Socket 初步整理

SSL概念

SSL(Secure Sockets Layer,安全套接层),安全套接层是Netscape公司率先采用的网络安全协议。它是在传输通信协议(TCP/IP)上实现的一种安全协议,采用公开密钥技术。SSL广泛支持各种类型的网络,同时提供三种基本的安全服务,它们都使用公开密钥技术。

其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层对网络连接进行加密。

Socket概念

网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。

建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。

Socket的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取后一种意思。通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原义那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110伏交流电,有的则提供有线电视节目。 客户软件将插头插到不同编号的插座,就可以得到不同的服务。

客户端证书生成

服务端给我们一个服务端的.pem格式的证书,通过Java指令将服务端证书添加到我们的密钥库中,生成我们的证书
keytool -import -alias 别名 -file 服务端证书路径 -storetype 密钥库(如 :JKS、BKS) -storepass 密码 -keystore (路径非必需)+ 文件名 -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-ext-jdk15on-1.46.jar(换成自己的jar)

这里的storetype如果是Java服务用JKS,Android用BKS
后边的provider如果不用的话可能会在加载密钥库的时候出错,并且后边用的jar包如果1.46不可以的话可以换换版本试试,比如1.45。

代码实现

  1. 准备好必要的参数
private static final int SERVER_PORT = 0000;//端口号
private static final String SERVER_IP = "00.000.000.00";//连接IP
private static final String CLIENT_KET_PASSWORD = "000000";//私钥密码
private static final String CLIENT_TRUST_PASSWORD = "000000";//信任证书密码
private static final String CLIENT_AGREEMENT = "TLS";//使用协议
private static final String CLIENT_KEY_MANAGER = "X509";//密钥管理器(如果是Java服务此处为SunX509)
private static final String CLIENT_TRUST_MANAGER = "X509";//
private static final String CLIENT_KEY_KEYSTORE = "BKS";//密库,这里用的是BouncyCastle密库(Java服务为JKS)
private static final String CLIENT_TRUST_KEYSTORE = "BKS";//    
  1. 生成SSLSocket对象
public void init(Context context) {
    try {
        //取得KeyManagerFactory和TrustManagerFactory的X509密钥管理器实例
        KeyManagerFactory keyManager = KeyManagerFactory.getInstance(CLIENT_KEY_MANAGER);
        TrustManagerFactory trustManager = TrustManagerFactory.getInstance(CLIENT_TRUST_MANAGER);
        //取得BKS密库实例
        KeyStore kks = KeyStore.getInstance(CLIENT_KEY_KEYSTORE);
        KeyStore tks = KeyStore.getInstance(CLIENT_TRUST_KEYSTORE);
        //加客户端载证书和私钥,通过读取资源文件的方式读取密钥和信任证书
        kks.load(context
                .getResources()
                .openRawResource(R.raw.keyclient), CLIENT_KET_PASSWORD.toCharArray());
        tks.load(context
                .getResources()
                .openRawResource(R.raw.keyclient), CLIENT_TRUST_PASSWORD.toCharArray());
        //初始化密钥管理器
        keyManager.init(kks, CLIENT_KET_PASSWORD.toCharArray());
        trustManager.init(tks);

        //取得SSL的SSLContext实例
        SSLContext sslContext = SSLContext.getInstance(CLIENT_AGREEMENT);
        //初始化SSLContext
        sslContext.init(keyManager.getKeyManagers(), trustManager.getTrustManagers(), null);

        //生成SSLSocket
        Client_sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket(SERVER_IP, SERVER_PORT);
        Client_sslSocket.setNeedClientAuth(true);
    } catch (Exception e) {
        e.printStackTrace();
    }
} 
  1. 发送数据
public void write(String body){
        try {
            byte data[] = dataProcessing(body);
            if (data == null || data.length == 0)
                throw new NullPointerException("数据处理出错!");
            //取出长度
            // int length = bys[0] << 8 & 0xFF00 | bys[1] & 0xFF;
            OutputStream outputStream = Client_sslSocket.getOutputStream();
            outputStream.write(data);
            // 发送读取的数据到服务端
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            Log.e(this.getClass().getName(),"OutputStream获取失败!");
        }

    }
  1. 读取数据
public String read(){
        try{
            InputStream in = Client_sslSocket.getInputStream();
            byte buffer[] = new byte[1024];
            int temp = 0;
            int count = 0;
            temp = in.read(buffer);
            String str = "";
            if(temp != -1){
               //前两位表示返回数据的长度 11是拼接的固定头数据,如果没有不用减11
                int length = buffer[0] << 8 & 0xFF00 | buffer[1] & 0xFF;
                byte[] result = new byte[length - 11];
                if (length < 1022){
                    System.arraycopy(buffer,13,result,0,length - 11);
                }else {
                    System.arraycopy(buffer,13,result,0,1011);//1011 = 1024 - 11 - 2;
                    while ((temp = in.read(buffer)) != -1){
                        System.arraycopy(buffer,0,result,1011 + count * 1024,temp);
                        count++;
                    }
                }
               str = new String(result, "UTF-8");
            }
            
            in.close();
            return str;
        } catch (UnsupportedEncodingException e) {
            Log.e(this.getClass().getName(),"数据编码格式错误!");
        } catch (IOException e) {
            Log.e(this.getClass().getName(),"InputStream获取失败!");
        }
        return "";
    }

5.关闭连接

public void close(){
        try {
            Client_sslSocket.close();
        } catch (IOException e) {
            Log.e(this.getClass().getName(),"连接关闭失败" + "  :" + e.getMessage().toString());
        }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容