在TCP加密通讯的过程,实践中发现,比之前想的要麻烦一点,那几个加密类也不是很好用,老是出一些莫名其妙的问题,比如说3des,就老是出莫名其妙的问题,表现在加密二进制字节数组,加密的时候说“数据无效”“无效的填充且无法被移除”之类的,结果换了个aes,据说aes是新一代对称加密算法,加密强度比3des高,速度快之类的,在.net4下直接有个aes,但是.net4刚出几天,连win7都不带,安装率太低了,大部分都是2.0,但是2.0里没有aes,后来发现在.net2里aes叫Rijndael,用了一下,加密刚才3des出错的那个字节数组就没问题了。
另外一个问题就是,加密的时候,凡是
CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(bt, 0, count);
之后
必须要加个cs.FlushFinalBlock();
否则因为可能字节不够长度而没有加密,返回0字节的数组。
还有本来想的挺美好的一个事情就是CryptoStream cs = new CryptoStream(流, aes.CreateEncryptor(), CryptoStreamMode.Write);
CryptoStream构造函数第一个参数是流,本以为像
networkstream ns=tcpclient.getstream();
这个ns,可以
CryptoStream csxie = new CryptoStream(ns, aes.CreateEncryptor(), CryptoStreamMode.Write);
CryptoStream csdu = new CryptoStream(ns, aes.CreateDecryptor(), CryptoStreamMode.Read);
加这一句就什么都不用管了,直接就是加密通讯了
结果发现不行如果客户这边用csxie.Write(bt,0,count);csxie.FlushFinalBlock();看似是写出去了,其实sniffer也能看到是写出去了,但是服务器那边如果用csdu.Read(bt,0,bt.Length);读,就一直卡在这一句,所以就不能实时的加密和解密,如果客户那边加一句csxie.clear();服务器那边就能读了,但是这句clear却把整个tcpclient给关闭了,那就没意义了,所以就比较麻烦了,所以就只能还是用networkstream来读写,然后把读出的数据用CryptoStream来加解密。
这样又引申出了一个新麻烦,这就要给每个加密的数组标明一个长度
这么说吧,比如用Rijndael加密“你”字,会得到16个字节,加密“好”字会得到16个字节,分别用Rijndael解密这2个字节数组没问题,但是你如果把这2个16字节给合成1个32字节的数组用Rijndael解密,就会告诉你“输入无效”之类的错误提示,麻烦就在这里,比如你加密了一段数据得到了8192个字节,传出去,那边正好收到了8192字节,直接解密就不用管了,但是数据是通过网络传输的,你这边发送8192那边不一定就一定能一次收到8192个字节的完整数组,如果没有加密解密比如直接转发或者写文件,那收到count个就转发或写count个就行了,但是由于要解密就不行了,加密了8192,就一定得解密这8192,多一个少一个都不行,所以每次发送加密数据的时候就得标明这一次加密的数组有多少个字节,如果一次收不全就再收等收全了再解密,如果一次收到了好几个整段的数组,就得分别解密然后合起来,余下的不够整段的要下次接受放在头里,这样一来把完整的网络通讯过程加解密要比直接传输多了大量的计算,而且每次一加解密都要new新的CryptoStream然后关闭。
但是好在cpu比我想象的要快的多的多,并没有出现想象中的“这样还能跑的动吗”的疑问,观察了一下,经过加密后传输和没有经过加密传输无论是服务端还是客户端的cpu占用率和内存占用率基本没有区别。但是网络体验就感觉到了一点延迟,但是问题不大。
谁有好办法望不吝赐教