TCP传输中使用AES加密和gizp压缩

最近项目需求需要用到TCP传输,为了保证安全传输使用AES,为了使 传输过程中减 数据量小,使用gzip压缩,特此分享一哈。
一、AES加密

关于AES的资料网上很多,个人觉得《加密与解密(第三版)》很不错,这本书中P155开始讲AES 下载地址:http://download.csdn.net/detail/qiwenmingshiwo/8755683

AES加解密算法的模式介绍 http://blog.csdn.NET/searchsun/article/details/2516191

这个过程中我们使用 bcprov 这个jar包,官网: http://www.bouncycastle.org/  
1. 我们秘钥的定义:



1
2
3
4
5
6
7
8
9
10
11
12
13
14
public final static CipherParameters keyParams1 = new ParametersWithIV(
            new KeyParameter(new byte[] { (byte0x01, (byte0x01,
                    (byte0x01, (byte0x01, (byte0x01, (byte0x01,
                    (byte0x01, (byte0x01, (byte0xab, (byte0x01,
                    (byte0x01, (byte0x01, (byte0x01, (byte0x01,
                    (byte0x01, (byte0x01, (byte0x01, (byte0x01,
                    (byte0x01, (byte0x01, (byte0x01, (byte0x01,
                    (byte0x01, (byte0xfc, (byte0x01, (byte0x01,
                    (byte0x01, (byte0xed, (byte0x01, (byte0x01,
                    (byte0x01, (byte0x01 }), new byte[] { (byte0x01,
                    (byte0x01, (byte0x01, (byte0x01, (byte0x01,
                    (byte0x01, (byte0x01, (byte0x01, (byte0x01,
                    (byte0x01, (byte0x01, (byte0x01, (byte0x01,
                    (byte0x01, (byte0xcf, (byte0x01 });




2.加密方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
     /**
     * AES加密
     * @param data数据
     * @return
     * @throws InvalidCipherTextException
     */
    public static byte[] encrypt(byte[] data) throws InvalidCipherTextException
    {
        BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()));
        cipher.init(true, keyParams);//秘钥
        byte[] encrypt = new byte[cipher.getOutputSize(data.length)];
        int size = cipher.processBytes(data, 0, data.length, encrypt, 0);
        byte[] encrypted = new byte[size + cipher.doFinal(encrypt, size)];
        System.arraycopy(encrypt, 0, encrypted, 0, encrypted.length);
        return encrypted;
    }


二、AES解密
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    /**
     * AES解密
     * @param data数据
     * @return
     * @throws InvalidCipherTextException
     */
    public static byte[] decrypt(byte[] data) throws InvalidCipherTextException
    {
        BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()));
        cipher.init(false, keyParams);//
        byte[] decrypt = new byte[cipher.getOutputSize(data.length)];
        int length = cipher.processBytes(data, 0, data.length, decrypt, 0);
        byte[] decrypted = new byte[length + cipher.doFinal(decrypt, length)];
        System.arraycopy(decrypt, 0, decrypted, 0, decrypted.length);
        return decrypted;
    }

三、Gizp压缩和解压缩

这一个部分网上有很多,比如下面这个大神的。
Java压缩技术(四) GZIP——Java原生实现
1. 压缩
    1. /** 
    2.  * 数据压缩 
    3.  *  
    4.  * @param is 
    5.  * @param os 
    6.  * @throws Exception 
    7.  */  
    8. public static void compress(InputStream is, OutputStream os)  
    9.         throws Exception {  
    10.   
    11.     GZIPOutputStream gos = new GZIPOutputStream(os);  
    12.   
    13.     int count;  
    14.     byte data[] = new byte[BUFFER];  
    15.     while ((count = is.read(data, 0, BUFFER)) != -1) {  
    16.         gos.write(data, 0, count);  
    17.     }  
    18.   
    19.     gos.finish();  
    20.   
    21.     gos.flush();  
    22.     gos.close();  
    23. }  

2.解压缩
  1. /** 
  2.  * 数据解压缩 
  3.  *  
  4.  * @param is 
  5.  * @param os 
  6.  * @throws Exception 
  7.  */  
  8. public static void decompress(InputStream is, OutputStream os)  
  9.         throws Exception {  
  10.   
  11.     GZIPInputStream gis = new GZIPInputStream(is);  
  12.   
  13.     int count;  
  14.     byte data[] = new byte[BUFFER];  
  15.     while ((count = gis.read(data, 0, BUFFER)) != -1) {  
  16.         os.write(data, 0, count);  
  17.     }  
  18.   
  19.     gis.close();  
  20. }  

四、简单示例
我们创建一个java程序模拟后台,创建一个android程序当做客户端。

1.后台(java控制台程序模拟)
    主程序部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
 * @author xiaoming
 * @time 2015年5月30日 下午5:01:01
 * @说明 AesDemo
 */
public class AesDemo {
 
    public static void main(String[] args) {
 
        test();
 
    }
 
    public static void test() {
        ServerSocket ss = null;
        Socket s  = null;
        DataInputStream dis = null;
        DataOutputStream dos = null;
        try {
            ss = new ServerSocket(10000);
            s = ss.accept();
            //========================获取请求部分==========================
            dis = new DataInputStream(s.getInputStream());
            //读取数据
            byte[] recData = (new TcpUtil()).readData(dis);
            System.out.println("长度:" + recData.length);
            // //解压缩
            byte[] uncompress = GZipUtils.decompress(recData);
            // 解密
            byte[] decrypt = AESUtil.decrypt(uncompress);
            System.out.println("解密前:" new String(uncompress));
            System.out.println("解密后:" new String(decrypt));
             
            //======================响应部分================================
            dos = new DataOutputStream(s.getOutputStream());
            byte[] respData = "傻逼傻逼蹦擦擦".getBytes();
            // 加密
            byte[] encrypt = AESUtil.encrypt(respData);
            // //压缩
            byte[] compress = GZipUtils.compress(encrypt);
            dos.writeInt(compress.length);// 把数据的长度写过去
            dos.write(compress);
            dos.flush();
            s.shutdownOutput();
        catch (InvalidCipherTextException e) {
            e.printStackTrace();
        catch (IOException e) {
            e.printStackTrace();
        catch (Exception e) {
            e.printStackTrace();
        finally {
            try {
                // 关闭资源
                if (dis != null) {
                    dis.close();
                }
                if (dos != null) {
                    dos.close();
                }
                if (s != null) {
                    s.close();
                }
                if (ss != null) {
                    ss.close();
                }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
 
}


上面读取数据时候使用的:   byte [] recData = ( new   TcpUtil()).readData(dis);进行了封装。TcpUtil类如下:   

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
 * @author qiwenming
 * @time 2015年5月30日 下午4:16:45
 * @说明 Tcp请求的工具类 简单的实现一哈
 */
public class TcpUtil {
 
    /**
     * 读取数据
     * @throws IOException 
     */
    public static byte[] readData(DataInputStream dis) throws IOException{
        //数据的长度
        int length = dis.readInt();
        int tmpLength = 1024// 每次读取最大缓冲区大小
        byte[] ret = new byte[length];//读取到流
        int readed = 0, offset = 0, left = length;
        byte[] bs = new byte[tmpLength];
        while (left > 0)
        {
            try
            {
                readed = dis.read(bs, 0, Math.min(tmpLength, left));
                if (readed == -1)
                    break;
                System.arraycopy(bs, 0, ret, offset, readed);
            }
            finally
            {
                offset += readed;
                left -= readed;
            }
        }
        return ret;
    }
     
}

2.android端


我们主要请求一个数据使一哈。

Activiy中的主要代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
    /**
     * 测试一哈
     * @param v
     */
    public void toTest(View v){
        String resMsg = "写代码真累";
        reqCleEdt.setText(resMsg);
        try {
            byte[] reqData = resMsg.getBytes(); 
            //加密
            byte[] encrypt =AESUtil.encrypt(reqData);
            reqCipEdt.setText(new String(encrypt));
            //压缩
            final byte[] compress = GZipUtils.compress(encrypt);
            new Thread(){
                public void run() {
                    try {
                        byte[] respData = new TcpUtil().requstData(compress);
                     
                        //解压缩
                          final byte[] uncompress = GZipUtils.decompress(respData);
                        //解密
                        final byte[] decrypt = AESUtil.decrypt(uncompress);
                         
                        runOnUiThread(new Runnable() {
                            public void run() {
                                respCleEdt.setText(new String(decrypt));
                                respCipEdt.setText(new String(uncompress));
                            }
                        });
                    catch (InvalidCipherTextException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                };
            }.start();
             
         
        catch (InvalidCipherTextException e) {
            e.printStackTrace();
        catch (Exception e) {
            e.printStackTrace();
        }
    }

上面用到的获取响应数据的方法:byte[] respData = new TcpUtil().requstData(compress);我进行了封装,如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/**
  * @author qiwenming
  * @time 2015年5月30日 下午4:16:45
  * @说明 Tcp请求的工具类 简单的实现一哈
  */
public  class  TcpUtil {
 
     private  OutputStream outputStream;
     private  InputStream inputStream;
     private  Socket socket;
     
     /**
      * 请求数据
      * @return 
      */
     public  byte [] requstData( byte [] data)  throws  Exception{
         try {
             if (socket== null ){
                 socket =  new  Socket( "192.168.1.106" , 10000 );
             }
             outputStream = socket.getOutputStream();
             DataOutputStream dos =  new  DataOutputStream(outputStream);
             dos.writeInt(data.length);
             dos.write(data); //把数据的长度写过去
             dos.flush();
             socket.shutdownOutput(); //数据发完
             byte [] recData = responseData();
             return  recData;
         } finally {
         //  disconnect();
         }
         
     }
     
     /**
      * 响应的数据
      * @throws IOException 
      */
     public  byte [] responseData()  throws  IOException{
         inputStream = socket.getInputStream();
         DataInputStream dis =  new  DataInputStream(inputStream);
         //数据的长度
         int  length = dis.readInt();
         int  tmpLength =  1024 // 每次读取最大缓冲区大小
         byte [] ret =  new  byte [length]; //读取到流
         int  readed =  0 , offset =  0 , left = length;
         byte [] bs =  new  byte [tmpLength];
         while  (left >  0 )
         {
             try
             {
                 readed = dis.read(bs,  0 , Math.min(tmpLength, left));
                 if  (readed == - 1 )
                     break ;
                 System.arraycopy(bs,  0 , ret, offset, readed);
             }
             finally
             {
                 offset += readed;
                 left -= readed;
             }
         }
         return  ret;
     }
     
     /**
      * 关闭资源
      * @throws IOException
      */
     public  void  disconnect()  throws  IOException
     {
         if  (outputStream !=  null )
         {
             outputStream.close();
         }
         if  (inputStream !=  null )
         {
             inputStream.close();
         }
         if  (socket !=  null  && !socket.isClosed())
         {
             socket.shutdownInput();
             socket.shutdownOutput();
             socket.close();
         }
     }
}


五、运行结果
如果你在使用的使用GZIP压缩错误的话,使用第三方的包(commons-compress),就ok了。  

                                

                            


源码下载





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值