RSA算法Java的简单实现

来源:互联网 发布:apache tomcat7.0安装 编辑:程序博客网 时间:2024/05/14 03:18

RSA简介

RSA算法据说是目前地球上最重要的加密算法。维基百科是这么介绍的:“对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA算法愈可靠。假如有人找到一种快速因数分解的算法,那么RSA的可靠性就会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的RSA密钥才可能被暴力破解。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要密钥长度足够长,用RSA加密的信息实际上是不能被解破的。”

  看上去很神奇是吧,其实在学习网络安全和密码学这门课的时候,都接触过。毕业近一年了,数论方面的知识忘的差不多了。如果大家对RSA算法原理很感兴趣,推荐下面这两篇文章:

http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html

http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html

本文描述下,我自己实现的一个简单的RSA算法。


RSA密钥生成和加密解密过程

   



RSA的具体实现

RSA具体实现的难点在于质数的生成。好在Java提供了一个强大的工具类BigInteger。具体的实现如下

(不过百行):

public class RSA {private BigInteger p = null;private BigInteger q = null;private BigInteger n = null;private BigInteger totient = null;private BigInteger e = null;private BigInteger d = null;public RSA(BigInteger p, BigInteger q) {this.p = p;this.q = q;n = p.multiply(q); // n = p * q;//totient =(p-1)*(q-1)即 (n)totient = (p.subtract(BigInteger.valueOf(1)).multiply((q.subtract(BigInteger.valueOf(1)))));
                e = getE();//选择公钥BigInteger y = egcd(totient, e)[1];                d = y.mod(totient); //产生私钥}public BigInteger getE() {// 这里以totient/4为种子,选取一个素数作为公钥return totient.divide(BigInteger.valueOf(4)).nextProbablePrime();}        // 扩展的Euclid算法,目的:算出e-1 mod npublic static BigInteger[] egcd(BigInteger d1, BigInteger d2) {BigInteger[] ret = new BigInteger[3];BigInteger u = BigInteger.valueOf(1), u1 = BigInteger.valueOf(0);BigInteger v = BigInteger.valueOf(0), v1 = BigInteger.valueOf(1);if (d2.compareTo(d1) > 0) {BigInteger tem = d1;d1 = d2;d2 = tem;}while (d2.compareTo(BigInteger.valueOf(0)) != 0) {BigInteger tq = d1.divide(d2); // tq = d1 / d2BigInteger tu = u;u = u1;u1 = tu.subtract(tq.multiply(u1)); // u1 =tu - tq * u1BigInteger tv = v;v = v1;v1 = tv.subtract(tq.multiply(v1)); // v1 = tv - tq * v1BigInteger td1 = d1;d1 = d2;d2 = td1.subtract(tq.multiply(d2)); // d2 = td1 - tq * d2ret[0] = u;ret[1] = v;ret[2] = d1;}return ret;}        // 加密public BigInteger encode(BigInteger d) {return d.modPow(this.e, this.n);}        // 解密public BigInteger decode(BigInteger c) {return c.modPow(this.d, this.n);}}

RSA的缺点

RSA算法使用乘方运算,明文以分组为单位进行加密,每个分组的二进制值均小于n也就是说分组的大

小必须小于等于log2(n)+1位。如果明文分组大于此长度,则需要进一步细分,或者借助另外一种对

称的加密算法来进行加密。此外,RSA加密解密效率不高,特别是密钥长度很长的时候,不适合对大

量信息进行加密。所以一般RSA会和其他对称的加密算法配合使用。

下面是我本科毕设中设计的一个简单的加密方案,以及前几天根据这个方案写的一个demo。


假设客户端要向服务发送数据,首先客户端需要通过用户名和密码生成自己的RSA密钥(用于解密的私

钥cPR),然后通过一个随机数生成这次数据传输的DES密钥deskey_c,除此之外我们还知道服务端的

RSA公钥sPU(服务端的RSA密钥是固定的)。有了这次数据传输的密钥信息之后,客户端就可以将数

据M1通过DES算法用deskey_c加密得到密文C1,然后将客户端生成的DES密钥deskey_c通过RSA算法

用服务端的公钥sPU加密得到加密后的DES密钥c_deskey_c。最后将加密后的信息(密文C1和加密后的

DES密钥c_deskey_c)通过http协议发送到服务端。服务端接收后,先通过自己的私钥sPR将DES密钥

解密出来,得到之前客户端生成的deskey_c,然后通过DES算法用deskey_c解密C1,得到原来的数据

M1。至此,客户端加密服务端解密的过程结束。在加密解密过程中,DES密钥为50位10进制数,RSA

算法中的p和q的范围是0到150位十进制整数。而当服务端向客户端发送数据的时候,同样需要生成密钥

信息。首先服务端通过客户端的用户名和密码得到客户端的RSA公钥cPU,然后通过一个随机数得到这

次数据传输的DES密钥deskey_s,然后通过DES算法用deskey_s将数据M2加密为密文C2,然后通过

RSA算法用客户端的公钥cPU将deskey_s加密为c_deskey_s。最后服务端将密文C2和加密后的DES

密钥c_deskey_s发送给客户端。客户端接收后,先通过RSA算法用自己的私钥cPR解密c_deskey_s,

得到原来服务端生成的DES密钥deskey_s,然后通过DES算法用该密钥解密出原来的数据M2。这样

就完成了服务端加密,客户端解密的过程。


Demo:



附上工程源码(最近加班紧,代码写的不是很好-_-||):

http://download.csdn.net/detail/he_qiao_2010/8548675


0 0
原创粉丝点击