最近项目需求需要用到TCP传输,为了保证安全传输使用AES,为了使
传输过程中减
数据量小,使用gzip压缩,特此分享一哈。
一、AES加密
关于AES的资料网上很多,个人觉得《加密与解密(第三版)》很不错,这本书中P155开始讲AES 下载地址: http://download.youkuaiyun.com/detail/qiwenmingshiwo/8755683
这个过程中我们使用 bcprov 这个jar包,官网: http://www.bouncycastle.org/
1. 我们秘钥的定义:
1234567891011121314publicfinalstaticCipherParameterskeyParams1=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.加密方法
二、AES解密
12345678910111213141516/***AES加密*@paramdata数据*@return*@throwsInvalidCipherTextException*/publicstaticbyte[]encrypt(byte[]data)throwsInvalidCipherTextException{BufferedBlockCiphercipher=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;}
三、Gizp压缩和解压缩
12345678910111213141516/***AES解密*@paramdata数据*@return*@throwsInvalidCipherTextException*/publicstaticbyte[]decrypt(byte[]data)throwsInvalidCipherTextException{BufferedBlockCiphercipher=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;}
这一个部分网上有很多,比如下面这个大神的。Java压缩技术(四) GZIP——Java原生实现
1. 压缩
- /**
- *数据压缩
- *
- *@paramis
- *@paramos
- *@throwsException
- */
- publicstaticvoidcompress(InputStreamis,OutputStreamos)
- throwsException{
- GZIPOutputStreamgos=newGZIPOutputStream(os);
- intcount;
- bytedata[]=newbyte[BUFFER];
- while((count=is.read(data,0,BUFFER))!=-1){
- gos.write(data,0,count);
- }
- gos.finish();
- gos.flush();
- gos.close();
- }
2.解压缩
- /**
- *数据解压缩
- *
- *@paramis
- *@paramos
- *@throwsException
- */
- publicstaticvoiddecompress(InputStreamis,OutputStreamos)
- throwsException{
- GZIPInputStreamgis=newGZIPInputStream(is);
- intcount;
- bytedata[]=newbyte[BUFFER];
- while((count=gis.read(data,0,BUFFER))!=-1){
- os.write(data,0,count);
- }
- gis.close();
- }
四、简单示例
我们创建一个java程序模拟后台,创建一个android程序当做客户端。
1.后台(java控制台程序模拟)主程序部分
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071/***@authorxiaoming*@time2015年5月30日下午5:01:01*@说明AesDemo*/publicclassAesDemo{publicstaticvoidmain(String[]args){test();}publicstaticvoidtest(){ServerSocketss=null;Sockets=null;DataInputStreamdis=null;DataOutputStreamdos=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(InvalidCipherTextExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}catch(Exceptione){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(IOExceptione){e.printStackTrace();}}}}
上面读取数据时候使用的:byte[]recData=(newTcpUtil()).readData(dis);进行了封装。TcpUtil类如下:
2.android端
12345678910111213141516171819202122232425262728293031323334353637/***@authorqiwenming*@time2015年5月30日下午4:16:45*@说明Tcp请求的工具类简单的实现一哈*/publicclassTcpUtil{/***读取数据*@throwsIOException*/publicstaticbyte[]readData(DataInputStreamdis)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;}}
我们主要请求一个数据使一哈。
Activiy中的主要代码:
上面用到的获取响应数据的方法:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647/***测试一哈*@paramv*/publicvoidtoTest(Viewv){StringresMsg="写代码真累";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(InvalidCipherTextExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}catch(Exceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}};}.start();}catch(InvalidCipherTextExceptione){e.printStackTrace();}catch(Exceptione){e.printStackTrace();}}
byte[]respData=newTcpUtil().requstData(compress);我进行了封装,如下:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687/***@authorqiwenming*@time2015年5月30日下午4:16:45*@说明Tcp请求的工具类简单的实现一哈*/publicclassTcpUtil{privateOutputStreamoutputStream;privateInputStreaminputStream;privateSocketsocket;/***请求数据*@return*/publicbyte[]requstData(byte[]data)throwsException{try{if(socket==null){socket=newSocket("192.168.1.106",10000);}outputStream=socket.getOutputStream();DataOutputStreamdos=newDataOutputStream(outputStream);dos.writeInt(data.length);dos.write(data);//把数据的长度写过去dos.flush();socket.shutdownOutput();//数据发完byte[]recData=responseData();returnrecData;}finally{// disconnect();}}/***响应的数据*@throwsIOException*/publicbyte[]responseData()throwsIOException{inputStream=socket.getInputStream();DataInputStreamdis=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;}/***关闭资源*@throwsIOException*/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了。
本文介绍了一种通过TCP进行数据传输时采用AES加密确保数据安全,并结合GZIP压缩减少数据量的方法。包括AES加密解密、GZIP压缩解压的具体实现,以及Java端与Android端的交互示例。
1402

被折叠的 条评论
为什么被折叠?



