POJ2447 RSA【公匙密码】

题目链接:

http://poj.org/problem?id=2447


题目大意:

RSA是个有名的公匙密码系统。在这个系统中,每个参与者有一个只能自己知道的私匙和一个每个人都

知道的公匙。为了安全地把信息传递给对方,应该用公匙对信息进行加密,对方用自己的私匙进行解密。

对RSA系统的描述如下:
首先,选择两个大素数P、Q,计算N = P * Q。

然后,选择一个正整数E作为加密密匙,令T = (p-1)*(q-1),且gcd(E,T) = 1。
最后,计算解密密匙D,使得(E * D) mod T = 1,这里D是E模T的逆元。

公匙表示为{E,N},私匙表示为{D,N},P和Q被舍弃。

加密数据的过程为
C = M^E mod N
解密数据的过程为
M = C^D mod N

M是一个比N小的非负整数成为明文,C是密文。
现在问题来了:给你密文C和公匙{E,N},能找到明文M吗?


思路:

因为N是一个大整数,先用PollardRho对N做大整数的数分解,得到一个素因子P,那么另一个素因子

Q = N/Q,这样得到了两个素数p和q。再求出T = (P-1)*(Q-1)。然后用扩展欧几里得的方法求出E关于

模T的逆元D。根据公匙M = C^D mod N,从而得到明文。


AC代码:

#include<iostream>
#include<algorithm>
#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#define LL long long
using namespace std;

LL mod_mul(LL x,LL y,LL mo)
{
    LL t;
    x %= mo;
    for(t = 0; y; x = (x<<1)%mo,y>>=1)
        if(y & 1)
            t = (t+x) %mo;

    return t;
}
//LL mod_mul(LL x,LL y,LL mo)
//{
//    LL t,T,a,b,c,d,e,f,g,h,v,ans;
//    T = (LL)(sqrt(double(mo)+0.5));
//    t = T*T - mo;
//    a = x / T;
//    b = x % T;
//    c = y / T;
//    d = y % T;
//    e = a*c / T;
//    f = a*c % T;
//    v = ((a*d+b*c)%mo + e*t) % mo;
//    g = v / T;
//    h = v % T;
//    ans = (((f+g)*t%mo + b*d)% mo + h*T)%mo;
//    while(ans < 0)
//        ans += mo;
//    return ans;
//}
LL mod_exp(LL num,LL t,LL mo)
{
    LL ret = 1, temp = num % mo;
    for(; t; t >>=1,temp=mod_mul(temp,temp,mo))
        if(t & 1)
            ret = mod_mul(ret,temp,mo);

    return ret;
}

//PollarRho大整数因子分解
LL gcd(LL a,LL b)
{
    if(b == 0)
        return a;
    return gcd(b, a % b);
}

LL PollarRho(LL n, int c)
{
    int i = 1;
    srand(time(NULL));
    LL x = rand() % (n-1) + 1;
    LL y = x;
    int k = 2;
    while(true)
    {
        i++;
        x = (mod_exp(x,2,n) + c) % n;
        LL d = gcd(n+y-x,n);
        if(1 < d && d < n)
            return d;
        if(y == x)
            return n;
        if(i == k)
        {
            y = x;
            k *= 2;
        }
    }
}

void ExGCD(LL a,LL b,LL &d,LL &x,LL &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        d = a;
    }
    else
    {
        ExGCD(b,a%b,d,y,x);
        y -= x*(a/b);
    }
}

int main()
{
    LL p,q,t,c,e,n;
    while(cin >> c >> e >> n)
    {
        p = PollarRho(n,10007);
        q = n/p;
        t = (p-1)*(q-1);
        LL d,x0,y0;
        ExGCD(e,t,d,x0,y0);
        x0 = (x0%t + t) % t;
        cout << mod_exp(c,x0,n) << endl;
    }
    return 0;
}


你可能感兴趣的:(POJ2447 RSA【公匙密码】)