zoukankan      html  css  js  c++  java
  • 破解 D-H 协议

    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[511000],q[511000];
    
    int tot,tlen,g;
    int mod;
    
    int pow_mod(int a,LL b)
    {
        register int ret=1;
        while(b)
        {
            if(b&1)ret=(LL)ret*a%mod;
            a=(LL)a*a%mod;
            b>>=1;
        }
        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=1,r=tlen;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(q[mid].y<p) l=mid+1;
            else if(q[mid].y>p) r=mid-1;
            else return q[mid].p;
        }
        return -1;
    }
    
    int BSGS(int y,int A)
    {
        if(y==0 && A==0)return 1;
        register int tmp=pow_mod(y,mod-2),cnt=1;
        int m=ceil(sqrt(mod));
        tot=0;
        w[++tot].y=A;
        w[tot].p=m+1;
        for(register int i=1; i<m; i++)
        {
            cnt=(LL)cnt*tmp%mod;
            LL t=(LL)cnt*A%mod;
            w[++tot].y=t;
            w[tot].p=i;
        }
        sort(w+1,w+1+tot,cmp);
        tlen=1;
        q[1]=w[1];
        for(int i=2; i<=tot; i++)
        {
            if(w[i].y!=w[i-1].y) q[++tlen]=w[i];
        }
        tmp=pow_mod(y,m),cnt=1;
        for(register int i=0; i<m; i++)
        {
            int pp=fd(cnt);
            if(pp!=-1)
            {
                if(pp==m+1) return i*m;
                return pp+i*m;
            }
            cnt=(LL)cnt*tmp%mod;
        }
        return 0;
    }
    
    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
    ",pow_mod(g,(LL)sx*sy));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    MS面试归来:)
    准备出发到成都
    线程的同步机制(zz)
    Windows Vista(zz)
    这几天上海热晕了
    微软官方:Vista硬件要求指南(zz)
    有趣的递归缩写(Recursive acronym)
    《三国志》生僻人名读法集(zz)
    Git bash常用命令
    各大输入法分类词库内部格式的简单比较
  • 原文地址:https://www.cnblogs.com/lglh/p/9439526.html
Copyright © 2011-2022 走看看