756: 破解 D-H 协议

时间限制: 1 Sec  内存限制: 128 MB
提交: 78  解决: 18
[提交] [状态] [讨论版] [命题人: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,然后用快速幂!
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL; struct LSnode
{
int y,p;
} w[],q[]; int tot,tlen,g;
int mod; int pow_mod(int a,LL b)
{
register int ret=;
while(b)
{
if(b&)ret=(LL)ret*a%mod;
a=(LL)a*a%mod;
b>>=;
}
return ret;
} bool cmp(LSnode n1,LSnode n2)
{
if(n1.y!=n2.y) return n1.y<n2.y;
return n1.p<n2.p;
} int fd(int p)
{
int l=,r=tlen;
while(l<=r)
{
int mid=(l+r)/;
if(q[mid].y<p) l=mid+;
else if(q[mid].y>p) r=mid-;
else return q[mid].p;
}
return -;
} int BSGS(int y,int A)
{
if(y== && A==)return ;
register int tmp=pow_mod(y,mod-),cnt=;
int m=ceil(sqrt(mod));
tot=;
w[++tot].y=A;
w[tot].p=m+;
for(register int i=; i<m; i++)
{
cnt=(LL)cnt*tmp%mod;
LL t=(LL)cnt*A%mod;
w[++tot].y=t;
w[tot].p=i;
}
sort(w+,w++tot,cmp);
tlen=;
q[]=w[];
for(int i=; i<=tot; i++)
{
if(w[i].y!=w[i-].y) q[++tlen]=w[i];
}
tmp=pow_mod(y,m),cnt=;
for(register int i=; i<m; i++)
{
int pp=fd(cnt);
if(pp!=-)
{
if(pp==m+) return i*m;
return pp+i*m;
}
cnt=(LL)cnt*tmp%mod;
}
return ;
} int main()
{
int T;
scanf("%d %d",&g,&mod);
scanf("%d",&T);
while(T--)
{
int u,v;
scanf("%d %d",&u,&v);
int sx,sy;
sy=BSGS(g,v);
sx=BSGS(g,u);
printf("%d\n",pow_mod(g,(LL)sx*sy));
}
return ;
}

最新文章

  1. Shou.TV 招聘【北京】— — 生效中
  2. [C#6] 7-索引初始化器
  3. 读书笔记_Effective_C++_条款四十七:请使用trait classes来表示类型信息
  4. supplicant
  5. Good Bye 2014 D. New Year Santa Network 图论+期望
  6. awk笔记1
  7. Objective-C中math.h数学计算公式介绍
  8. QT小技巧—更好管理项目(增加预编译头文件,并且指定moc文件的生成位置)good
  9. 关于spring通知中propagation的7种配置《转载》
  10. Linux显示检查设置文件中的语法是否正确
  11. [SQL]LeetCode182. 查找重复的电子邮箱 | Duplicate Emails
  12. Docker,Docker Compose,Docker Swarm,Kubernetes之间的区别
  13. Django中STATIC_URL、STATIC_ROOT、STATICFILES_DIRS 的区别关系
  14. delphi 中OutputDebugString 函数的妙用(转载)
  15. 微信小程序跳转分析
  16. 转:Java properties | FileNotFoundException: properties (系统找不到指定的文件。)
  17. [转载]表单校验之datatype
  18. SpringBoot配置Aop demo
  19. Android O PackageInstaller 解析
  20. CSharp如何自定义鼠标样式

热门文章

  1. 51nod1007(01背包)
  2. Stream流、方法引用
  3. CODEVS 3027 线段覆盖2
  4. Python爬取天气预报
  5. nagios部署配置流程
  6. Unity 坐标
  7. spock和junit测试报告
  8. java程序中路径问题
  9. Primefaces dataTable设置某个cell的样式问题
  10. 你还在为UiPath课程考试发愁吗?