(1) 算法原理
加密过程:
第一步,用户首先输入两个素数p=3和q=11,并求出n = p*q,然后再求出n的欧拉函数值phi=(p-1)*(q-1)。
第二步,在[e,phi]中选出一个与phi互素的整数e。
第三步,根据e*d mod phi=1求出e的乘法逆元d。至此我们已经得到了公开密钥kp={e,n}和秘密密钥ks={d,p,q}。
第四步,让用户输入要进行加密的小于n一组正整数(个数不超过MAXLENGTH=500),输入以-1为结束标志,实际个数存入size中,正整数以clear[MAXLENGTH]保存。
第五步,对第四步所输入的明文clear[MAXLENGTH]通过公钥进行加密。遍历clear[size],对每一个整数用以下算法进行加密,并将加密后的密文保存在cipherText[MAXLENGTH]中,加密公式C = Me mod n。
第六步,对第四步所得的密文cipherText[MAXLENGTH]使用私钥进行解密得到明文,解密公式M = Cd mod n。
(2) 算法参数
RSA密码算法主要有p、q、size、clear[MAXLENGTH]、cipherText[MAXLENGTH]五个参数。p、q为大素数,size是输入明文字符个数、clear[MAXLENGTH]是明文数组、cipherText[MAXLENGTH]是得到的密文。
实现代码:
package com.company;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class Test9 {
public static void main(String[] args) {
//第一步,用户首先输入两个素数p=3和q=11,并求出n = p*q,
// 然后再求出n的欧拉函数值phi=(p-1)*(q-1)。
Scanner sc=new Scanner(System.in);
System.out.print("请输入两个大素数:");
int p=sc.nextInt();
int q=sc.nextInt();
int n=p*q;
int phi=(p-1)*(q-1);
//第二步,在[e,phi]中选出一个与phi互素的整数e。
ArrayList arrayList = new ArrayList<Integer>();
for (int i=3;i<phi;i++){
if (gcd(i,phi)==1){
arrayList.add(i);
}
}
int e= (int) arrayList.get(0);
System.out.println("e的值为"+e);
//根据e*d mod phi=1求出e的乘法逆元d。至此我们已经得到了
// 公开密钥kp={e,n}和秘密密钥ks={d,p,q}
int d=(phi+1)/e;
System.out.println("d的值为:"+d);
System.out.println("输出公钥:"+"{"+e+","+n+"}");
System.out.println("输出私钥:"+"{"+d+","+p+","+q+"}");
//第四步,让用户输入要进行加密的小于n一组正整数(个数不超过MAXLENGTH=500),
// 输入以-1为结束标志,实际个数存入size中,正整数以clear[MAXLENGTH]保存。
int MAXLENGTH=500;
System.out.print("请输入明文长度:");
int size=sc.nextInt();
if (size>MAXLENGTH){
return;
}
System.out.print("请输入明文数组,输入-1时结束:");
int[] clear=new int[size];
for (int i=0;i<size+1;i++){
int temp=sc.nextInt();
if (temp==-1){
break;
}else
{
clear[i]=temp;
}
}
//第五步,对第四步所输入的明文clear[MAXLENGTH]通过公钥进行加密。
// 遍历clear[size],对每一个整数用以下算法进行加密,并将加密后的密
// 文保存在cipherText[MAXLENGTH]中,加密公式C = Me mod n。
int [] cipherText=new int[size];
for (int i=0;i<size;i++){
cipherText[i]=jiami(e,n,clear[i]);
}
System.out.println("输出密文数组:"+Arrays.toString(cipherText));
for (int i=0;i<size;i++){
clear[i]=jiemi(cipherText[i],d,n);
}
System.out.println("输出明文数组:"+Arrays.toString(clear));
}
public static int gcd(int a, int b) {
int min = a < b ? a : b;//判断并取出两个数中小的数
for (int i = min; i >= 1; i--) { //循环,从最小值开始,依次递减,直到i=1
if (a%i==0&&b%i==0){ //当i能同时被A和B余尽时,返回i
return i;
}
}
return 0;
}
public static int jiami(int e,int n,int m){
int c=(int)Math.pow(m,e)%n;
return c;
}
public static int jiemi(int c,int d,int n){
long m=(long)Math.pow(c,d)%n;//数据类型应为long,否则会因为数据过大解密出错
int z=(int)m;
return z;
}
}
运行结果: