#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<time.h>
using namespace std;
typedef long long LL;
const int TIMES=5; //米勒罗宾素数测试次数
const int EXP=500000; //p和q的差距
LL p,q,n,e,d,t;
LL big_rand(LL m) //生成大的随机数
{
LL x=rand();
x*=rand();
if(x<0) x=-x;
return x%=m;
}
LL mul(LL a,LL b,LL mod) //快速乘法,解决模大数的时候乘法溢出的问题
{
LL ans=0;
while(b)
{
if(b&1) ans=(ans+a)%mod;
b>>=1;
a=(a+a)%mod;
}
return ans;
}
LL quickpow(LL a,LL b,LL mod) //快速幂
{
LL ans=1;
while(b)
{
if(b&1) ans=mul(ans,a,mod);
b>>=1;
a=mul(a,a,mod);
}
return ans;
}
LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;}
LL exgcd(LL a,LL b,LL &x,LL &y) //扩展gcd
{
LL d;
if(!b) {x=1;y=0;return a;}
d=exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
bool Miller_Rabbin(LL x) //米勒-罗宾测试
{
LL a,m=(x-1)>>2,i=1;
do{
a=(LL)rand()*rand()%(x-1)+1;
if(quickpow(a,x-1,x)!=1) return 0;
}while(i++<m);
return 1;
}
void get_prime(LL &x,LL &y) //素数生成
{
LL m=(LL)rand()*rand();
x=big_rand(m);
while(!Miller_Rabbin(x)) x=big_rand(m);
y=big_rand(m);
while(!(abs(x-y)<=EXP&&Miller_Rabbin(y))) y=big_rand(m);
}
LL get_e(LL n) //产生和互为素数的E
{
LL e;
while(true)
{
e=(LL)rand()*rand();
if(e<t&&gcd(t,e)==1LL) return e;
}
}
void get_key() //密钥生成
{
LL y;
printf("密钥生成中,请等待……\n");
get_prime(p,q); //产生两个值接近的素数
printf("生成的素数:%I64d %I64d\n",p,q);
n=p*q;
t=(p-1)*(q-1); //n的欧拉函数值
e=get_e(t); //生成和t互质的e
exgcd(e,t,d,y); //求e模t的逆d
if(d<0) d+=t; //为负数的话得加上t
puts("产生的密钥如下:");
printf("公钥:(n,e):(%I64d,%I64d)\n",n,e);
printf("私钥:(n,d):(%I64d,%I64d)\n",n,d);
}
LL encode(LL x) //加密
{
return quickpow(x,e,n);
}
LL decode(LL x) //解密
{
return quickpow(x,d,n);
}
void control() //控制函数
{
while(true)
{
puts("请选择:1.加密 2.解密");
int ch;
scanf("%d",&ch);
if(ch!=1&&ch!=2) break;
LL M;
printf("请输入明文或者密文:");
scanf("%I64d",&M);
if(ch==1) M=encode(M);
else M=decode(M);
printf("加/解密结果为:%I64d\n",M);
}
}
int main()
{
srand(unsigned(time(NULL)));
get_key();
control();
return 0 ;
}
RSA
最新推荐文章于 2023-08-12 12:24:02 发布