题意
1977年,罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)提出了RSA 加密算法。RSA 加密算法是一种非对称加密算法,其可靠性由极大整数因数分解的难度决定。换言之,对一极大整数做因数分解愈困难,RSA 算法愈可靠。假如有人找到一种快速因数分解的算法的话,那么用 RSA 加密的信息的可靠性就肯定会极度下降。
RSA 的基本原理如下:
公钥与私钥的产生
随机选择两个不同大质数 pp 和 ,计算 N=p×qN=p×q
根据欧拉函数性质,求得 r=φ(N)=φ(p)φ(q)=(p−1)(q−1)r=φ(N)=φ(p)φ(q)=(p−1)(q−1)
选择一个小于 rr 的正整数 ,使 e⊥re⊥r。并求得 ee 关于 的乘法逆元 dd,有
将 pp 和 的记录销毁。此时,(N,e)(N,e) 是公钥,(N,d)(N,d) 是私钥。
消息加密:首先需要将消息 mm 以一个双方约定好的格式转化为一个小于 ,且与 NN 互质的整数 。如果消息太长,可以将消息分为几段,这也就是我们所说的块加密,后对于每一部分利用如下公式加密:
ne≡c (mod N)ne≡c (mod N)
消息解密:利用密钥 dd 进行解密
现在有两个用户由于巧合,拥有了相同的模数 NN,但是私钥不同。设两个用户的公钥分别为 和 e2e2 ,且两者互质。明文消息为 mm,密文分别为:
c2≡me2 (mod N)c2≡me2 (mod N)
现在,一个攻击者截获了 c1,c2,e1,e2,Nc1,c2,e1,e2,N请帮助他恢复出明文 m。
题解
然而问题跟RSA并没有太大关系…
一个重要的条件:e1⊥e2e1⊥e2,则设:
x×e1+y×e2=1x×e1+y×e2=1
用exgcd求出x,y后,即
mxe1+ye2=c1xc2y=m1=mmxe1+ye2=c1xc2y=m1=m
代码
#include<cstdio>
#include<cctype>
using namespace std;
typedef long long ll;
int T;ll k,c1,c2,e1,e2,mod,X,Y,x,y;
char ch;
inline ll rd()
{
ll x=0;int f=1;
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
return x*f;
}
inline void exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b){x=1;y=0;return;}
exgcd(b,a%b,x,y);k=x;x=y;y=k-a/b*y;
}
inline ll mul(ll a,ll b)
{
ll ret=0;
for(;b;b>>=1,a=(a<<1)%mod) if(b&1) ret=(ret+a)%mod;
return ret;
}
inline ll fp(ll a,ll b)
{
ll ret=1;
for(;b;b>>=1,a=mul(a,a)) if(b&1) ret=mul(ret,a);
return ret;
}
int main(){
scanf("%d",&T);
while(T--){
c1=rd();c2=rd();e1=rd();e2=rd();mod=rd();
exgcd(e1,e2,X,Y);
if(X<0){exgcd(c1,mod,x,y);c1=(x%mod+mod)%mod;X=-X;}
if(Y<0){exgcd(c2,mod,x,y);c2=(x%mod+mod)%mod;Y=-Y;}
printf("%lld\n",mul(fp(c1,X),fp(c2,Y)));
}
}