好久好久才搞出的RSA
花了一天的时间才搞出来
RSA没有任何理解上的难度,只不过换成大数来实现BigInteger
BigInteger
关于java BigInteger用法:
import java.util.Scanner;
import java.util.Arrays;
import java.util.Base64;
import java.math.*;
import java.security.SecureRandom;
import java.io.*;
import java.util.Random;
public class RSA{
final static Base64.Decoder decoder = Base64.getDecoder();
final static Base64.Encoder encoder = Base64.getEncoder();
public static BigInteger x,y;
public static void main(String []args) throws Exception
{
System.out.println("*******************************RSA**********************************");
System.out.println("text输入可以是任何字符,最大为多大我也没试过");
System.out.println("*******************************RSA**********************************");
int stop=0;
while(stop==0)
{
System.out.println("Please select 0加密 or 1解密:");
int select;
Scanner input0=new Scanner(System.in);
select=input0.nextInt();
if(select==0)
{System.out.println("Please input your text:");
Scanner input=new Scanner(System.in);
String text=input.nextLine();
encrypt(text);
}
else
{
System.out.println("Please input your text:");
Scanner input1=new Scanner(System.in);
String text1=input1.nextLine();
/* System.out.println("Please input your Privatekey:");
Scanner input2=new Scanner(System.in);
String key=input2.nextLine();
System.out.println("Please input your n:");
Scanner input3=new Scanner(System.in);
String n=input3.nextLine();
BigInteger N=new BigInteger(n);*/
decode(text1);
}
System.out.println("***********press 0 to continue,press 1 to stop************");
Scanner input4=new Scanner(System.in);
stop=input4.nextInt();
}
}
static void encrypt(String text) throws IOException//加密
{
byte []binary=text.getBytes("UTF-8");
String text1=encoder.encodeToString(binary);
byte []binarys=text1.getBytes();
BigInteger text2=new BigInteger(binarys);
Random rnd = new Random();
BigInteger p=BigInteger.probablePrime(512,rnd);
BigInteger q=BigInteger.probablePrime(1024,rnd);
BigInteger e=new BigInteger("65535");
BigInteger n=p.multiply(q);
System.out.println("n:"+n.toString());
BigInteger fn=p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
for(int h=0;;h++)
{
if(!fn.gcd(e).equals(BigInteger.ONE))
e=new BigInteger(512,rnd);
exgcd(e,fn);
BigInteger temp=x;
exgcd(temp,fn);
if(!e.equals(x))
continue;
x=temp;
if(!x.equals(BigInteger.ONE))
break;
}
BigInteger d;
if(x.add(BigInteger.ONE).abs().subtract(x.abs()).equals(BigInteger.ONE))
d=x;
else d=fn.add(x);
File i=new File("CA.txt");
FileWriter in=new FileWriter(i);
PrintWriter input=new PrintWriter(in);
System.out.println("e:"+e);
System.out.println("fn:"+fn);
System.out.println("d:"+d);
System.out.println("明文:"+text2);
BigInteger C=fastmodmi(text2,e,n);
String str1=d.toString();
String str2=n.toString();
input.println(str1);
input.println(str2);
System.out.println("密文:"+C);
in.close();input.close();
}
static void decode(String text) throws IOException
{
BigInteger text1=new BigInteger(text);
FileReader in=new FileReader("CA.txt");
BufferedReader input=new BufferedReader(in);
String d=input.readLine();
String n=input.readLine();
in.close();
BigInteger N=new BigInteger(n);
BigInteger privatekey=new BigInteger(d);
BigInteger m=fastmodmi(text1,privatekey,N);
String text2="";
byte []binarys=m.toByteArray();
for(int i=0;i<binarys.length;i++)
text2=text2+(char)binarys[i];
System.out.println("明文:"+new String(decoder.decode(text2), "UTF-8"));
}
static BigInteger fastmodmi(BigInteger m,BigInteger e,BigInteger n)//快速幂
{
BigInteger temp=m;
BigInteger mod1=new BigInteger("1");
for(int i=0;;i++)
{
if(e.and(BigInteger.ONE).equals(BigInteger.ONE))
mod1=mod1.multiply(temp).mod(n);
e=e.shiftRight(1);
if(e.equals(BigInteger.ZERO))
break;
temp=temp.multiply(temp).mod(n);
}
return mod1;
}
public static void exgcd(BigInteger a,BigInteger p){//求模的逆元
if(p.equals(BigInteger.ZERO)){
x=BigInteger.ONE;
y=BigInteger.ZERO;
return;
}
exgcd(p,a.mod(p));
BigInteger k=x;
x=y;
y=k.subtract(a.divide(p).multiply(y));
}
}
**本来很简单的一个算法,但是期间出现了各种错误。
1、一开始是没将base64的编码给改成整数,导致BigInteger一直报错。
2、快速幂一开始也没搞清楚谁是谁,哎
3、最惨的是我一直没弄懂私钥怎么求,还以为是一个一个的试,发现要花好多的时间。后来又怀疑大数的分解因子是个难题这句话,才反应过来n的欧拉函数通过两个素数求,但是这两个素数只有我知道,其他人什么都有不知道,也不能分解出,原来如此!辗转相除法出现在我的眼前。
4、最后一个问题是n太小,而加密的明文有太大,那就不可能解密的了,哎。
**