题意
1977年,罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)提出了RSA 加密算法。RSA 加密算法是一种非对称加密算法,其可靠性由极大整数因数分解的难度决定。换言之,对一极大整数做因数分解愈困难,RSA 算法愈可靠。假如有人找到一种快速因数分解的算法的话,那么用 RSA 加密的信息的可靠性就肯定会极度下降。
RSA 的基本原理如下:
公钥与私钥的产生
随机选择两个不同大质数
p
p
和 ,计算
N=p×q
N
=
p
×
q
根据欧拉函数性质,求得
r=φ(N)=φ(p)φ(q)=(p−1)(q−1)
r
=
φ
(
N
)
=
φ
(
p
)
φ
(
q
)
=
(
p
−
1
)
(
q
−
1
)
选择一个小于
r
r
的正整数 ,使
e⊥r
e
⊥
r
。并求得
e
e
关于 的乘法逆元
d
d
,有
将
p
p
和 的记录销毁。此时,
(N,e)
(
N
,
e
)
是公钥,
(N,d)
(
N
,
d
)
是私钥。
消息加密:首先需要将消息
m
m
以一个双方约定好的格式转化为一个小于 ,且与
N
N
互质的整数 。如果消息太长,可以将消息分为几段,这也就是我们所说的块加密,后对于每一部分利用如下公式加密:
ne≡c (mod N)
n
e
≡
c
(
m
o
d
N
)
消息解密:利用密钥
d
d
进行解密
现在有两个用户由于巧合,拥有了相同的模数
N
N
,但是私钥不同。设两个用户的公钥分别为 和
e2
e
2
,且两者互质。明文消息为
m
m
,密文分别为:
c2≡me2 (mod N)
c
2
≡
m
e
2
(
m
o
d
N
)
现在,一个攻击者截获了
c1,c2,e1,e2,N
c
1
,
c
2
,
e
1
,
e
2
,
N
请帮助他恢复出明文 m。
题解
然而问题跟RSA并没有太大关系…
一个重要的条件:
e1⊥e2
e
1
⊥
e
2
,则设:
x×e1+y×e2=1
x
×
e
1
+
y
×
e
2
=
1
用exgcd求出x,y后,即
mxe1+ye2=c1xc2y=m1=m
m
x
e
1
+
y
e
2
=
c
1
x
c
2
y
=
m
1
=
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)));
}
}