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

来源:互联网 发布:服务器返回的数据错误 编辑:程序博客网 时间:2024/06/04 18:22
最近项目需求需要用到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了。  

                                

                            


源码下载





原创粉丝点击