参考:
利用扩展欧几里得算法编程求逆元
蒙哥马利幂模算法(二分快速幂)
import java.math.BigInteger;
import java.util.Random;
import java.util.Scanner;
public class Exp3 {
public static void main(String[] args) {
BigInteger[] plainText;
BigInteger[] ciperText;
plainText=input();
BigInteger p=choosePQ();
System.out.println("p:"+p);
BigInteger q = choosePQ();
System.out.println("q:"+q);
BigInteger n =p.multiply(q);
System.out.println("n:"+n);
BigInteger on=p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
BigInteger e=new BigInteger("17");//e选择17
BigInteger d =extendedEuclidean(e,on);
System.out.println("d:"+d);
ciperText=rsaEncode(plainText,e,n);
System.out.println("加密结果:");
for (int i = 0; i < ciperText.length; i++) {
System.out.println(ciperText[i]);
}
char[] decodeText;
decodeText=rsaDecode(ciperText,d,n);
System.out.println("解密结果:");
for (int i = 0; i < decodeText.length; i++) {
System.out.print(decodeText[i]);
}
}
//输入明文并将明文处理成bigint类型
public static BigInteger[] input() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入要加密的明文");
String plaintext = sc.nextLine();
int[] plainInt = new int[plaintext.length()];
BigInteger[] plainBigint = new BigInteger[plaintext.length()];
for (int i = 0; i < plaintext.length(); i++) {
char plaintextChar = plaintext.charAt(i);
plainInt[i] = plaintextChar;
plainBigint[i]=BigInteger.valueOf(plainInt[i]);
}
return plainBigint;
}
public static BigInteger choosePQ() {
Random r = new Random();
String tempThree = "3";
BigInteger three = new BigInteger(tempThree);
BigInteger bigNum;
while (true) {
//生成长度为1024的0,1string字符串,获得1024bit位效果
while(true) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 1024; i++) {
sb.append(r.nextInt(2));
}
String str = sb.toString();
//将0,1字符串转换为10进制BigInteger类型
bigNum = new BigInteger(str, 2);
if(bigNum.compareTo(three)>0)
break;
}
//System.out.println(bigNum);
if (Miller_Rabin(bigNum)) {
break;
}
}
return bigNum;
}
public static boolean Miller_Rabin(BigInteger bigNum) {
String tempTwo = "2";
BigInteger two = new BigInteger(tempTwo);
//判断是否为偶数,是则一定不是素数
if (bigNum.mod(two).equals(BigInteger.ZERO)) {
return false;
}
int j = 0;
//获得n-1=2^k*q;
BigInteger k = BigInteger.ZERO;
//q最初的值就是n-1
BigInteger q = bigNum.subtract(BigInteger.ONE);
while (q.mod(two).equals(BigInteger.ZERO)) {
k = k.add(BigInteger.ONE);
q = q.divide(two);
}
int num_k = k.intValue();
Random r = new Random();
int flag = 0;
while (j < 128) {
BigInteger a = new BigInteger(bigNum.bitLength(), r);
while (true) {//确保a>0&&a<n-1
if (a.compareTo(bigNum.subtract(BigInteger.ONE)) < 0 && a.compareTo(BigInteger.ONE) > 0) {
break;
} else
a = new BigInteger(bigNum.bitLength(), r);
}
//当a^q mod n =1的时候有可能是素数
if (a.modPow(q, bigNum).equals(BigInteger.ONE))
flag = 1;
//当a^(2*q*i) mod n = n-1的时候有可能是素数
else {
for (int i = 0; i <= num_k - 1; i++) {
BigInteger twoPowI = BigInteger.valueOf(2^i);
if (a.modPow(twoPowI.multiply(q),bigNum).equals(bigNum.subtract(BigInteger.ONE))) {
flag = 1;
break;
}
}
}
j++;
}
if (flag == 0)
return false;
return true;
}
public static BigInteger extendedEuclidean(BigInteger a1,BigInteger b1){
BigInteger temp=b1;
if(a1.compareTo(b1)<0)
{
a1=b1.add(a1);
b1=a1.subtract(b1);
a1=a1.subtract(b1);
}
BigInteger q,r,x,y;
BigInteger x2 = new BigInteger("1");
BigInteger x1 = new BigInteger("0");
BigInteger y2 = new BigInteger("0");
BigInteger y1 = new BigInteger("1");
while(b1.compareTo(BigInteger.ZERO)>0){
q=a1.divide(b1);
r=a1.subtract(q.multiply(b1));
x=x2.subtract(q.multiply(x1));
y=y2.subtract(q.multiply(y1));
a1=b1;
b1=r;
x2=x1;
x1=x;
y2=y1;
y1=y;
}
y=y2;
if(y.compareTo(BigInteger.ZERO)<0)
y=y.add(temp);
return y;
}
public static BigInteger[] rsaEncode(BigInteger[] plainText,BigInteger e,BigInteger n){
BigInteger[] ciperText=plainText;
for (int i = 0; i < plainText.length; i++) {
BigInteger temp;
temp=MontgomeryPowerModule(plainText[i],e,n);
ciperText[i]=temp;
}
return ciperText;
}
public static char[] rsaDecode(BigInteger[] ciperText,BigInteger d,BigInteger n){
int[] toChar=new int[ciperText.length];
char[] decodeText=new char[ciperText.length];
for (int i = 0; i < ciperText.length; i++) {
BigInteger temp;
temp=MontgomeryPowerModule(ciperText[i],d,n);
toChar[i]=temp.intValue();
decodeText[i]=(char) toChar[i];
}
return decodeText;
}
public static BigInteger MontgomeryPowerModule(BigInteger a,BigInteger e,BigInteger n){
BigInteger result=BigInteger.ONE;
while(e.compareTo(BigInteger.ZERO)>0){
if(e.mod(BigInteger.TWO).compareTo(BigInteger.ONE)==0){
result = result.multiply(a).mod(n);
}
e=e.divide(BigInteger.TWO);
a=a.multiply(a).mod(n);
}
return result;
}
}