RSA加密算法(思路):
1:选择两个大素数p, q(p,q需严格保密,一般在100位以上)
实例:设p = 47, q = 71(计算方便所以举简单数字的例子)
2:计算n = p * q, r = (p - 1)(q - 1)
实例:n = 47 * 71 = 3337 r = 46 * 70 = 3220
3:选择一个公钥e,要求e < r且 e不是r的因子
实例:e = 79
4:选择私钥d,满足 (d * e) mod r = 1
实例:代入:d * 79 mod 3220 = 1 得到 d = 1019
5:销毁p,q 的记录
6:加密过程:明文pt,加密私钥e,密文ct
计算公式:ct =
p
t
e
pt^e
pte mod n
实例:明文2021,加密后ct = 2538
7:解密过程:
计算公式:pt =
c
t
d
ct^d
ctd mod n
代码实现:
//RSA算法(java实现)
import java.io.*;
public class RSA {
private int p = 0, q = 0;
private long n = 0, r = 0, e = 0, d = 0;
private long pt = 0;//明文
private long ct = 0;//密文
private long word = 0;//解密后明文
//判断是否为素数(试除法)
public boolean isPrime(long t) {
if (t == 1) return false;
for (int i = 2; i <= t / i; i++)
if (t % i == 0)
return false;
return true;
}
//求最大公因数(欧几里得算法)
public long gcd(long a, long b) {
return b == 0 ? a : gcd(b, a % b);
}
//p, q, n, r, e, d
public void start() throws Exception {
//输入素数p
System.out.println("请输入素数p: ");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
this.p = Integer.parseInt(bufferedReader.readLine());
if (isPrime(this.p)) break;
else System.out.println("您输入的不是素数,请重新输入p");
}
//输入素数q
System.out.println("请输入素数q: ");
while (true) {
this.q = Integer.parseInt(bufferedReader.readLine());
if (isPrime(this.q)) break;
else System.out.println("您输入的不是素数,请重新输入q");
}
this.n = this.p * this.q;
this.r = (p - 1) * (q - 1);
System.out.println("这两个素数的乘积n为:" + this.n);
System.out.println("n的欧拉数=(p-1)(q-1):" + this.r);
getE();
getD();
}
//提供一个公钥e,这个值要求小于r并且不是r的因子
public void getE() throws Exception {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入公钥: ");
while (true) {
this.e = Long.parseLong(bufferedReader.readLine());
if (this.e < this.r && r % this.e != 0)
break;
}
System.out.println("公钥为:" + this.e);
}
//计算密钥(欧几里得扩展法)
public void getD() {
long value = 1;
for (long i = 1; ; i++) {
value = i * this.r + 1;
//System.out.println("value: " + value);
if ((value % this.e == 0) && (value / this.e < this.r)) {
this.d = value / this.e;
break;
}
}
System.out.println("生成的私钥为:" + this.d);
}
//输入需要加密的明文
public void getPt() throws Exception {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入明文:");
this.pt = Long.parseLong(bufferedReader.readLine());
}
//(快速幂)
public long qmi(long a, long b, long p) {
long res = 1;
while (b > 0) {
if ((b & 1) != 0) res = res * a % p;
b = b >> 1;
a = a * a % p;
}
return res;
}
//加密后解密
public void RSAMain() throws Exception {
this.getPt();
System.out.println("输入的明文为: " + this.pt);
//加密
this.ct = this.qmi(this.pt, this.e, this.n);
System.out.println("算出的密文为:" + this.ct);
//解密
this.word = this.qmi(this.ct, this.d, this.n);
System.out.println("解密后所得的明文为:" + this.word);
}
//入口
public static void main(String[] args) throws Exception {
RSA t = new RSA();
t.start();
t.RSAMain();
}
}
效果展示:
代码很多地方还需要完善,比如大素数