TCP传输中使用AES加密和gizp压缩
最近项目需求需要用到TCP传输,为了保证安全传输使用AES,为了使传输过程中减数据量小,使用gzip压缩,特此分享一哈。
一、AES加密
关于AES的资料网上很多,个人觉得《加密与解密(第三版)》很不错,这本书中P155开始讲AES 下载地址:http://download.****.net/detail/qiwenmingshiwo/8755683
这个过程中我们使用 bcprov 这个jar包,官网:http://www.bouncycastle.org/
1. 我们秘钥的定义:
1234567891011121314public
final
static
CipherParameterskeyParams1=
new
ParametersWithIV(
new
KeyParameter(
new
byte
[]{(
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
}),
new
byte
[]{(
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
*/
public
static
byte
[]encrypt(
byte
[]data)
throws
InvalidCipherTextException
{
BufferedBlockCiphercipher=
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;
}
三、Gizp压缩和解压缩
12345678910111213141516/**
*AES解密
*@paramdata数据
*@return
*@throwsInvalidCipherTextException
*/
public
static
byte
[]decrypt(
byte
[]data)
throws
InvalidCipherTextException
{
BufferedBlockCiphercipher=
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;
}
这一个部分网上有很多,比如下面这个大神的。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
*/
public
class
AesDemo{
public
static
void
main(String[]args){
test();
}
public
static
void
test(){
ServerSocketss=
null
;
Sockets=
null
;
DataInputStreamdis=
null
;
DataOutputStreamdos=
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
(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类如下:
2.android端
12345678910111213141516171819202122232425262728293031323334353637/**
*@authorqiwenming
*@time2015年5月30日下午4:16:45
*@说明Tcp请求的工具类简单的实现一哈
*/
public
class
TcpUtil{
/**
*读取数据
*@throwsIOException
*/
public
static
byte
[]readData(DataInputStreamdis)
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;
}
}
我们主要请求一个数据使一哈。
Activiy中的主要代码:
上面用到的获取响应数据的方法:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647/**
*测试一哈
*@paramv
*/
public
void
toTest(Viewv){
StringresMsg=
"写代码真累"
;
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
(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);我进行了封装,如下:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687/**
*@authorqiwenming
*@time2015年5月30日下午4:16:45
*@说明Tcp请求的工具类简单的实现一哈
*/
public
class
TcpUtil{
private
OutputStreamoutputStream;
private
InputStreaminputStream;
private
Socketsocket;
/**
*请求数据
*@return
*/
public
byte
[]requstData(
byte
[]data)
throws
Exception{
try
{
if
(socket==
null
){
socket=
new
Socket(
"192.168.1.106"
,
10000
);
}
outputStream=socket.getOutputStream();
DataOutputStreamdos=
new
DataOutputStream(outputStream);
dos.writeInt(data.length);
dos.write(data);
//把数据的长度写过去
dos.flush();
socket.shutdownOutput();
//数据发完
byte
[]recData=responseData();
return
recData;
}
finally
{
// disconnect();
}
}
/**
*响应的数据
*@throwsIOException
*/
public
byte
[]responseData()
throws
IOException{
inputStream=socket.getInputStream();
DataInputStreamdis=
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;
}
/**
*关闭资源
*@throwsIOException
*/
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了。