第一步,选择密钥
p、q
r = p x q
φ(r) = (p-1) * (q-1)
φ(r)
互质的量 k
,即保证 gcd(φ(r), k) = 1
时,选择 k
。 可以令 sp = k
或 pk = k
。因为与 φ(r)
互质的数可能不止一个,所以 k
的值是有选择的。可以先设 k
为一个初值,并且 k < φ(r)
,然后用试探法求出满足条件 φ(r)
与 k
的最大公约数为 1 的 k,即 gcd(φ(r), k) = 1
。
注意,如果选一个密钥的值大于 φ(r)
的值,就不能正确求出另一个密钥。
sk * pk ≡ 1 mod φ(r)
,已知 sk 或 pk,用乘逆算法求 pk 或 sk。第二步,加密
对明文自乘 pk 次幂或 sk 次幂,再按模 r 求余,就可得到密文。
第三步,解密
与加密过程类型,对密文自乘 pk 次幂或 sk 次幂,再按模 r 求余,就可得到明文。
// 拓展gcd
void exgcd(ll a,ll b,ll& d,ll& x,ll& y){
if(!b) {
d = a; x = 1; y = 0; }
else{
exgcd(b, a%b, d, y, x); y -= x*(a/b); }
}
// 求逆元
ll inv(ll a, ll p){
ll d,x,y;
exgcd(a,p,d,x,y);
return d == 1 ? (x+p)%p : -1;
}
使用 RSA 算法进行加密和解密时需要用到此算法,也就是我们所说的快速幂,下面给出对应模板。
#include
#define mst(a,b) memset(a,b,sizeof(a);
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
// ¿ìËÙÃÝ
ll poww(ll a,ll b,ll mod){
ll ans=1,base=a;
while(b){
if(b&1)
ans = ans*base%mod;
base = base*base%mod;
b>>=1;
}
return ans;
}
int main(){
cout<<poww(34,60,51)<<endl; //34
cout<<poww(345,89,101)<<endl; //34
}
有了上述两段关键代码后,我们的整个加密算法就简单了,下面给出整体实现源码:
#include
#define mst(a,b) memset(a,b,sizeof(a);
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=1e3+5;
int n,m,t;
typedef long long ll;
// 拓展gcd
void exgcd(ll a,ll b,ll& d,ll& x,ll& y){
if(!b) {
d = a; x = 1; y = 0; }
else{
exgcd(b, a%b, d, y, x); y -= x*(a/b); }
}
// 求逆元
ll inv(ll a, ll p){
ll d,x,y;
exgcd(a,p,d,x,y);
return d == 1 ? (x+p)%p : -1;
}
// 快速幂
ll poww(ll a,ll b,ll mod){
ll ans=1,base=a;
while(b){
if(b&1)
ans = ans*base%mod;
base = base*base%mod;
b>>=1;
}
return ans;
}
// 加密过程
ll encryption(ll pk,ll r,ll num){
return poww(num,pk,r)%r;
}
// 解密过程
ll decrypt(ll sk,ll r,ll text){
return poww(text,sk,r)%r;
}
int main(){
ll prime1,prime2,pk;
cout<<"请输入测试数据组数:"<<endl;
cin>>t;
while(t--){
cout<<"请输入两个大的素数和公钥"<<endl;
cin>>prime1>>prime2>>pk;
// 公开模数
ll r = prime1 * prime2;
// 欧拉函数
ll n = (prime1-1)*(prime2-1);
cout<<"公开模数r为:"<<r<<endl;
ll sk = inv(pk,n);
cout<<"私钥sk为:"<<sk<<endl;
cout<<"请输入要加密的数字串(输入0结束):"<<endl;
ll num;
cin>>num;
while(num){
// 密文
int cipherText = encryption(pk,r,num);
cout<<"加密后的密文为:"<<cipherText<<endl;
// 明文
int plainText = decrypt(sk,r,cipherText);
cout<<"解密后的明文为:"<<plainText<<endl;
cin>>num;
}
}
return 0;
}
学如逆水行舟,不进则退