破解 D-H 协议
时间限制: 1 Sec 内存限制: 128 MB
提交: 133 解决: 53
[提交] [状态] [讨论版] [命题人:admin]
题目描述
Diffie-Hellman密钥交换协议是一种简单有效的密钥交换方法。它可以让通讯双方在没有事先约定密钥(密码)的情况下,通过不安全的信道(可能被窃听)建立一个安全的密钥K,用于加密之后的通讯内容。
假定通讯双方名为Alice和Bob,协议的工作过程描述如下(其中mod表示取模运算):
协议规定一个固定的质数P,以及模P的一个原根g。P和g的数值都是公开的,无需保密。
Alice生成一个随机数a,并计算A=ga mod P,将A通过不安全信道发送给Bob。
Bob生成一个随机数b,并计算B=gb mod P,将B通过不安全信道发送给Alice。
Bob根据收到的A计算出K=Ab mod P ,而Alice根据收到的B计算出K=Ba mod P。
双方得到了相同的K,即gab mod P。K可以用于之后通讯的加密密钥。
可见,这个过程中可能被窃听的只有A,B,而a,b,K是保密的。并且根据A,B,P,g这4个数,不能轻易计算出K,因此K可以作为一个安全的密钥。
当然安全是相对的,该协议的安全性取决于数值的大小,通常a,b,P都选取数百位以上的大整数以避免被破解。然而如果Alice和Bob编程时偷懒,为了避免实现大数运算,选择的数值都小于231,那么破解他们的密钥就比较容易了。
输入
第一行包含两个空格分开的正整数g和P。
第二行为一个正整数n,表示Alice和Bob共进行了n次连接(即运行了n次协议)。
接下来n行,每行包含两个空格分开的正整数A和B,表示某次连接中,被窃听的A,B数值。
输出
输出包含n行,每行一个正整数K,为每次连接你破解得到的密钥。
样例输入
3 31
3
27 16
21 3
9 26
样例输出
4
21
25
提示
对于30%的数据,2≤A,B,P≤1000。
对于100%的数据,2≤A,B<P<231,2≤g<20,1≤n≤20。
题意 :
给你A B g p ,让你去求K k=A^b%p 或者k=B^a%p ,bsgs算法解同余方程 a^x % p = b % p
A=g^a%p 等价于 A%p=g^a%p 等价于A≡g^a(mod p) (事实) 就可以套用BSGS算法了
(恒成立 一般是表示含有未知量的)
因为( aX=kb+c 等于 aX≡c(mod b) )。
题解
【bsgs算法】
对于同余方程 a,b,p都一直,且p为素数,求解x
令 m = sqrt(p) + 1 ( 稍大于sqrt(p)的一个整数)
令 x = i*m - j ,ij均为整数,那么i*m-j一定可以凑出任意一个整数x,并且i只需从1到m,如果有误差,可以通过 j 来调整。
这样一来,同余方程变为
那么恒等式右边,可以枚举 j 预处理放到map里,然后左边枚举 i ,直到在map存在相等的右边值,则结束
解得:x = i*m - j
时间复杂度,当p很大时(1e9),还是要考虑优化,一不小心就超时
所以本题目已知 利用bsgs求解b,所以答案
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll qpow(ll n,ll m,ll p)
{
n%=p;
ll ans=1;
for(;m;m>>=1)
{
if(m&1)ans=ans*n%p;
n=n*n%p;
}
return ans;
}
int main()
{
ll g,p,A,B,n;
scanf("%lld%lld%lld",&g,&p,&n);
ll m=sqrt(p)+1; //x=i*m-j,注意m必须大于sqrt(p)
map<ll,ll>M; //预处理g^j
ll res=1; //a^0
for(int j=0;j<=m;j++)
{
M[res%p]=j;
res=res*g%p;
}
ll dk=qpow(g,m,p);
while(n--)
{
scanf("%lld%lld",&A,&B);
int a,b;
ll k=dk*qpow(B,p-2,p)%p;
for(int i=1;i<=m;i++)
{
if(M.count(k))
{
b=i*m-M[k];
break;
}
k=k*dk%p;
}
ll ans=qpow(A,b,p);
printf("%lld\n",ans);
}
}