1.RSA 非对称加密算法的一种。
2.一些基础知识:
1) gcd(a, b) 为a, b的最大公约数,如果gcd(a, b) = 1,则称a, b 互素。
2) 模运算, mod。如果(a mod n) = (b mod n),则称a与b模n同余。
3)欧拉函数,定义φ(n)为欧拉函数,那么φ(n)的值为比n小并且与n互为素数的正整数的个数。比如φ(9) = |{8, 7, 5,4,2,1}|=6。
4)欧拉函数的性质1:如果p是素数,则φ(p) = p - 1,例如φ(7) = |{6, 5, 4, 3, 2, 1}| = 6。
5)欧拉函数的性质2:如果p, q是素数,则 φ(p*q) = (p-1) * (q - 1)。
6)欧拉定理:在数论中,欧拉定理(也称费马-欧拉定理)是一个关于同余的性质。欧拉定理表明,若n,a为正整数,且n,a互质,gcd(a,n) = 1,则a^φ(n) ≡ 1 (mod n)。例如a = 3, n = 5,gcd(3,5) = 1,φ(n) = φ(5) = 5 -1 = 4, a^φ(n) = 3^4 = 81, 81 mod 5 = 1,满足欧拉定理。
7)欧拉定理的证明:
首先证明下面这个命题:
对于集合Zn={x1,x2,...,xφ(n)},其中xi(i=1,2,…φ(n))是不大于n且与n互素的数,即n的一个化简剩余系,或称简系,或称缩系),考虑集合S = {a*x1(mod n),a*x2(mod n),...,a*xφ(n)(mod n)}
则S = Zn
1) 由于a,n互质,xi也与n互质,则a*xi也一定于n互质,因此
任意xi,a*xi(mod n) 必然是Zn的一个元素
2) 对于Zn中两个元素xi和xj,如果xi ≠ xj
则a*xi(mod n) ≠ a*xj(mod n),这个由a、n互质和消去律可以得出。
所以,很明显,S=Zn
既然这样,那么
(a*x1 × a*x2×...×a*xφ(n))(mod n)
= (a*x1(mod n) × a*x2(mod n) × ... × a*xφ(n)(mod n))(mod n)
= (x1 × x2 × ... × xφ(n))(mod n)
考虑上面等式左边和右边
左边等于([a^φ(n)] *(x1 × x2 × ... × xφ(n))) (mod n)
右边等于x1 × x2 × ... × xφ(n))(mod n)
而x1 × x2 × ... × xφ(n)(mod n)和n互质
根据消去律,可以从等式两边约去,就得到:
a^φ(n) ≡ 1 (mod n)
3.RSA算法的操作过程
1)取两个大素数p, q,保密。计算n = p * q,公开n。
2)计算欧拉函数φ(n) = (p - 1) * (q - 1);
3)任意取一个与φ(n)互为素数的小整数e1,则gcd(e, φ(n)) = 1,1 < e < φ(n),公开e,作为公钥用于加密(或者签名验证)。
4)寻找e2,使得e1^e2 ≡ 1 (mod φ(n)),即是(e1*e2)mod((p-1)*(q-1))=1。
5)(n及e1),(n及e2)就是密钥对,可以分别为公钥与私钥。RSA加解密的算法完全相同,设A为明文,B为密文,则:A=B^e1 mod n;B=A^e2 mod n;
e1和e2可以互换使用,即:A=B^e2 mod n;B=A^e1 mod n;
6)举一个例子:
选取两个素数(在实际应用中应该选取两个大素数) p = 3, q = 11;
计算n = p * q = 33;
计算φ(n) = (p - 1) * (q - 1) = 2 * 4 = 20;
我们来寻找一个e1 (参看上面的操作过程3), 我们取为3,现在来寻找e2;
寻找e2的过程是一个试探的过程,总之要满足e1^e2 ≡ 1 (mod φ(n));
e2 e1 * e2 e1*e2 mod φ(n) 判断
1 3 3 mod 20 = 3 不满足
2 6 6 mod 20 = 6 no
3 9 9 mod 20 = 9 no
4 12 12 mod 20 = 12 no
5 15 15 mod 20 = 15 no
6 18 18 mod 20 = 18 no
7 21 21 mod 20 = 1 yes
.....................
后面肯定还可以找到,不过我们到此结束
现在我们得到密匙对,去公钥(33, 3) , 私钥(33, 7);
对于一个明文:B = 5
加密: 密文A = 5 ^3 mod 33 = 26;
解密: 明文B = 26^ 7 mod 33 = 5;
下面这段小代码是计算过程(顺便贴上):
public class Test {
public static void main(String[] args) {
long i = (long)Math.pow(5, 3) % 33;
System.out.println(i);
System.out.println((long)Math.pow(i,7) % 33);
}
}