最近项目需求需要用到TCP传输,为了保证安全传输使用AES,为了使传输过程中减数据量小,使用gzip压缩,特此分享一哈。
二、AES解密
一、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. 我们秘钥的定义:
1234567891011121314publicfinalstaticCipherParameters keyParams1 =newParametersWithIV(newKeyParameter(newbyte[] { (byte)0x01, (byte)0x01,(byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01,(byte)0x01, (byte)0x01, (byte)0xab, (byte)0x01,(byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01,(byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01,(byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01,(byte)0x01, (byte)0xfc, (byte)0x01, (byte)0x01,(byte)0x01, (byte)0xed, (byte)0x01, (byte)0x01,(byte)0x01, (byte)0x01}),newbyte[] { (byte)0x01,(byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01,(byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01,(byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01,(byte)0x01, (byte)0xcf, (byte)0x01});
2.加密方法
12345678910111213141516/*** AES加密* @param data数据* @return* @throws InvalidCipherTextException*/publicstaticbyte[] encrypt(byte[] data)throwsInvalidCipherTextException{BufferedBlockCipher cipher =newPaddedBufferedBlockCipher(newCBCBlockCipher(newAESEngine()));cipher.init(true, keyParams);//秘钥byte[] encrypt =newbyte[cipher.getOutputSize(data.length)];intsize = cipher.processBytes(data,0, data.length, encrypt,0);byte[] encrypted =newbyte[size + cipher.doFinal(encrypt, size)];System.arraycopy(encrypt,0, encrypted,0, encrypted.length);returnencrypted;}
二、AES解密
12345678910111213141516/*** AES解密* @param data数据* @return* @throws InvalidCipherTextException*/publicstaticbyte[] decrypt(byte[] data)throwsInvalidCipherTextException{BufferedBlockCipher cipher =newPaddedBufferedBlockCipher(newCBCBlockCipher(newAESEngine()));cipher.init(false, keyParams);//byte[] decrypt =newbyte[cipher.getOutputSize(data.length)];intlength = cipher.processBytes(data,0, data.length, decrypt,0);byte[] decrypted =newbyte[length + cipher.doFinal(decrypt, length)];System.arraycopy(decrypt,0, decrypted,0, decrypted.length);returndecrypted;}
三、Gizp压缩和解压缩
这一个部分网上有很多,比如下面这个大神的。Java压缩技术(四) GZIP——Java原生实现
1. 压缩
- /**
- * 数据压缩
- *
- * @param is
- * @param os
- * @throws Exception
- */
- public static void compress(InputStream is, OutputStream os)
- throws Exception {
- GZIPOutputStream gos = new GZIPOutputStream(os);
- int count;
- byte data[] = new byte[BUFFER];
- while ((count = is.read(data, 0, BUFFER)) != -1) {
- gos.write(data, 0, count);
- }
- gos.finish();
- gos.flush();
- gos.close();
- }
2.解压缩
- /**
- * 数据解压缩
- *
- * @param is
- * @param os
- * @throws Exception
- */
- public static void decompress(InputStream is, OutputStream os)
- throws Exception {
- GZIPInputStream gis = new GZIPInputStream(is);
- int count;
- byte data[] = new byte[BUFFER];
- while ((count = gis.read(data, 0, BUFFER)) != -1) {
- os.write(data, 0, count);
- }
- gis.close();
- }
四、简单示例
我们创建一个java程序模拟后台,创建一个android程序当做客户端。1.后台(java控制台程序模拟)主程序部分
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071/*** @author xiaoming* @time 2015年5月30日 下午5:01:01* @说明 AesDemo*/publicclassAesDemo {publicstaticvoidmain(String[] args) {test();}publicstaticvoidtest() {ServerSocket ss =null;Socket s =null;DataInputStream dis =null;DataOutputStream dos =null;try{ss =newServerSocket(10000);s = ss.accept();//========================获取请求部分==========================dis =newDataInputStream(s.getInputStream());//读取数据byte[] recData = (newTcpUtil()).readData(dis);System.out.println("长度:"+ recData.length);// //解压缩byte[] uncompress = GZipUtils.decompress(recData);// 解密byte[] decrypt = AESUtil.decrypt(uncompress);System.out.println("解密前:"+newString(uncompress));System.out.println("解密后:"+newString(decrypt));//======================响应部分================================dos =newDataOutputStream(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 = (newTcpUtil()).readData(dis);进行了封装。TcpUtil类如下:
12345678910111213141516171819202122232425262728293031323334353637/*** @author qiwenming* @time 2015年5月30日 下午4:16:45* @说明 Tcp请求的工具类 简单的实现一哈*/publicclassTcpUtil {/*** 读取数据* @throws IOException*/publicstaticbyte[] readData(DataInputStream dis)throwsIOException{//数据的长度intlength = dis.readInt();inttmpLength =1024;// 每次读取最大缓冲区大小byte[] ret =newbyte[length];//读取到流intreaded =0, offset =0, left = length;byte[] bs =newbyte[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;}}returnret;}}
2.android端
我们主要请求一个数据使一哈。
Activiy中的主要代码:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647/*** 测试一哈* @param v*/publicvoidtoTest(View v){String resMsg ="写代码真累";reqCleEdt.setText(resMsg);try{byte[] reqData = resMsg.getBytes();//加密byte[] encrypt =AESUtil.encrypt(reqData);reqCipEdt.setText(newString(encrypt));//压缩finalbyte[] compress = GZipUtils.compress(encrypt);newThread(){publicvoidrun() {try{byte[] respData =newTcpUtil().requstData(compress);//解压缩finalbyte[] uncompress = GZipUtils.decompress(respData);//解密finalbyte[] decrypt = AESUtil.decrypt(uncompress);runOnUiThread(newRunnable() {publicvoidrun() {respCleEdt.setText(newString(decrypt));respCipEdt.setText(newString(uncompress));}});}catch(InvalidCipherTextException e) {// TODO Auto-generated catch blocke.printStackTrace();}catch(Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}};}.start();}catch(InvalidCipherTextException e) {e.printStackTrace();}catch(Exception e) {e.printStackTrace();}}
上面用到的获取响应数据的方法:
byte[] respData =newTcpUtil().requstData(compress);我进行了封装,如下:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687/*** @author qiwenming* @time 2015年5月30日 下午4:16:45* @说明 Tcp请求的工具类 简单的实现一哈*/publicclassTcpUtil {privateOutputStream outputStream;privateInputStream inputStream;privateSocket socket;/*** 请求数据* @return*/publicbyte[] requstData(byte[] data)throwsException{try{if(socket==null){socket =newSocket("192.168.1.106",10000);}outputStream = socket.getOutputStream();DataOutputStream dos =newDataOutputStream(outputStream);dos.writeInt(data.length);dos.write(data);//把数据的长度写过去dos.flush();socket.shutdownOutput();//数据发完byte[] recData = responseData();returnrecData;}finally{// disconnect();}}/*** 响应的数据* @throws IOException*/publicbyte[] responseData()throwsIOException{inputStream = socket.getInputStream();DataInputStream dis =newDataInputStream(inputStream);//数据的长度intlength = dis.readInt();inttmpLength =1024;// 每次读取最大缓冲区大小byte[] ret =newbyte[length];//读取到流intreaded =0, offset =0, left = length;byte[] bs =newbyte[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;}}returnret;}/*** 关闭资源* @throws IOException*/publicvoiddisconnect()throwsIOException{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了。![]()