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

一、AES加密

关于AES的资料网上很多,个人觉得《加密与解密(第三版)》很不错,这本书中P155开始讲AES 下载地址:
这个过程中我们使用 bcprov 这个jar包,官网: http://www.bouncycastle.org/
1. 我们秘钥的定义:

publicfinalstaticCipherParameterskeyParams1=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加密
 
       
*@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;
 
       
}



二、AES解密

/**
 
       
*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;
 
       
}



三、Gizp压缩和解压缩

这一个部分网上有很多,比如下面这个大神的。

Java压缩技术(四) GZIP——Java原生实现

1. 压缩


1. /**
2. *数据压缩
3. *
4. *@paramis
5. *@paramos
6. *@throwsException
7. */
8. publicstaticvoidcompress(InputStreamis,OutputStreamos) 
9.  throwsException{ 
10. 
11.  GZIPOutputStreamgos=newGZIPOutputStream(os); 
12. 
13.  intcount; 
14.  bytedata[]=newbyte[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. *@paramis
5. *@paramos
6. *@throwsException
7. */
8. publicstaticvoiddecompress(InputStreamis,OutputStreamos) 
9.  throwsException{ 
10. 
11.  GZIPInputStreamgis=newGZIPInputStream(is); 
12. 
13.  intcount; 
14.  bytedata[]=newbyte[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控制台程序模拟)

主程序部分

/**
 
        
*@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=(new TcpUtil()).readData(dis);进行了封装。TcpUtil类如下:

/**
 
        
*@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;
 
        
}
 
        

 
        
}

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


/**



*测试一哈



*@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-generatedcatchblock



e.printStackTrace();



}catch(Exceptione){



//TODOAuto-generatedcatchblock



e.printStackTrace();



}



};



}.start();









}catch(InvalidCipherTextExceptione){



e.printStackTrace();



}catch(Exceptione){



e.printStackTrace();



}



}


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

/**
 
        
*@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了。


在线AES工具 aes下载_java

在线AES工具 aes下载_ci_02


在线AES工具 aes下载_网络_03