RSA算法

下面计划:1,RSA-OAEP 2,Rabin算法 3,详解中国剩余定理

********************************

鉴于在博客中写公式略显难看,有碍观瞻,博客中的内容我都事先用latex写了一个pdf的文档,可以在下链接下载 

http://download.csdn.net/detail/xue_haiyang/7637701

********************************

*******************************\\

由于我对RSA算法比较熟悉,所以决定从RSA下手。由于我的水平有限,下面所写的难免有各种错误,还请留言批评指正(欢迎任意的批评交流)。


*******************************\\


随着对算法的了解,我计划分成三个大部分学习这个部分。第一大部分关于RSA基本加密的分析和实现;第二大部分Rabin函数的实现以及Rabin-OAEP的实现;
第三部分 依葫芦画瓢,写个JAVA下自己的大数包。(发现JAVA大数包结构清晰,所以希望自己能通过画瓢更加熟悉JAVA语言)




下面我就第一部分从分成几个章节写。

  1. RSA加密算法基础
  2.  基本RSA实现
  3. 根据中国剩余定理改进



第一部分 RSA加密算法基础
19世纪70年代,现实中,密钥分发是一个很急迫需要。私钥加密方案解决不了这个问题。Diffie 和Hellman就提出了
公钥加密方案的概念。每个人i公开一个公钥 , 同时自己保存一个私钥 . 任何一个希望给i发送信息的人
就使用   加密消息m 得到c,并发送给i . i 拿到c,可以使用 解密出消息m. 下面图示公钥加密方案的模型。


之后RSA三个人就给出了公钥加密方案的实例--RSA加密方案。我首先描述一下方案,然后在分析下方案的正确性。
  1. 密钥生成 首先生成长度为 的两个大素数P, Q, 令N=PQ,. 选取较小的整数e 满足e 和 是互素的。也就是。                  计算.                   
  2.  加密 对于明文, 计算密文                
  3.  解密 对于密文c, 计算               


下面分析下方案的正确性。对于任意明文空间的$m$,有




我们就有 , 然后就有





  1. 实际上中的元素的阶是整除的。
  2. 为了加快加密的速度一般上选择这个素数。下面我会详细说说为什么要选择这样的$e$.


第二部分: 基本RSA实现
下面就看看怎样使用JAVA实现RSA加密算法。通过搜索发现在JAVA中封装好了一个BigInteger的类,至于该类的API见。




下面是对基本RSA的实现和例子。其中的PQ是使用的RSA公司分解挑战中的一个例子。


</pre><pre code_snippet_id="383363" snippet_file_name="blog_20140609_1_7560533" name="code" class="java">/**********
xuehaiyang@iie.ac.cn
***********/
import java.math.BigInteger;
public class RSATest {
<span style="white-space:pre">	</span>public static void main(String[] args)
<span style="white-space:pre">	</span>{<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>//Key generation
<span style="white-space:pre">	</span>// N is the RSA modulo. e is the public key and d is the private key.
BigInteger P = new
BigInteger("398075086424064937397125500550386491199064362342526708406385189575946388957261768583317");
BigInteger Q = new
BigInteger("472772146107435302536223071973048224632914695302097116459852171130520711256363590397527");
BigInteger P1 = new
BigInteger("398075086424064937397125500550386491199064362342526708406385189575946388957261768583316");
BigInteger Q1 = new
BigInteger("472772146107435302536223071973048224632914695302097116459852171130520711256363590397526");




BigInteger N = new BigInteger("33");
BigInteger PiN = new BigInteger("33");
N = P.multiply(Q);
PiN=P1.multiply(Q1);
BigInteger e = new BigInteger("65577");
BigInteger d = e.modInverse(PiN);
System.out.println("d is " + d);
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>
//encryption; m is the plaintext and c is the ciphertext
BigInteger m = new BigInteger("123456789");
BigInteger c= m.modPow(e, N);
System.out.println("Ciphertext is " + c);
<span style="white-space:pre">	</span>
<span style="white-space:pre">		</span>
//decryption; m1 is the plaintext and c is the ciphertext
BigInteger m1 =new BigInteger("987654321");
m1= c.modPow(d, N);
System.out.println("Plaintext is " + m1);
<span style="white-space:pre">		</span>
//Fast decryption with CRT; m2 is the plaintext and c is the ciphertext
BigInteger m2 =new BigInteger("987654321");
m2= ((c.modPow(d, P).multiply(Inv_P_ModQ).multiply(P))
    .add(c.modPow(d, Q).multiply(Inv_Q_ModP).multiply(Q))).mod(N);
System.out.println("Plaintext is " + m2);
}
}




RSA跟对称加密算法相比的缺点是效率比较低。这里边$e$选择 的原因是在兼顾安全的前提下增加加密的效率。如果我们记$e=(e_i)$ for $i=0, 1,... ,16$
这里要计算 . 2^{16}+1 只在第一位和最后一位是1,减少乘法的次数。




第三部分: 根据中国剩余定理改进
其实这里边RSA的效率还是比较低,一个好的解决方案是增加解密的速度。使用的方法是中国剩余定理.
解密方在生成私钥的时候,直接计算$P$ mod $Q$的逆和$Q$ mod $P$的逆。如下


/**********
xuehaiyang@iie.ac.cn
***********/


import java.math.BigInteger;
public class RSACRT{
<span style="white-space:pre">	</span>public static void main(String[] args)
<span style="white-space:pre">	</span>{<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>//Key generation
<span style="white-space:pre">	</span>// N is the RSA modulo. e is the public key and d,Inv_P_ModQ,Inv_Q_ModP is the private key.
BigInteger P = new
BigInteger("398075086424064937397125500550386491199064362342526708406385189575946388957261768583317");
BigInteger Q = new
BigInteger("472772146107435302536223071973048224632914695302097116459852171130520711256363590397527");
BigInteger Inv_P_ModQ = P.modInverse(Q);
BigInteger Inv_Q_ModP = Q.modInverse(P);
BigInteger P1 = new
BigInteger("398075086424064937397125500550386491199064362342526708406385189575946388957261768583316");
BigInteger Q1 = new
BigInteger("472772146107435302536223071973048224632914695302097116459852171130520711256363590397526");




BigInteger N = new BigInteger("33");
BigInteger PiN = new BigInteger("33");
N = P.multiply(Q);
PiN=P1.multiply(Q1);
BigInteger e = new BigInteger("65577");
BigInteger d = e.modInverse(PiN);
System.out.println("d is " + d);
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>
//encryption; m is the plaintext and c is the ciphertext
BigInteger m = new BigInteger("123456789");
BigInteger c= m.modPow(e, N);
System.out.println("Ciphertext is " + c);
<span style="white-space:pre">	</span>
<span style="white-space:pre">		</span>




<span style="white-space:pre">		</span>
//Fast decryption with CRT; m2 is the plaintext and c is the ciphertext
BigInteger m2 =new BigInteger("987654321");
m2= ((c.modPow(d, P).multiply(Inv_P_ModQ).multiply(P))
    .add(c.modPow(d, Q).multiply(Inv_Q_ModP).multiply(Q))).mod(N);
System.out.println("Plaintext is " + m2);
}




}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值