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次幂

程序#

加密

Copy
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); } }

解密

Copy
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 @   启林O_o  阅读(1127)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
点击右上角即可分享
微信分享提示
CONTENTS