java实现的简单RSA加解密算法

时间:2021-01-01 18:32:09

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以内的数计算也会溢出!

正确运行结果如下:

java实现的简单RSA加解密算法