zoukankan      html  css  js  c++  java
  • 【BZOJ5296】【CQOI2018】破解D-H协议(BSGS)

    【BZOJ5296】【CQOI2018】破解D-H协议(BSGS)

    题面

    BZOJ
    洛谷

    Description

    Diffie-Hellman密钥交换协议是一种简单有效的密钥交换方法。它可以让通讯双方在没有事先约定密钥(密码)的情况下
    通过不安全的信道(可能被窃听)建立一个安全的密钥K,用于加密之后的通讯内容。
    假定通讯双方名为Alice和Bob,协议的工作过程描述如下(其中mod表示取模运算):
    1.协议规定一个固定的质数P,以及模P的一个原根g。P和g的数值都是公开的,无需保密。
    2.Alice生成一个随机数a,并计算A=g^a mod P,将A通过不安全信道发送给Bob。
    3.Bob生成一个随机数b,并计算B=g^b mod P,将B通过不安全信道发送给Alice。
    4.Bob根据收到的A计算出K=A^b mod P,而Alice根据收到的B计算出K=B^a mod P。
    5.双方得到了相同的K,即g^(a*b) mod P。K可以用于之后通讯的加密密钥。
    可见,这个过程中可能被窃听的只有A、B,而a、b、K是保密的。并且根据A、B、P、g这4个数,不能轻易计算出
    K,因此K可以作为一个安全的密钥。
    当然安全是相对的,该协议的安全性取决于数值的大小,通常a、b、P都选取数百位以上的大整数以避免被破解。然而如
    果Alice和Bob编程时偷懒,为了避免实现大数运算,选择的数值都小于2^31,那么破解他们的密钥就比较容易了。

    Input

    输入文件第一行包含两个空格分开的正整数g和P。
    第二行为一个正整数n,表示Alice和Bob共进行了n次连接(即运行了n次协议)。
    接下来n行,每行包含两个空格分开的正整数A和B,表示某次连接中,被窃听的A、B数值。
    2≤A,B<P<231,2≤g<20, n<=20

    Output

    输出包含n行,每行1个正整数K,为每次连接你破解得到的密钥。

    Sample Input

    3 31

    3

    27 16

    21 3

    9 26

    Sample Output

    4

    21

    25

    题解

    (BSGS)模板题啊。。。
    显然只要求出(a,b)就行了。。
    然后就是给定了(g,P)
    (g^a=A(mod P))就行了。。
    最后乘起来。。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    const int HashMod=111111;
    struct HashTable
    {
    	struct Line{int v,next,u;}e[1000000];
    	int h[HashMod],cnt;
    	void Add(int u,int v,int w){e[++cnt]=(Line){v,h[u],w};h[u]=cnt;}
    	void insert(int x,int y){Add(x%HashMod,y,x);}
    	int Query(int x)
    	{
    		for(int i=h[x%HashMod];i;i=e[i].next)
    			if(e[i].u==x)return e[i].v;
    		return -1;
    	}
    	void clear(){memset(h,0,sizeof(h));cnt=0;}
    }Hash;
    int G,MOD,n,m,Q;
    int fpow(int a,int b)
    {
    	int s=1;
    	while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}
    	return s;
    }
    int BSGS(int y,int z,int p)
    {
    	Hash.clear();
    	for(int i=0,t=z;i<m;++i,t=1ll*t*y%p)Hash.insert(t,i);
    	for(int i=1,tt=fpow(y,m),t=tt;i<=m;++i,t=1ll*t*tt%p)
    	{
    		int h=Hash.Query(t);if(h==-1)continue;
    		return i*m-h;
    	}
    	return -1;
    }
    int main()
    {
    	G=read();MOD=read();m=sqrt(MOD)+1;Q=read();
    	while(Q--)
    	{
    		int A=read(),B=read();
    		printf("%d
    ",fpow(G,1ll*BSGS(G,A,MOD)*BSGS(G,B,MOD)%(MOD-1)));
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    94. Binary Tree Inorder Traversal
    101. Symmetric Tree
    38. Count and Say
    28. Implement strStr()
    实训团队心得(1)
    探索性测试入门
    LC.278. First Bad Version
    Search in Unknown Sized Sorted Array
    LC.88. Merge Sorted Array
    LC.283.Move Zeroes
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8897985.html
Copyright © 2011-2022 走看看