在Android和Windows之间进行RSA加密通讯的方法和注意事项

来源:互联网 发布:js获取select选中事件 编辑:程序博客网 时间:2024/05/18 02:24

文章的内容来源于手头的一个项目。需求是在android手机(做客户端)和Windows(做服务器)之间进行低负载的加密通讯。

开发语言:客户端和服务器都用Java


加密方法选择的是RSA。说几句题外话。从道理上讲,RSA并不适合于数据加密,特别是数据量大的时候,因为比较慢,普通的使用方法是数据用对称加密,然后用RSA加密对称加密中使用的密钥,再分别交换。这样,用对称加密解决了速度的问题(对称加密和非对称加密,一般认为速度能差1000倍),用RSA解决了强度问题(到目前未为止,普遍认为1024位的RSA是安全的)。

手头这个项目因为通讯量很小,最长的不超过200字节,因此用RSA是比较合适的,而且,实际上个人认为秒级的延迟对于GUI用户而言还是可以忍受的。因此,在项目中采用了如下的方案:

1、生成RSA密钥对,公钥发给客户端使用,私钥由服务器使用;

2、客户端用公钥加密所有发出的数据,也用公钥解密所有收到的数据;

3、服务器用私钥加密所有发出的数据,也用私钥解密所有收到的数据;

其实很简单是吧。


遇到的问题是:服务器无法解密客户端发送的加密数据,客户端可以解密服务器发送的加密数据,但被填充过(解密出来的明文比原始明文长一截)。通过研究网上的帖子,终于找到管事儿的。http://my.oschina.net/cwalet/blog/35867

原来是windows上的java虚拟机和android上的java虚拟机对于RSA的实现不同,确切的说,是缺省算法不同造成的。处理步骤如下:

1、下一个jar包。http://www.bouncycastle.org/download/bcprov-jdk15on-148.jar

2、在Eclipse中将其引入构建路径;

3、修改jre下lib/security目录下的java.security文件,加入下面一行

security.provider.??=org.bouncycastle.jce.provider.BouncyCastleProvider

记得其中的问号用一个数字代替。根据java.security文件的内容可以确定这个数字。个人猜测,文件是按key-value方式组织的,所以不按顺序编号可能不行,但我懒得试验了。

这部分内容现在还存在一个疑点:在开发机上,像本节说的就可以了。但在生产环境中还必须再做一步:将bcprov-jdk15on-148.jar拷贝到jre\lib\ext目录下,不知道为什么。否则,会出现RSA失败,其实就是没找到算法。有关内容参考 http://blog.csdn.net/sx1116/article/details/5823677 写的很清楚。

4、修改服务器的源码(运行在windows上的),比如原来是

Cipher cipher=Cipher.getInstance("RSA");

则修改成

Cipher cipher=Cipher.getInstance("RSA",“BC”);

修改好在编译一次就行了,没有其它步骤。


相关的内容可以参考:

http://my.oschina.net/cwalet/blog/35867 作者 cwalet

http://www.gleisarbeiter.de/category/java/ 作者 未具名的老外

http://blog.csdn.net/sx1116/article/details/5823677 作者 sx1116

感谢他们,没有他们的文章,这问题也解决不了。也希望我这几行字对遇到同样问题的人有帮助。