RSA加密算法操作的java演示

背景

在读wiki中的RSA加密算法 的原理的时候,其中的n,e,d,m过于抽象,没有具体的数据,让人不好理解。
我就参照上wiki上说明的操作,用代码实现具体的操作。可能会更加具体而更容易理解。

操作

公钥与私钥的产生

假设Alice想要通过一个不可靠的媒体接收Bob的一条私人消息。她可以用以下的方式来产生一个公钥和一个私钥:

  1. 随意选择两个大的质数p和q,p不等于q,计算N=pq。
  2. 根据欧拉函数,求得 r=φ(N)=φ(p)φ(q)=(p1)(q1)
  3. 选择一个小于r的整数e,使e与r互质。并求得e关于r的模反元素,命名为d(求d令 ab1(modn) )。(模反元素存在,当且仅当er互质)
  4. 将p和q的记录销毁。

(N,e)是公钥,(N,d)是私钥。Alice将她的公钥(N,e)传给Bob,而将她的私钥(N,d)藏起来。

下面的java代码片段就是jdk实现的生成公钥和私钥的方法。可以把e,n,d打印出来。验证下是不是符合上面的说明。试过,e总为65537。

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);
KeyPair keypair = kpg.genKeyPair();
RSAPrivateKey privatekey= (RSAPrivateKey)keypair.getPrivate();
RSAPublicKey publickey= (RSAPublicKey)keypair.getPublic();

BigInteger e = publickey.getPublicExponent();
BigInteger N = publickey.getModulus();

BigInteger d = privatekey.getPrivateExponent();
BigInteger N = privatekey.getModulus();

加密消息

假设Bob想给Alice送一个消息m,他知道Alice产生的N和e。他使用起先与Alice约好的格式将m转换为一个小于N的整数n,比如他可以将每一个字转换为这个字的Unicode码,然后将这些数字连在一起组成一个数字。假如他的信息非常长的话,他可以将这个信息分为几段,然后将每一段转换为n。用下面这个公式他可以将n加密为c:

nec (mod N)

计算c并不复杂。Bob算出c后就可以将它传递给Alice。

下面代码片段中的m,N,e,c与上面说明一致。m怎么到n就是分段与编码的问题,这里只是简单的用utf8编码(真实中不会这样编码,数据长了之后可能m会大于N)。因为汉字的utf8转出来,n为是一个负数,所以在前面加了>来保证它为正。

    String m = ">下午5点见";
    byte[] bys = m.getBytes("UTF8");
    BigInteger n =new BigInteger(bys);
    BigInteger e = publickey.getPublicExponent();
    BigInteger N = publickey.getModulus();
    BigInteger c = n.modPow(e,N);

解密消息

Alice得到Bob的消息c后就可以利用她的密钥d来解码。她可以用以下这个公式来将c转换为n:

cdn (mod N)

得到n后,她可以将原来的信息m重新复原。

解码的原理是

cdned (mod N)

以及 ed=1(modp1)ed=1(modq1) 。由欧拉定理可证明(因为p和q是质数)

nedn (mod p)nedn (mod q)

这说明(因为p和q是不同的质数,所以p和q互质)

nedn (mod pq)

下面代码片段中的c,d,n,N与上面解释的一致。

BigInteger d = privatekey.getPrivateExponent();
BigInteger N = privatekey.getModulus();
BigInteger n=c.modPow(d,N);
String m =new String(n.toByteArray(),"UTF8"); 
System.out.println(m);

代码片段地址

你可能感兴趣的:(java,rsa)