DH的作业

Diffie-Hellman密钥协商算法

一、DH介绍

DH密钥协商协议即Diffie-Hellman密钥协商算法,DH密钥协商算法在1976年在Whitfield Diffie和Martin Hellman两人合著的论文New Directions in Cryptography(Section Ⅲ PUBLIC KEY CRYPTOGRAPHY)中被作为一种公开秘钥分发系统(public key distribution system)被提出来。并不是用来加密的,而是解决密钥配送的问题,双方就某次通信达成密钥的统一

1.1 DH密钥协商协议的流程

以Alice和Bob为通信双方角色,述阐DH算法的流程。

1)首先Alice与Bob共享一个素数p以及该素数p的本原根g(geneator),当然这里有2⩽g⩽p−1。这两个数是可以不经过加密地由一方发送到另一方,至于谁发送的并不重要,其结果只要保证双方都得知p和g即可。


img


2)然后Alice产生一个私有的随机数A,满足1⩽A⩽p−1,然后计算![g^A](https://private.codecogs.com/gif.latex?\fn_cm g^A) mod p = ![Y_a](https://private.codecogs.com/gif.latex?\fn_cm Y_a) ,将结果Ya通过公网发送给Bob;与此同时,Bob也产生一个私有的随机数B,满足1⩽B⩽p−1,计算![g^B](https://private.codecogs.com/gif.latex?\fn_cm g^B) mod p = Y_b,将结果Yb通过公网发送给Alice。


img


3)此时Alice知道的信息有p,g,A,Y_a,其中数字A是Alice私有的,只有她自己知道,别人不可能知道,其他三个信息都是别人有可能知道的;Bob知道的信息有p,g,B,![Y_b](https://private.codecogs.com/gif.latex?\fn_cm Y_b),其中数字B是Bob私有的,只有他自己知道,别人不可能知道,其他都是别人有可能知道的。

到目前为止,Alice和Bob之间的秘钥协商结束。

Alice通过计算![K_a](https://private.codecogs.com/gif.latex?\fn_cm K_a) =![(Y_b)^A](https://private.codecogs.com/gif.latex?\fn_cm (Y_b)^A) mod p得到秘钥K_a,同理,Bob通过计算![K_b](https://private.codecogs.com/gif.latex?\fn_cm K_b) = ![(Y_a)^B](https://private.codecogs.com/gif.latex?\fn_cm (Y_a)^B) mod p得到秘钥K_b,此时可以证明,必然满足

K_a = K_b。因此双方经过协商后得到了相同的秘钥,达成秘钥协商的目的。

Alice和Bob生成秘钥时其实是进行相同的运算过程,因此必然有![K_a](https://private.codecogs.com/gif.latex?\fn_cm K_a) = ![K_b](https://private.codecogs.com/gif.latex?\fn_cm K_b)。"相同的运算过程"是双方能够进行秘钥协商的本质原因,类似的利用椭圆曲线进行秘钥协商也是与之相同的原理。

更严密地考虑,A和B不应该选择p−1,也就是说只能在集合 {1,2,3,…,p−2} 中选择。这是因为如果选择p−1,那么由费马小定理可知,情况就退化成了 g^{p-1}=1modp的情况,对秘钥协商的机密性构成威胁。

那么窃听者Eve能否破解秘钥呢?首先要知道Eve能够得知哪些信息,显然Eve能够窃听到的信息只能有p,g,Y_a,![Y_b](https://private.codecogs.com/gif.latex?\fn_cm Y_b),现在的问题是Eve能够通过以上信息计算出![K_a](https://private.codecogs.com/gif.latex?\fn_cm K_a)或者![K_b](https://private.codecogs.com/gif.latex?\fn_cm K_b)吗?要计算K_a或者K_b需要知道A或者B。

以计算A为例,Eve能根据条件![g^A](https://private.codecogs.com/gif.latex?\fn_cm g^A) mod p = Y_a计算出A吗?实际上当p是大质数的时候,这是相当困难的,这就是离散对数问题。实际上在论文发表的当时,计算该问题的最有效的算法的时间复杂度大约是O(\sqrt{p})。也正是求解该问题在计算上的困难程度保证了DH算法的安全性。如果能够找到对数时间复杂度的算法,那么该算法即容易被攻破。

1.2 举个例子

1)假设Alice和Bob共享的p和g分别是p = 17,g = 3,显然这里g = 3是p = 17的一个本原根,实际上3,5,6,7,10,11,12,14都是17的本原根。

2)然后Alice选定一个私有数字,假设A=15,计算![Y_a](https://private.codecogs.com/gif.latex?\fn_cm Y_a) = ![3^{15}](https://private.codecogs.com/gif.latex?\fn_cm 3^{15}) mod 17 = 14348907 mod 17 = 6,将6发送给Bob;同时Bob也选定一个私有的数字,假设B=13 ,计算Y_b = ![3^{13}](https://private.codecogs.com/gif.latex?\fn_cm 3^{13}) mod 17 = 1594323 mod 17 = 12,将12发送给Alice。

3)Alice计算秘钥![K_a](https://private.codecogs.com/gif.latex?\fn_cm K_a) = ![12^{15}](https://private.codecogs.com/gif.latex?\fn_cm 12^{15}) mod 17 = 2147483647 mod 17 = 8,Bob计算秘钥K_b = ![6^{13}](https://private.codecogs.com/gif.latex?\fn_cm 6^{13}) mod 17 = 2147483647 mod 17 = 8 。双方经过协商后,8最终成为双方的协商的秘钥。

1.3 存在的问题

是否DH秘钥协商算法就一定安全呢?应该说也不是,因为存在一种称为中间人攻击,能够对这种秘钥协商算法构成威胁。假设秘钥协商过程中,在Alice和Bob中间有一个称为Mallory的主动攻击者,他能够截获Alice和Bob的消息并伪造假消息,考虑如下情况。

1)Alice和Bob已经共享一个素数p及其该素数p的本原根g,当然Mallory监听到报文也得知了这两个消息。

2)此时Alice计算Y_a = ![g^A](https://private.codecogs.com/gif.latex?\fn_cm g^A) mod p,然而在将Y_a发送给Bob的过程中被Mallory拦截,Mallory自己选定一个随机数S,计算

![Y_{sb}](https://private.codecogs.com/gif.latex?\fn_cm Y_{sb}) = ![g^S](https://private.codecogs.com/gif.latex?\fn_cm g^S) mod p ,然后将Y_{sb}发送给了Bob。


img


3)同时Bob计算![Y_b](https://private.codecogs.com/gif.latex?\fn_cm Y_b) = g^B mod p,然而在将Yb发送给Alice的过程中被Mallory拦截,Mallory自己选定一个随机数T,计算

![Y_{ta}](https://private.codecogs.com/gif.latex?\fn_cm Y_{ta}) = ![g^T](https://private.codecogs.com/gif.latex?\fn_cm g^T) mod p,然后将Y_{ta}发送给了Alice


img


由于通讯消息被替换,Alice计算出的秘钥实际上是Alice和Mallory之间协商秘钥:![K_{am}](https://private.codecogs.com/gif.latex?\fn_cm K_{am}) = g^{A×T} mod p;Bob计算出的秘钥实际上是Bob与Mallory之间协商的秘钥:K_{bm} = ![g^{BS}](https://private.codecogs.com/gif.latex?\fn_cm g^{BS}) mod p。如果之后Alice和Bob用他们计算出的秘钥加密任何信息,Mallory截获之后都能够解密得到明文,而且Mallory完全可以伪装成Alice或者Bob给对方发消息。

二、作业

2.1 作业要求

## 作业
编程实现 DH 密钥协商协议
共同参数。素数P,P的一个生成元g
1. A 随机选择一个 [1,p-1] 范围内的数`x`,计算 `X` = g^xmod p ,并将结果发送给B。
2. B 随机选择一个 [1,p-1] 范围内的数`y`,计算 `Y` = g^y mod p, 并将结果发送给A。
k` = Y^x = X^y
### 提示
编写 bool isPrime(int n) ; 判断 n是素数
编写 int GCD(int a, int b); 计算 a,b最大公因子
编写 int ExpMod(int b, int n, int m) 计算 b^n mod m .
编写 bool isPrimeRoot(g, p); 判断 g是模p乘的生成元。
寻找p的生成元 ,从 g 从2,3等较小的数开始进行穷举。 计算 g^n mod p , 1<=n < p-1 的到的数据不同,g即为生成元。
可以在网上搜集相应的算法即源代码,但不能使用语言提供的函数直接的出结果。
### 上交内容要求
1. 选用自己熟悉的语言实现上述要求。上交内容包括程序源代码和一份简单的实验报告(电子版本md格式)
2. 用git管理

2.2 程序展示

  • 测试一:共享的质数为:313,A选择的生成元为:296,B选择的生成元为:305,A选择的随机数:5,B选择的随机数:10
  • 结果:密钥都是:4182119424


  • 测试一:共享的质数为:113,A选择的生成元为:97,B选择的生成元为:106,A选择的随机数:23,B选择的随机数:19

  • 结果:密钥都是:-5062875838873911181


image-20221018114446991


2.3 代码展示

package sixth;

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        // 113 106 97
        //313 305 296
        System.out.println("请输入一个共享的质数p:");
        Scanner scp = new Scanner(System.in);
        int p = scp.nextInt();
        if (isPrime(p)){
            System.out.println("共享的质数为:" + p);
        }else {
            System.out.println(p + "不是质数");
        }

        System.out.println("请输入A选择的生成元:");
        Scanner scAg = new Scanner(System.in);
        int Ag = scAg.nextInt();
        if (isPrimeRoot(Ag,p)){
            System.out.println("A选择的生成元为:" + Ag);
        }else{
            System.out.println(Ag+"不能作为A选择的生成元");
        }

        System.out.println("请输入B选择的生成元:");
        Scanner scBg = new Scanner(System.in);
        int Bg = scBg.nextInt();
        if (isPrimeRoot(Bg,p)){
            System.out.println("B选择的生成元为:" + Bg);
        }else{
            System.out.println(Bg+"不能作为B选择的生成元");
        }

        System.out.println("请输入A选择的随机数:");
        Scanner sca = new Scanner(System.in);
        int a = sca.nextInt();
        if (1 <= a && a <= p-1){
            System.out.println("A选择的随机数:" + a);
        }else{
            System.out.println(a+"不能作为A选择的随机数");
        }

        System.out.println("请输入B选择的随机数:");
        Scanner scb = new Scanner(System.in);
        int b = scb.nextInt();
        if (1 <= b && b <= p-1){
            System.out.println("B选择的随机数:" + b);
        }else{
            System.out.println(b+"不能作为B选择的随机数");
        }

        //计算ExpMod,g ^ n mod p
        int YA = ExpMod(Ag,a,p);
        int YB = ExpMod(Bg,b,p);
        System.out.println("由公式g ^ n mod p得,A的计算结果为:"+YA+",B的计算结果为:"+YB);
        System.out.println("由公式k` = Y^x = X^y得,A的计算的密钥为:"+key(a,YA)+",B的计算的密钥为:"+key(a,YA));
    }
    //k` = Y^x = X^y
    public static long key(int n,int Y){
        long  k = 1;
        while(n > 0){
            k = k * Y;
            n = n - 1;
        }
        return k;
    }
    //编写 int ExpMod(int g, int n, int p) 计算 g^n mod p
    public static int ExpMod(int g, int n, int p){
        int sum = 1;
        while (n > 0){
            sum = sum * g;
            n = n -1;
        }
        System.out.println(sum);
        return sum % p;
    }

    //判断是否为质数
    public static boolean isPrime(int p) {
        //n<=3时,质数有2和3
        if (p <= 3) {
            return p > 1;
        }
        //当n>3时,质数无法被比它小的数整除
        for (int i = 2; i < p; i++) {
            if (p % i == 0) {
                return false;
            }
        }
        return true;
    }

    //如果x加上x的各个位数字之和得到y,就说x是y的生成元
    public static boolean isPrimeRoot(int g,int p){
        int sum = g;
        if (g < 1 || g > p-1){
            return false;
        }
        int[] s = new int[10];//不超过10个数
        for (int i = 0; i < 10; i++) {
            int k = g % 10;
            s[i] = k;
            g = g / 10;
            if (g <= 0){
                break;
            }
        }
        for (int i = 0; i < 10; i++) {
            sum = sum + s[i];
        }
        if (p == sum){
            return true;
        }else {
            return false;
        }
    }

}

   break;
        }
    }
    for (int i = 0; i < 10; i++) {
        sum = sum + s[i];
    }
    if (p == sum){
        return true;
    }else {
        return false;
    }
}

}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值