BZOJ-4522 [Cqoi2016]密钥破解(Pollard-Rho算法+exgcd)
题目描述
一种非对称加密算法的密钥生成过程如下:
\(1.\) 任选两个不同的质数 \(p,q\)。
\(2.\) 计算 \(N=pq,r=(p-1)(q-1)\)。
\(3.\) 选取小于 \(r\) ,且与 \(r\) 互质的整数 \(e\)。
\(4.\) 计算整数 \(d\),使得 \(ed\equiv 1 \pmod {r}\)。
\(5.\) 二元组 \((N,e)\) 称为公钥,二元组 \((N,d)\) 称为私钥。
当需要加密消息 \(n\) 时(假设 \(n\) 是一个小于 N 的整数,因为任何格式的消息都可转为整数表示),使用公钥 \((N,e)\),按照 \(n^e\equiv c \pmod {N}\) 运算,可得到密文 \(c\)。
对密文 \(c\) 解密时,用私钥 \((N,d)\),按照 \(c^d\equiv n \pmod {N}\) 运算,可得到原文 \(n\)。算法正确性证明省略。
由于用公钥加密的密文仅能用对应的私钥解密,而不能用公钥解密,因此称为非对称加密算法。通常情况下,公钥由消息的接收方公开,而私钥由消息的接收方自己持有。这样任何发送消息的人都可以用公钥对消息加密,而只有消息的接收方自己能够解密消息。
现在,你的任务是寻找一种可行的方法来破解这种加密算法,即根据公钥破解出私钥,并据此解密密文。
输入:\(e,N,c(N\leq 2^{62},c<N)\),输出:\(d,n\)。
分析
\(1.\) \(\text{Pollard-Rho}\) 分解 \(N\)。
$2. $ 取 \(N\) 两个质因数 $p,q $,得到 \(r\)。
\(3.\) 利用扩展欧几里得算法求出 \(e\) 的逆元 \(d\)。
\(4.\) \(c,d\) 都已知,快速幂算 \(n\)。
代码
#include<bits/stdc++.h>
using namespace std;
#define int128 __int128
long long e,N,c,r,d,n;
long long quick_pow(long long a,long long b,long long mod)
{
long long ans=1;
while(b)
{
if(b&1)
ans=(int128)ans*a%mod;
a=(int128)a*a%mod;
b>>=1;
}
return ans;
}
long long max_factor;
bool Miller_Rabin(long long p)
{
if(p<2)
return 0;
if(p==2)
return 1;
if(p==3)
return 1;
long long d=p-1,r=0;
while(d%2==0)
{
r++;
d>>=1;
}
for(long long k=0;k<10;k++)
{
long long a=rand()%(p-2)+2;
long long x=quick_pow(a,d,p);
if(x==1||x==p-1)
continue;
for(int i=0;i<r-1;i++)
{
x=(int128)x*x%p;
if(x==p-1)
break;
}
if(x!=p-1)
return 0;
}
return 1;
}
long long f(long long x,long long c,long long n)
{
return ((int128)x*x+c)%n;
}
long long Pollard_Rho(long long n)
{
long long s=0,t=0;
long long c=rand()%(n-1)+1;
int step=0,goal=1;
long long val=1;
for(goal=1; ;goal<<=1,s=t,val=1)
{
for(step=1;step<=goal;step++)
{
t=f(t,c,n);
val=(int128)val*abs(t-s)%n;
if(step%127==0)
{
long long d=__gcd(val,n);
if(d>1)
return d;
}
}
long long d=__gcd(val,n);
if(d>1)
return d;
}
}
vector<long long> factor;
void fac(long long x)
{
if(x<=max_factor||x<2)
return ;
if(Miller_Rabin(x))
{
factor.push_back(x);
//max_factor=max(max_factor,x);
return ;
}
long long p=x;
while(p>=x)
p=Pollard_Rho(x);
while(x%p==0)
x=x/p;
fac(x);fac(p);
}
void exgcd(long long a,long long b,long long &x,long long &y)
{
if(!b)
{
x=1;
y=0;
return ;
}
exgcd(b,a%b,y,x);
y=y-(int128)(a/b)*x%r;
y=(y%r+r)%r;
}
long long inv(long long a,long long b)//ax=1(mod b)
{
long long x,y;
exgcd(a,b,x,y);
x=(x%b+b)%b;
return x;
}
int main()
{
srand((unsigned)time(NULL));
cin>>e>>N>>c;
fac(N);
r=(factor[0]-1)*(factor[1]-1);
d=inv(e,r);
n=quick_pow(c,d,N);
cout<<d<<" "<<n<<endl;
return 0;
}
posted on 2020-12-05 16:51 DestinHistoire 阅读(134) 评论(0) 收藏 举报