在计算机网络中,公钥密码系统在数字签名与保障信息机密有着重要的作用
目前最流行的是RSA公钥算法,今天我们来聊聊这个算法是怎么回事
篇幅较长
第一步:生成大素数
在rsa公钥的初始阶段 , 需要生成两个大素数 p 和 q
如何生成大素数
我们先来看费马小定理 – 对于质数p和任意整数a,有a^p ≡ a(mod p)(同余)。反之,若满足a^p ≡ a(mod p),p也有很大概率为质数。将两边同时约去一个a,则有a^(p-1) ≡ 1(mod p)
当然费马小定理是有可能选到合数的 ,要记住
在费马小定理中有a^p ≡ a(mod p) 对于幂取模的问题我们先说一小段代码
int quick_mod( int a , int b , int mod ){
int res =1 ;
a = a %mod ;
while( b ){
if( b & 1 ){
res = (res * a)%mod ;
}
a = (a*a)%mod;
b>>=1 ;
}
return res ;
}
这里是int但是真正的rsa用的是1024位的数 , 我们使用的是思路,这样的思路可以同样适用在1024位的数上
上面的代码是快速幂取模运算
思路很简单 把一个数的幂次方分解
比方说 1000 的 10次方
10的二进制( 也就是上面的b-1024位的数也可以) 1010
1000^10 = (1*1000^8) * (0*1000^4) * (1*1000^2) * (0*1000^1) ;
但是其实我们有个问题那就是当n很大时我们乘的时候有可能溢出
我们就需要这个算法的一个小兄弟 快速乘取模
long long quick_mul( long long a , long long b ,long long mod){
long long res = 0 ;
a = a%mod;
while( b != 0 ){
if( b &1 ){
res = (res+a) %mod;
}
b>>=1;
a = (a+a) %mod ;
}
return res;
}
再将快速幂模中的乘法换成现在这个快速乘取模就可以了
上面就是这个过程
那么我们可以实现费马小定理了
接着米勒-雷宾提出了二次探测法:如果p是奇素数,则 x^2 ≡ 1(mod p)的解为 x ≡ 1 或 x ≡ p - 1(mod p)
如果a^(n-1) ≡ 1 (mod n)成立,Miller-Rabin算法不是立即找另一个a进行测试,而是看n-1是不是偶数。如果n-1是偶数,另u=(n-1)/2,并检查是否满足二次探测定理即a^u ≡ 1 或 a^u ≡ n - 1(mod n)。
Miller_Rabin素数测试
这里我直接写代码
bool Miller_Rabin( long long n ){
if( n <= 2 ){ // 小于2的情况
return n == 2 ;
}
if( n % 2 == 0 ){ // 偶数
return false ;
}
// 米勒_罗宾测试 反过来判断
long long u = n -1 ;
while( u % 2 == 0 ){
u = u / 2 ;
}
for( int i= 0 ; i < 13 &&mp[i]<n; i++){
long long a = mp[i] ; //这里就是随机数,这里挑了推荐的13个
long long x = quick_mod( a , u , n ) ;
while( u < n ){
long long y = quick_mod( x , 2, n ) ;
if( y==1 && x!=1 && x!=(n-1)){
return false ;
}
x = y ;
u = u* 2 ;
}
if( x != 1)
return false ;
}
return true ;
}
那么我们可以自己试试这个代码
到此我们说完了RSA的生成两个大素数的过程