RSA
1. RSA加密算法
RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。例如:
(1)乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
(2)甲方获取乙方的公钥,然后用它对信息加密。
(3)乙方得到加密后的信息,用私钥解密
公钥加密的信息只有私钥解得开,那么只要私钥不泄漏,通信就是安全的。
2. RSA原理
RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。通常是先生成一对RSA 密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。
对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA算法愈可靠。假如有人找到一种快速因数分解的算法的话,那么用RSA加密的信息的可靠性就肯定会极度下降。但找到这样的算法的可能性是非常小的。
3. 算法
(1)选择两个不同的大素数p和q,pq越大越安全;
(2)计算乘积n=pq和计算 n 的欧拉函数Φ(n)=(p-1)(q-1);
(3)选择大于1小于Φ(n)的随机整数e,使得gcd(e,Φ(n))=1;注:gcd即最大公约数。(随机选择一个整数 e,条件是 1< e < Φ(n),且 e 与 Φ(n) 互质)
(4)计算d使得de=1mod Φ(n);注:即de mod Φ(n) =1。(计算e对于 Φ(n) 的模反元素d,可以使得 e*d 除以 Φ(n) 的余数为 1)
(5)对每一个密钥k=(n,p,q,d,e),定义加密变换为Ek(x)=xe mod n,解密变换为Dk(x)=yd mod n,这里x,y∈Zn;
(6)p,q销毁,以{e,n}为公开密钥,{d,n}为私有密钥。
RSA使用公共指数e和私有指数d。指数e是每个人都知道的公钥(e, n)的一部分。使用公钥e加密的消息只能使用私钥d解密
c:密文,m:明文
加密:c = m^e mod n
解密:m = c^d mod n
4. 实例
1、假设p = 3、q = 11(p,q都是素数即可。),则N = pq = 33;
r =Φ(n)= (p-1)(q-1) = (3-1)(11-1) = 20;
根据gcd(e,Φ(n))=1,即gcd(e,20)=1,令e=3,则,d = 7。(两个数交换一下也可以。)
到这里,公钥和密钥已经确定。公钥为(N, e) = (33, 3),密钥为(N, d) = (33, 7)。
2、例题:在RSA加密体制中, 已知素数 p = 7, q = 11, 公钥 e = 13, 试计算私钥 d 并给出对明文 m = 5 的加密,求其密文. 已知密文 c = 15, 求其明文
解:
n=pq=77
φ(n)=(p-1)(q-1)=60
ed≡1 mod φ(n)
即13d mod 60 = 1
解得:d = 37
公钥(n,e)=(77,13)
密文c = m^e mod n = 5^13 mod 77 = 26
私钥(n,d)=(77,37)
明文m = c^d mod n = 15^37 mod 77 = 71
5. RSA签名及其验证
A和B进行加密通信时,B首先要生成一对密钥。一个是公钥,给A,B自己持有私钥。A使用B的公钥加密要加密发送的内容,然后B在通过自己的私钥解密内容
假设A要想B发送消息,A会先计算出消息的消息摘要,然后使用自己的私钥加密这段摘要加密,最后将加密后的消息摘要和消息一起发送给B,被加密的消息摘要就是“签名”。
B收到消息后,也会使用和A相同的方法提取消息摘要,然后使用A的公钥解密A发送的来签名,并与自己计算出来的消息摘要进行比较。如果相同则说明消息是A发送给B的,同时,A也无法否认自己发送消息给B的事实。
其中,A用自己的私钥给消息摘要加密成为“签名”;B使用A的公钥解密签名文件的过程,就叫做“验签”。
6. 代码
package seventh;
import java.util.Scanner;
public class RSA {
public static void main(String[] args) {
int p = 1;
int q = 1;
int n ;
int o;//欧拉函数
int d;
int e;
int c;//密文
int m;//明文
System.out.println("请输入e:");
e = new Scanner(System.in).nextInt();
System.out.println("请输入n:");
n = new Scanner(System.in).nextInt();
System.out.println("公钥为(e,n):"+"("+e+","+n+")");
System.out.println("如果需要求明文m,请输入密文c:(没有请输入-1)");
c = new Scanner(System.in).nextInt();
for (; p <= n; p++) {
if (isPrime(p)){
if (n % p == 0){
if(isPrime(n/p)){
q = n/p;
break;
}
}
}
}
//System.out.println(q);
o = (q - 1) * (p - 1);
System.out.println("求得欧拉函数值为:"+o);
for (d = 1; d <= o; d++){
if ((d*e)%o == 1){
break;
}
}
System.out.println(d);
System.out.println("私钥为(d,n):"+"("+d+","+n+")");
if (c != -1){
m = (int)Math.pow(c,d) % n;
System.out.println("密文为:"+m);
}
}
//判断是否为质数
public static boolean isPrime(int p) {
//n<=3时,质数有2和3
if (p <= 3) {
return p > 1;
}
//当n>3时,质数无法被比它小的数整除
for (int i = 2; i < p; i++) {
if (p % i == 0) {
return false;
}
}
return true;
}
}
运行结果:
[外链图片转存中…(img-8jByc2kK-1666748298386)]
[外链图片转存中…(img-4yUVbSCJ-1666748298387)]
[外链图片转存中…(img-6QFxnYgX-1666748298388)]