Rabin简单加解密

算法描述

程序分为两个部分,一部分加密,一部分解密。
解密部分:先通过生成大素数算法生成公钥n和私钥p、q,然后运用广义欧几里得除法计算s,t使sp+tq=1,然后输入用公钥加密的密文c,然后计算同余式x^2=c(modn)的四个根(在求解时可以不用中国剩余定理,直接采用当p=q=3(mod4)时的定理,直接由s,t求解),然后用校验值判断出真正的解,得到明文。
加密部分:先将文本转换为整数,然后在转换后的值中加入校验值,然后利用获得的公钥计算c=m^2(modn)得到密文。

加密类中

1、 生成大素数直接采用java中自带的大数的类的函数BigInteger.probablePrime(n,rnd),rnd为随机数因子,n为生成的随机大素数的二进制的位数,设置n为100时的生成结果如下:

2、 运用广义欧几里得除法时,定义两个数组long s[]= {1,0,0};long t[]= {0,1,0}s[0]为s-2,s[1]为s-1,t同理;设置while循环,当r2!=0时进行循环运算,最后s,t的大小即为s[1]和t[1]。相关代码如下:

3、 解密过程中对于二次同余方程,当p=q=3(mod4)用如下解的公式,u=c[(p+1)/4](modp)。v=c(q+1)/4。x=(tqu+spv)(modn)。y=(tqu-spv)(modn)。四个解分别为x,y,n-x,n-y,将相关公式用程序式表示,程序如下:

4、 进行校验部分,因为会解出四个值,所以在进行加密时加入了校验值,解密时需要根据校验值找出四个解中真正的解,程序中采用在密文的二进制后加入额外的01字符串作为校验值,所以在解出四个解后,将其转化为二进制字符串,将其末尾的01字符串与校验值进行比较,最后将校验值删除,再将二进制字符串转换得到明文,此处校验值为010,程序如下:

解密类中

1、 将文本形式的明文进行编码,转换为整数,这里先将输入的字符串转换为char型数组,再转换为二进制数,再将二进制数转换为十进制整数,程序如下:

2、 添加校验值,为了能从四个解中找出唯一的解,需要在值后面加入校验值,这里先将明文转换为二进制字符串,再在字符串的末尾加入01的二进制校验值,程序中校验值为010,程序如下:

3、 最后由得到的公钥计算c=m^2(modn)得到密文c,程序如下:

另:由于所需计算的数字远远超出了java的int,long的变量类型,所以在程序的运算中运用了java的BigInteger类,可以用该类的方法计算大数的加减乘除等运算,相关方法如下:
BigInteger.add(b)); //大整数加法,b也为一个大数
BigInteger.subtract(b)); //大整数减法
BigInteger.multiply(b)); //大整数乘法
BigInteger.divide(b)); //大整数除法(取整)
BigInteger.remainder(b)); //大整数取模
BigInteger.pow(exponent)); //大整数a的exponent次幂

程序

加密

package rabin;

import java.math.BigInteger;
import java.util.Scanner;

public class Encrypt {

	public static void main(String[] args) {
		
		System.out.println("请输入 ");
		Scanner in = new Scanner(System.in);
		String str = in.next();
		
		
		//将string转化为char数组,再转化为2进制字符串,再转换为整数
		char[] strchar = str.toCharArray();
		long binary=0;
		for(int i=0;i<strchar.length;i++) {
			binary=binary+Integer.parseInt((Integer.toBinaryString(strchar[i])),2);
		}
		System.out.println("明文为: "+binary);
		
		//添加校验信息,这里设置为010
		String strbinary=Long.toString(Integer.parseInt(Long.toBinaryString(binary)+"010",2));
		binary=Long.valueOf(strbinary);
		
		System.out.println("请输入公钥:  ");
		BigInteger n = in.nextBigInteger();
		BigInteger m = new BigInteger(Long.toString(binary*binary));
		BigInteger c = m.remainder(n);
		System.out.println("加密结果为:"+c);
		
	}

}

解密

package rabin;

import java.math.BigInteger;
import java.util.Random;
import java.util.Scanner;

public class Decrypt {

	public static void main(String[] args) {
		//生成大素数
		Random rnd = new Random();
		BigInteger p = BigInteger.probablePrime(20,rnd);//生成2进制为n位的大素数p,n可以设置,为了方便这里设置为20
		BigInteger q = BigInteger.probablePrime(20,rnd);//生成2进制为n位的大素数q
		BigInteger n = p.multiply(q);//私钥p,q相乘得到公钥n
		
		
		System.out.println("公钥为: "+n+" 私钥为: "+p+"和"+q);
		System.out.println("输入要解密的内容");
		Scanner in = new Scanner(System.in);
		BigInteger c = in.nextBigInteger();
		
		
		//用广义欧几里得出发求s,t使s*p+t*q=1;
		long s[]= {1,0,0};
		long t[]= {0,1,0};
		long r1=p.longValue();
		long r2=q.longValue();
		long tmp;
		long i=r1/r2;
		tmp=r2;
		r2=r1%r2;
		r1=tmp;
		while(r2!=0) {
			s[2]=s[0]-i*s[1];
			t[2]=t[0]-i*t[1];
			s[0]=s[1];
			s[1]=s[2];
			t[0]=t[1];
			t[1]=t[2];
			if(r2!=0)
				i=r1/r2;
			tmp=r2;
			r2=r1%r2;
			r1=tmp;
		}
		BigInteger S=BigInteger.valueOf(s[1]);
		BigInteger T=BigInteger.valueOf(t[1]);
		
		//开始解密
		int P=(p.intValueExact()+1)/4;
		int Q=(q.intValueExact()+1)/4;
		BigInteger u=(c.pow(P)).remainder(p);
		BigInteger v=(c.pow(Q)).remainder(q);
		BigInteger x1 = ((T.multiply(q.multiply(u))).add(S.multiply(p.multiply(v)))).remainder(n);
		BigInteger x2 = n.subtract(x1);
		BigInteger y1 = ((T.multiply(q.multiply(u))).subtract(S.multiply(p.multiply(v)))).remainder(n);
		BigInteger y2 = n.subtract(y1);
		
		//用校验值对四个解密结果进行判断
		String a= x1.toString(2);
		String b= x2.toString(2);
		String e= y1.toString(2);
		String d= y2.toString(2);
		String result[]= {a,b,e,d};
		for(int j=0;j<result.length;j++) {
			if(result[j].lastIndexOf("010",result[j].length()-3)==result[j].length()-3) {
				result[j]=result[j].substring(0,result[j].length()-3);
				System.out.println("解密得: "+Long.valueOf(result[j], 2));
				break;
			}
		}
		
	}
	
}

运行结果

加密

解密

posted @ 2020-01-21 14:53  启林O_o  阅读(1018)  评论(0编辑  收藏  举报