upc - 6756: 破解 D-H 协议 (bsgs算法)

题目描述

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。

 

很裸的 baby_step_giant_step(bsgs)算法板子

AC代码(其实不用这么麻烦,但是为了记住这个板子用了exbsgs)

/* Lyl */
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define linf 0x3f3f3f3f3f3f3f3fLL
#define pi acos(-1.0)
#define ms(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;

ll qpow(ll x, ll y, ll mod){ll s=1;while(y){if(y&1)s=s*x%mod;x=x*x%mod;y>>=1;}return s;}

int baby_step_giant_step(int a, int b, int p)
{
	a %= p, b %= p;
	if(b == 1) return 0;
	int cnt = 0;
	ll t = 1;
	for(int g = __gcd(a, p); g != 1; g = __gcd(a, p))
	{
		if(b % g) return -1;
		p /= g, b /= g, t = t * a / g % p;
		++cnt;
		if(b == t) return cnt;
	}

	map<int, int> hash;
	int m = int(sqrt(1.0 * p) + 1);
	ll base = b;
	for(int i = 0; i != m; ++i)
	{
		hash[base] = i;
		base = base * a % p;
	}

	base = qpow(a, m, p);
	ll now = t;
	for(int i = 1; i <= m + 1; ++i)
	{
		now = now * base % p;
		if(hash.count(now))
			return i * m - hash[now] + cnt;
	}

	return -1;
}

int main()
{
    ll g, a, b, p, n;
    scanf("%lld%lld%lld", &g, &p, &n);
    while(n--)
    {
        scanf("%lld%lld", &a, &b);
        ll ans=baby_step_giant_step(g, a, p);
        if(ans==-1) continue;
        printf("%lld\n", qpow(b, ans, p));
    }

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值