武汉大学应用密码学RSA加密解密大作业
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1 对RSA算法的理解
RSA加密算法是一种非对称加密算法,它基于一个非常简单的数论思想:“将两个素数乘起来是很容易的,但是分解该乘积是非常困难的”。
1.1加解密步骤
(1)生成公钥和私钥
a)随机生成两个不相等的大素数p和q,计算N=p*q;
b)根据欧拉函数,求出φ=(p-1)*(q-1);
c)选择一个小于r的整数e,求e关于r的模反元素d使得e*d mod φ
=1
得到公钥
(2)加密
给定明文m,公钥
(3)解密
给定密文c,私钥
1.2素性检验
RSA算法的实现难点之一是生成大素数,这就需要生成一个大数并对其进行素性检验。素性检验有很多种方法。其中包括确定性方法和随机方法。确定性方法有试除法(埃拉托斯特尼筛法),卢卡斯-莱默检验法和AKS素数测试。常见的随机方法有费马素性检验,米勒-拉宾检验和欧拉-雅科比测试。本次作业采用就是米勒-拉宾检验方法。
米勒-拉宾(Miller Rabin) 算法原理:
要测试N 是否为素数,首先将N-1 分解为2s d。在每次测试开始时,先随机选一个介于[1, N-1]的整数a,之后如果对所有的r∈[0, s-1],若a d mod N ≠ 1 且a2^rd mod N ≠1,则N 是合数。否则,N 有3/4 的概率为素数。
1.3安全问题
(1)公共模数攻击。每个人具有相同的r,但有不同的指数e和d,这是不安全的。
(2)低加密指数攻击。如果选择了较低的e值,虽然可以加快计算速度,但存在不安全性。
(3)低解密指数攻击。如果选择了较低的d值,也是不安全的。
(4)选择密文攻击。如A想让T对一个T不愿意签名的消息m’签名,A首先选择一个任意值x,计算y=x e(mod r),然后要求T对m=ym’签名,A最后计算(m d mod r)x-1 mod r =( ym’) d x-1mod r= m’d mod r。
还有一些不是直接对RSA的算法本身进行的攻击,如中间人攻击、时间攻击、边信道攻击等。
2.具体实现
2.1函数说明
void ProducePrime(JTextField prime):使用JA V A的Biginteger生成512位的
大数,再用Miller Robin算法检验是否是素数。参数prime即为生成的大素数。
boolean MillerRobin(BigInteger n):用Miller Robin检验判断大数n是否是素数。
BigInteger modex(BigInteger a, BigInteger b, BigInteger n):模幂运算,计算a b mod n
BigInteger inverse(BigInteger a, BigInteger b):求逆运算,计算a-1 ( b )
String Encode(String Plaintext, BigInteger n, int nLen, int m, JTextField e):加密,用公钥(n,e)对明文Plaintext加密。
String Decode(String Ciphertext, BigInteger n, int m, JTextField d):解密,用私钥d对密文Ciphertext解密。
2.2JA V A代码
import java.math.BigInteger;
import java.util.Random;
import java.util.Scanner;
import javax.swing.JTextField;
public class RSA {
public static void main(String[] args) {
String s;
JTextField p = new JTextField(35);
JTextField q = new JTextField(35);
JTextField e = new JTextField(35);
JTextField d = new JTextField(35);
ProducePrime(p);
ProducePrime(q);
BigInteger pp = new BigInteger(p.getText());
BigInteger qq = new BigInteger(q.getText());
BigInteger oo = (pp.subtract(new BigInteger("1"))).multiply(qq
.subtract(new BigInteger("1")));
BigInteger ee;
do {
ee = new BigInteger(100, new Random()).mod(oo);
} while (MillerRobin(ee) == false);
e.setText(ee.toString());
d.setText(inverse(ee, oo).toString());
BigInteger n = pp.multiply(qq);
int nLen = n.bitLength();
int m = (int) (Math.ceil((double) (nLen) / 16.0));
nLen = (nLen - 1) / 16;
String Ciphertext = new String();