RSA加解密算法的过程很简单,它是典型的公钥加密算法,算法简单明了是较典型对称加密算法DES而言!
RSA加解密算法过程大致如下:
首先:选择两个大素数(通常都在百位以上才能保证足够安全)P,Q;
接着:计算P*Q=N,(P-1)*(Q-1)=fn;
接着:随机选择一个数E(其实为了安全要保证它也足够大,但要小于fn),使其满足E和fn的最大公因子为1,就是满足它倆互质,这样的E就是可以充当公钥了;
接着:计算私钥,私钥D满足公式(E*D)%fn=1,满足该公式的D可以充当私钥;
最后:加密是,明文W,加密公式是求W的E次方和N的余数,解密公式是求前面加密得到的余数的D次方和N的余数!(为了保证正确性要使得W要小于N)
接下来就是我用java实现了一个极其简单的RSA算法:
makekey.java实现选择俩素数,确定公私钥
import java.util.Random;
public class makekey {
private static int P,Q,D,E,FN;
static Random rdom=new Random();
public static void twopnumcre(){
setp(cheackp());//设置素数p
setq(cheackp());//设置素数q
}
public static int cheackp(){//获得一个素数,本例中为了计算正确将两个大素数控制在13以内
int num=rdom.nextInt(13);
while(true){
boolean is=true;
for(int h=2;h<num;h++)
if(num%h==0)
{
is=false;
break;
}
if(num==1||num==0)
is=false;
if(is)
break;
num=rdom.nextInt(13);
}
return num;
}
public static void pubkeycre(int P,int Q){//得到公钥和私钥
int fN=(P-1)*(Q-1);
creE();
creD(fN,gete());
setfn();//设置N,N=p*q
System.out.println("OK!");///表明素数的选择以及公私钥的生成成功
}
public static boolean findgyz(int num,int fn){//判断num和fn的最大公因子是否为1,利用到了欧几里得算法判断一个随机生成的数是否可以为公钥
int a=0;
while(num>0){
a=num;
num=fn%num;
fn=a;
}
if(a==1)
return true;
return false;
}
public static void creE(){//生成公钥的逻辑
int num=rdom.nextInt(getFN());//限制公钥的范围在(p-1)*(q-1)以内,超出的话会出错
while(true){
if(findgyz(num,getFN())&&num!=1){
sete(num);
break;
}
num=rdom.nextInt(getFN());
}
}
public static void creD(int fn,int e){//公钥选好后计算得到私钥
int num=1;
while(true){
if((num*fn+1)%e==0)
{
setd((num*fn+1)/e);
break;
}
num++;
}
}
public static void setp(int p){
P=p;
}
public static void setq(int q){
Q=q;
}
public static void setd(int d){
D=d;
}
public static void sete(int e){
E=e;
}
public static int getp(){
return P;
}
public static int getq(){
return Q;
}
public static int getd(){
return D;
}
public static int gete(){
return E;
}
public static void setfn(){
FN=P*Q;
}
public static int getfn(){
return FN;
}
public static int getFN(){
return (P-1)*(Q-1);
}
}
jiajiesic.java是程序的入口:
import java.util.Scanner;
public class jiajiesic {
Scanner scan=new Scanner(System.in);
public jiajiesic(){
makekey.twopnumcre();//先得到两个素数
makekey.pubkeycre(makekey.getp(), makekey.getq());//生成公私钥
System.out.println("选择的两个素数是:"+makekey.getp()+"\t"+makekey.getq());
System.out.println("公钥、私钥以及N分别是:"+makekey.gete()+"\t"+makekey.getd()+"\t"+makekey.getfn());
String str="9";
int tempsic,tempming;
System.out.println("请输入要加密的字符串('0'退出)!");
while(str.charAt(0)!='0'){
str=scan.nextLine();
tempsic=jiasic(Integer.parseInt(str));////??
tempming=jiesic(tempsic);
System.out.println("加密后是:"+tempsic);
System.out.println("解密后是:"+tempming);
}
}
public int jiasic(int num){//加密
return (int)Math.pow(num,makekey.gete())%makekey.getfn();
}
public int jiesic(int num){//解密
return (int)Math.pow(num, makekey.getd())%makekey.getfn();
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new jiajiesic();
}
}
从我的实现可以看出俩素数的选择违背了RSA的要求,但百位以上的素数的判定以及计算都是很困难的,至少对我来说是这样;还有就是在加解密的过程中是直接调用java.math的求方公式,是死算,没有加点技巧保证求方时不溢出,在遇到大的数时会计算溢出导致结果不正确,所以验证时也最好选择20以内的数验证,有时20以内的数计算也会溢出!
正确运行结果如下: