[POJ2447] RSA

博客内容介绍了如何破解RSA加密系统,通过找到N的质数因子P和Q,使用PollardRho算法,然后利用扩展欧几里得求解私钥D,最后通过pow_mod计算原文M。解题过程中需要注意模运算的细节,避免WA。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

题目大意:

一个公钥密钥系统,给出C(密文),{E, N}公钥,要求破解出原文M


解题思路:

思路其实很简单。

1)由N破解出P和Q,得到T=(P-1)*(Q-1)

用PollardRho找出一个的质数因子(经过验证,不需要MillerRabin和二分配合,因为这个n肯定只有P和Q这两个非平凡因子)

PS:代码换过,不过注释掉的MillerRabin和二分部分继续留着,可以过POJ1811~

2)用扩展欧几里得求D

由于E和T是互质的,也就是gcd(E, T)=1。 (E * D) mod T = 1。用扩展欧几里得求解欧几里得方程E*D+T*K=gcd(E, T)=1即可。

最后用D=(D%T+T)%T处理了一下,也不确定是否必须。WA了无数次,这里写成%N了,坑爹啊!

3)pow_mod(C, D, N)


源代码:

其中很多模板都是用别人的,网上搜了几个源代码发现都TLE或者WA了,所以把自己这个拼凑的和尚的破袈裟贴一下……

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <limits.h>
#include <ctime>
using namespace std;

#define int64_t __int64
#define TIME 100

int64_t gcd(int64_t a,int64_t b)
{
    while(b)
    {
        int64_t t=a%b;
        a=b;
        b=t;
    }
    return a;
}

int64_t mul_mod(int64_t a, int64_t b, int64_t n){
    int64_t tmp=0;
    while(b)
    {
        if(b&1){
            tmp+=a;
            tmp%=n;
        }
        a<<=1;
        a%=n;
        b>>=1;
    }
    return tmp;
}

int64_t pow_mod(int64_t a, int64_t n,int64_t m)
{
    int64_t p=1;
    for(int64_t i=1;i<=n;i<<=1)
    {
        if(i&n) p=mul_mod(p,a,m);
        a=mul_mod(a,a,m);
    }
    return p;
}

int64_t usr_abs(int64_t x){return x>0?x:-x;}

//bool MillerRabin(int64_t n, int tries) //Return true if prime
//{
//    if(n==1) return false;
//    if(n==2||n==3) return true;
//    if(!(n&1)) return false;
//    int64_t d=n-1;
//    int s=0;
//    while(!(d&1)) {d>>=1;s++;}
//    while(tries--)
//    {
//        int64_t x=pow_mod(usr_abs((int64_t)rand())%(n-3)+2,d,n),y;
//        for(int j=0;j<s;j++)
//        {
//            y=mul_mod(x,x,n);
//            if(y==1&&x!=1&&x!=n-1) return false;
//            x=y;
//        }
//        if(x!=1) return false;
//    }
//    return true;
//}


int64_t PollardRho(int64_t n) //n shouldn't be prime
{
    if(!(n&1)) return 2;
    while(true)
    {
        int64_t x=usr_abs((int64_t)rand())%n,y=x;
        int64_t c=usr_abs((int64_t)rand())%n;
        if(c==0||c==2) c=1;
        for(int i=1,k=2;;i++)
        {
            x=mul_mod(x,x,n);
            if(x>=c) x-=c; else x+=n-c;
            if(x==n) x=0;
            if(x==0) x=n-1; else x--;
            int64_t d=gcd(x>y?x-y:y-x,n);
            if(d==n) break;
            if(d!=1) return d;
            if(i==k) {y=x;k<<=1;}
        }
    }
}

//int64_t get_small(int64_t n)
//{
//    int64_t m, tmp1, tmp2;
//    if (MillerRabin(n, TIME)) return n;
//    m=PollardRho(n);
//    tmp1=get_small(m);
//    tmp2=get_small(n/m);
//    return tmp1<tmp2?tmp1:tmp2;
//}

//Solve ax+by=(a,b)
void gcd_solve(int64_t a, int64_t b, int64_t &x, int64_t &y)
{
    if (b==0){x=1;y=0;}
    else
    {
        gcd_solve(b,a%b,y,x);
        y-=a/b*x;
    }
}

int main()
{
    int64_t C, E, N, P, Q, T, D, K, M;
    srand((unsigned int)time(NULL));
    while (cin>>C>>E>>N)
    {
        //Get P and Q ==> T
        P=PollardRho(N);
//        P=get_small(N);
        Q=N/P;
        T=(P-1)*(Q-1);
        //Find D. Here D is a multiplicative inverse of E, modulo T. 
        //ED mod T = 1   ==> ED+KT=1  而gcd(E,T)==1,即求解E*D+T*K = (E, T)
        gcd_solve(E, T, D, K);
        D=(D%T+T)%T;
        //M = (C ^ D) mod N
        cout<<pow_mod(C, D, N)<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值