P5451 [THUPC2018]密码学第三次小作业

P5451 [THUPC2018]密码学第三次小作业

题目大意

现在有两个用户由于巧合,拥有了相同的模数 \(N\),但是私钥不同。设两个用户的公钥分别为 \(e_1\)\(e_2\)且两者互质。明文消息为 \(m\),密文分别为:

\[\begin{matrix}c_1=m^{e_1}\bmod N\\c_2=m^{e_2}\bmod N\end{matrix} \]

现在,一个攻击者截获了 \(c_1\)\(c_2\)\(e_1\)\(e_2\)\(N\),请帮助他恢复出明文 \(m\)

分析

太妙啦,我们来顺一遍思路啊。

首先我们要求m,但给的式子都不是m的一次幂。那我们先放一下给的式子。我们可以发现给的m的次幂是e1和e2,则我们考虑一下能不能用e1,e2凑出1

我们注意到e1,e2互质,那我们想到用裴蜀定理。得到,\(e_1x+e_2y=1\)的式子。

我们带入一下,\(m=m^{e_1x+e_2y}=m^{e_1x}*m^{e_2y}\),再结合给的式子,我们可以得到,\(m=c_1^x*c_2^y(mod\ N)\)

x,y我们可以很简单的用exgcd求得。还有一个小问题,如果x,y不是正数怎么办,那就转化一下,假设x为负数则,式子可以转化为\((c_1^{-1})^{-x}\)

而,c1的逆元,需要注意,不能直接用费马小定理求,用exgcd求,结束啦。

Ac_code

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false); cin.tie(0), cout.tie(0)
using namespace std;
typedef long long LL;
typedef __int128_t i128;
LL exgcd(LL a, LL b, LL& x, LL& y)
{
    if (!b)
    {
        x = 1, y = 0;
        return a;
    }
    LL d = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}

LL get_inv(LL a,LL p)
{
    LL x,y;
    LL d = exgcd(a,p,x,y);
    return (x%p+p)%p;
}

LL ksm(LL a,LL b,LL mod)
{
    LL res = 1;
    while(b)
    {
        if(b&1) res = (i128)res*a%mod;
        b>>=1;
        a = (i128)a*a%mod;
    }
    return res;
}

int main()
{
    ios;
    int T;cin>>T;
    while(T--)
    {
        LL c1,c2,e1,e2,N;
        LL s,t;
        cin>>c1>>c2>>e1>>e2>>N;
        exgcd(e1,e2,s,t);
        LL k,ans = 0;
        if(s<0) k = ceil((1.0-s)/e2),s += e2*k,t -= e1*k;
        ans = ksm(c1,s,N);
        if(t<0) ans = (i128)ans*ksm(get_inv(c2,N),-t,N)%N;
        else ans = (i128)ans*ksm(c2,t,N)%N;
        cout<<ans<<'\n';
    }
    return 0;
}
posted @ 2022-09-06 18:58  艾特玖  阅读(27)  评论(0)    收藏  举报