快要闲的被开除了 所以我决定做些其他事加速我程序生涯的结束
翻到rsa算法 发现物理是神的学科 数学是成神之前的学科
为寻其原理(为自己写个简单demo)搜了一下
有这个网址和这个网址说的比较好(对于我这种一点都没了解过的)
=========
rsa的内涵在于公私钥的加解密
http中是明文传输,https中ssl就有用到类似的公私钥外加证书认证做到保密。
==========
rea加解密过程
注:≡是同余数的意思 比如 1≡3 mod 2 成立,1和3% 2都是1下面有de≡1 mod f(n)
(1)选择一对不同的、足够大的素数p,q。
(2)计算n=pq。
(3)计算f(n)=(p-1)(q-1),同时对p, q严加保密,不让任何人知道。
(4)找一个与f(n)互质的数e,且1<e<f(n)。
(5)计算d,使得de≡1 mod f(n)。这个公式也可以表达为d ≡e-1 mod f(n)
这里要解释一下,≡是数论中表示同余的符号。公式中,≡符号的左边必须和符号右边同余,也就是两边模运算结果相同。显而易见,不管f(n)取什么值,符号右边1 mod f(n)的结果都等于1;符号的左边d与e的乘积做模运算后的结果也必须等于1。这就需要计算出d的值,让这个同余等式能够成立。
(6)公钥KU=(e,n),私钥KR=(d,n)。
(7)加密时,先将明文变换成0至n-1的一个整数M。若明文较长,可先分割成适当的组,然后再进行交换。设密文为C,则加密过程为:
。
(8)解密过程为:
。
(1)选择一对不同的、足够大的素数p,q。
int p = 997 ,q = 1009 ;
这个刚好是1000000多点 验证码或银行密码的6位数能放进去。。。
(2)计算n=pq。
int n = p*q;//p*q
(3)计算f(n)=(p-1)(q-1),同时对p, q严加保密,不让任何人知道。
int fn = (p-1)*(q-1); //(p-1)*(q-1);
(4)找一个与f(n)互质的数e,且1<e<f(n)。
int e = Util.getCoprimeList(fn);//93733 ;//Util.getCoprimeList(fn);
原谅我搞android的习惯性工具函数类放一个Util.java里
//返回一个小点的互质数
public static int getCoprimeList(int num){
int coprime = 3;
for( ;coprime <= num ;coprime++){
if(check2(num,coprime))
return coprime;
}
return 1;
}
//判断是否互质
public boolean check(int m, int n)
{
return check2(m > n ? m : n, m <= n ? m : n);
}
public static boolean check2(int max, int min)
{
int mo = max % min;
Log.e("ssh",max + " "+ min);
if (mo == 0) {
return min == 1 ? true : false;
}
else {
return check2(min, mo);
}
}
本来设置互质数从随机中间数开始找 结果运算就爆炸了 管他的小点就小点
(5)计算d,使得de≡1 mod f(n)。这个公式也可以表达为d ≡e-1 mod f(n)
本来看到这个一下懵逼了,搜了同余是什么 同余怎么求解 上面给的第二个链接教我了解决方法 成神前的数学
网页中给的demo里f(n)=(p-1)(q-1)= 18442 × 49890= 920071380 e = 19,求d
d满足:e * d ≡ 1 (mod f(n))
即(19 * d) mod 920071380 = 1
欧几里德算法(辗转相除法)求d
循环,直至d 的系数为 1, 即e位置=1时结束
[a式]19×d - 920071380×k =1 (k 为正整数)
[b式]19×d - 9×k =1 将f(n)位置 mod e位置 的余数9代替f(n)位置
[c式]1×d - 9×k=1 将e位置 mod f(n)位置 的余数1代替e位置
e位置=1,结束,然后
令k=0,带入[c式],得d=1;
d=1,带入[b式],得k=2;
k=2,带入[a式],得d=96849619
到这里求出d值了
于是就有了我自己的破算法
int d = Util.getD(e,fn);
//求d
public static int getD(int e , int fn){
int k = 1, d = 1;
ArrayList<Integer> eList = new ArrayList();
ArrayList<Integer> fnList = new ArrayList();
eList.add(e);
fnList.add(fn);
boolean trueOrFalse = true;
while (e != 1 && fn != 1){
if(trueOrFalse){
fn = fn % e;
trueOrFalse = false;
}
else{
e = e % fn;
trueOrFalse = true;
}
eList.add(e);
fnList.add(fn);
}
for (int i = eList.size()-1 ; i >= 0 ; i--){
if(i%2 == 0){
d = (fnList.get(i)*k+1)/eList.get(i);
}
else{
k = (eList.get(i)*d-1)/fnList.get(i);
}
}
return d;
}
(6)公钥KU=(e,n),私钥KR=(d,n)。
然后就能得到我们自己的 我demo得到的 e=5 n=1005973 d=602381
(7)加密时,先将明文变换成0至n-1的一个整数M。若明文较长,可先分割成适当的组,然后再进行交换。设密文为C,则加密过程为:。
话说这步真的很麻烦被加密的m必须小于n 太长就要分割 (要传汉字基本可以一个字一个字加密了) 而且e次方绝对会超过java 的int,long上限 原先我互质数e设为从中间随机去查找几万都出来了 妥妥的超过double。就按时间复杂度最差的写了递归函数(因为我省事不用想啊)
int mima = 333333;
int c = (int) Util.getC(mima,e,n);
// 加密过程为:C≡M^e(mod n)。
public static double getC(double M, int e ,int n){
//10 3 33
int i = 1;
double mod = M;
while ( i< e ){
mod = (mod*M)%n;
i++;
}
return mod;
}
(8)解密过程为:

int M = (int) Util.getC(c,d,n);//(int) (Math.pow(c,d)%n);
我的控制台打印结果 (没人发现我用的androidstudio吧)
需要不同公钥私钥只要改变互质数e 或素数p,q(这个改了e也改了)
有大佬有更好的算法见解欢迎留言