RSA

#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 ;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值