对Diffie-Hellman密钥交换算法实现的一点改进

Diffie-Hellman算法描述: 目前被许多商业产品交易采用。

HD算法为公开的密钥算法,发明于1976年。该算法不能用于加密或解密,而是用于密钥的传输和分配。

    DH 算法的安全性体现在:在有限域上计算离散对数非常困难。

    离散对数:定义素数p的原始根(primitive root)为这样一个数,它能生成1~p-1所有数的一个数。现设ap的原始根,则

a mod p, a2 mod p,…,ap-1 mod p

  两两互不相同,构成一个1~p-1的全体数的一个排列。对于任意数b及素数p的原始根a,可以找到一个唯一的指数i,满足b=ai mod p, 0<=i<=p-1

则称指数i为以a为底、模Pb离散对数


算法描述:
假如Alice 和 Bob在不安全的网络上进行协商共同的密码:
1.Alice和Bob先说好一个大素数p和它的原始根a
2.Alice随机产生一个数x,
计算X=ax mod p,然后把X发给Bob
3.  Bob秘密产生一个随机数y,计算Y=ay mod p,然后把Y发给Alice
4.Alice计算k=Yx mod p;
5.Bob计算k*=Xy mod p;

因为

k=Yx mod p= (ay) x mod p=(a x)ymod p=X y mod p= k*

所以 k= k*

不安全线路上的窃听者只能得到apXY,除非能计算离散对数xy,否则将无法得到密钥k。因此,kAliceBob独立计算出的密钥。

 

 

今天主要分析一下D-H算法的实现问题,随机数有很多办法实现,不讨论了。仔细看看D-H算法可以发现除开随机数的生成,实际上就是4次(n^x)mod p的过程。n是随机的大数(或者X,Y),x就各自的原始随机源,而p是大素数。为何要是大素数跟他的原始根呢,数学上有安全性的证明。

要实现D-H算法主要就是

1:p大素数的生成,以及其原始根的查找。这个问题,可以通过查找大素数表,网络上也有很多经典生成办法。

2:(n^x)mod p的运算。n是大数,x也是大数,这样一个运算,空间上64位的数据是远远溢出的,时间上也是一个考验。

拿1024位的x来说,我们虽然可以使用大数库(gmp,openssl,crypt++都可以),但是n^x这样一个结果有多大呢?直接计算是很不划算的做法。

其实我们可以根据以下原理做出改进。

(n^2)mod p=((n mod p)*n) mod p。

这个式子在这里不证明了。

这样做出改进后,我们最大的中间结果最多n^2位而已,空间复杂度从n^x降到n*n,1024位的数据,也不过2000位就能存储。

此外改成这种形式,也便于代码循环处理。


补充,当年其实最大的改进是在于对x运算的使用,并不是简单的x-1次乘法运算来实现,而且用2进制表达的思路来算,简单来说比如x为10(方便举例,实际是个很大值),不是对n做9次乘法,而是算出2进制1001里8次乘法和1次乘法的结果,再做一次乘法。当x很大时,时间复杂度不是O(x),而是O(log x).

已经常年不更了,不做详细描述的,懂的同学,一提即会。


x优化的简要实现如下:

inline void old_dh(int n,int x,int p)
{
    struct timeval start_tv,loop1_tv;
    gettimeofday(&start_tv, NULL);
    long long tmp = n;
    for(int i=0;i<x-1;++i)
    {
        tmp = n*tmp;
        tmp = tmp%p;
    }
    tmp = tmp%p;
    gettimeofday(&loop1_tv, NULL);
    int iMs = (loop1_tv.tv_sec - start_tv.tv_sec)*1000 + (loop1_tv.tv_usec - start_tv.tv_usec)/1000;
    printf("old_dh,n:%lld,x:%lld,p:%lld,res:%lld,cost time %d ms\n",n,x,p,tmp, iMs);
}

inline void new_dh(int n,int x,int p)
{
    printf("Begin new_dh\n");
    struct timeval start_tv,loop1_tv;
    gettimeofday(&start_tv, NULL);
    long long sn = n%p;
    long long bit_tmp = sn;

    long long res_mod_bitmap[64];             //res_mod_bitmap[1] is the result of(n^2)%p,so res_mod_bitmap[4] is the result of(n^16)%p
    res_mod_bitmap[0] = sn;
    for(int i=1;i<64;++i)
    {
        bit_tmp = (bit_tmp*bit_tmp);
        bit_tmp = bit_tmp%p;
        res_mod_bitmap[i] = bit_tmp;
    }
    printf("finish res_mod_bitmap\n");

    //dep x into bit pres(like x is 10,then is binary 1010)
    long long res = -1;
    for(int i=0;i<64;++i)
    {
        long long vernier = 1<<i;
        if(vernier>x)
            break;
        if(x&vernier)
        {
            if(res==-1)
                res = res_mod_bitmap[i];
            else
                res = (res*res_mod_bitmap[i])%p;
        }

    }

    gettimeofday(&loop1_tv, NULL);
    int iMs = (loop1_tv.tv_sec - start_tv.tv_sec)*1000 + (loop1_tv.tv_usec - start_tv.tv_usec)/1000;
    printf("new_dh,n:%lld,x:%lld,p:%lld,res:%lld,cost time %d ms\n",n,x,p,res, iMs);
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值