一、什么是D-H算法【参考了相关资料】
迪菲-赫尔曼密钥交换(Diffie–Hellman key exchange,简称“D–H”) 是一种安全协议,不是加密协议。它可以让双方在完全没有对方任何预先信息的条件下通过不安全信道建立起一个密钥。这个密钥可以在后续的通讯中作为对称密钥来加密通讯内容。

迪菲-赫尔曼密钥交换是1976年在Whitfield Diffie和Martin Hellman的合作下发明的。它是第一个实用的在非保护信道中建立共享密钥方法。

这个方案首先由Whitfield Diffie和Martin Hellman于1976发布。后来发现这个方案已经在之前几年由英国信号情报部门发明(发明者为Malcolm J. Williamson),但是当时这被列为是机密。2002年,赫尔曼建议将该算法改名为Diffie–Hellman–Merkle密钥交换以表明 Ralph Merkle对于公钥加密算法的贡献(Hellman, 2002)。

2002年,Martin Hellman写到:

这个系统…从此被称为迪菲-赫尔曼密钥交换。 虽然这个系统首先是在我和迪菲的一篇论文中描述的,但是这却是一个公钥交换系统,是Merkle提出的概念,因此如果加上他的名字,这个系统实际上应该称为’Diffie–Hellman–Merkle密钥交换’。我希望这个小小的讲坛可以帮助我们认识到Merkle对公钥密码学的同等重要的贡献。

美国专利 4,200,770, 现在已经过期。它描述了这个算法,并且表明了Hellman、Diffie和Merkle是算法的发明者。

二、相关的算法重点:
模有关的公式:

a*b mod n ≡ ( (a mod n) * (b mod n ) ) mod n

1、什么是元根(primitive_root),为什么需要元根?

(1)定义:若p为一个质数,若存在1<a<=p-1,使得:
a mod p,
a^2 mod p,
a^3 mod p,

a^(p-1) mod p ,两两互不相同,且构成一个1~p-1的全体数的一个排列,则a为p的原根。(元根可能有多个)。

(2)为什么需要元根?,元根的意义是什么?

元根有一些特别的特性:比如
对于p=5,那么,2和3就是其元根。在这种情况下,对于元根2,存在这种关系
2^0 =1mod5
2^1= 2mod5
2^2 =4 mod5
2^3 =3 mod5
2^4 =1 mod5
3也是一样的。
(3)为什么需要的是质数?

当 a, p都为质数时,可以利用欧拉定理,来快速计算。具体可以参考相关数论书。密码学离开欧拉定理根本就玩不转。
欧拉函数φ的定义:对于正整数N,代表小于等于N的与N互质的数的个数,记作φ(N)。
特别地,对于N为质数时,φ(N)=N-1;
欧拉定理:
若N>2; a与N互质,则a^(φ(N)) ≡1modN .

如何应用:比如,对于 3^2018 mod 7,我们就可以:
φ(7) =6;
根据欧拉定理,则有:
3^(φ(7)) mod 7
=3^6 mod 7
=1 mod7;

那么
3 ^2018 mod7
= (3^6 ) ^336 * 3^2 mod7 =( ((3^6 ) ^336 mod7 )* (3^2 mod7) ) mod7
=( 1* (3^2 mod7) ) mod7
=1*2 mod7
=2

如果不是质数,那这个情况就不容易处理了。

实际操作中,元根也会选择是一个质数的元根。这样,元根和欧拉定理的性质都能用上了。

思考一下:假定元根为a =113,N =2^127 -1 即113^ 19 mod N,如何计算?

2、指数模的计算(x^y mod p),当x,y值较大时,直接计算是不可行了,需要借助算法。

3、为什么D-H算法会有效?

D-H算法的实质是,
(1)对于给定K,G,p 三个值,求K=(G^a ) % p,中a的值;
或者
(2)给定M,G,p 三个值,求M= (G^b) % p , 中b的值;
其中(1),K为A发给B的值;G,p是已知,G为元根,p为大质数。(2)同样。

可以看出,一方面,非常困难 。即上面的式子,在p为大质数时,G为元根的情况下,(1)或(2)的求解,目前没有快速的算法,只有暴力破解,但耗时过长。【不信你可以试试,反正我是试过了,电脑一直不动】。
另一方面,却非常容易。即已知(G^a ) % p,中G,a, p;却很容易算出K; 【后面也有算法哈】

同一个公式的两边,形成了一个非常困难和一个非常容易(象不象RSA的结构?),形成一个严重不对称的结构(即单向陷门函数的特征),因此,可以用来进行密码处理。

三、相关的rust 代码

use std::{thread, time};
//D-H密码交换
fn is_prime(n: u128) -> bool {!(2..(n)).any(|x| n % x == 0)
}
fn max_prime(n: u128) -> u128 {let mut num = n;while !is_prime(num) {num = num - 1;}num
}
// x^y mod p 如何计算 13^15679 mod 458
fn pow_mod(x: u128, y: u128, p: u128) -> u128 {if y == 0 {return 1;} else {let z = pow_mod(x, y / 2, p); //如果y=5_u128, y/2=2if y % 2 == 0 {return ((z % p) * (z % p)) % p;} else {return ((((x % p) * (z % p)) % p) * (z % p)) % p;}}
}//求p 原始根 的集合,最多产生元根的上限,从小至大
fn generator_primitive_root(p: u128, num: u128) -> Vec<u128> {if !is_prime(p) {panic!("p:{} is not prime!", p);}let mut values: Vec<u128> = Vec::new();let target = (1..p).map(|x| x).collect::<Vec<u128>>();for i in 1..p {if values.len() as u128 > num {return values;}let mut temp_value: Vec<u128> = (1..p).map(|y| pow_mod(i, y, p)).collect();temp_value.sort();if temp_value == target {values.push(i);//println!("value:{:?}=>{}",temp_value,x);}}println!("元根value:{:?}", values);values
}
//求 指数i, 即为b(任意数)的以a为基数的模p的离散对数。
fn dis_log(b: u128, a: u128, p: u128) -> u128 {//对于任意数b及素数p的原始根a,可以找到一个唯一的指数i,满足:b=( a ^ i) mod p,其中 0≤i≤p-1let data: Vec<u128> = (0..p - 1).filter(|&i| pow_mod(a, i, p) == b).collect();println!("dis_log=> i ={:?}", data);data[0]
}
fn main() {let sleep_seconds = time::Duration::from_secs(1000);let randnum = 1259_u128; //随机输入一个较大的值let max_prime = max_prime(randnum); //求出randnum中最大的质数let groups_primitive_root = generator_primitive_root(max_prime, 50); //50个原根let G_primitive_root = *&groups_primitive_root[10]; //10为随机取,指取第11个元根集合数据let P = max_prime;let A_private_key = 14_u128; // no openlet B_private_key = 39_u128; // no openlet A_send_to_B_num = pow_mod(G_primitive_root, A_private_key, P);let B_send_to_A_num = pow_mod(G_primitive_root, B_private_key, P);let A_compute_key_num = pow_mod(B_send_to_A_num, A_private_key, P);let B_compute_key_num = pow_mod(A_send_to_B_num, B_private_key, P);println!("测试中的参数:");println!("G_primitive_root : {:?}", G_primitive_root);println!("A_send_to_B_num  : {:?}", A_send_to_B_num);println!("B_send_to_A_num  : {:?}", B_send_to_A_num);println!("A_compute_key_num: {:?}", A_compute_key_num);println!("B_compute_key_num: {:?}", B_compute_key_num);println!("\n真实环境中的参数:");// 真实中的加密参数let g: u128 = 113;let p: u128 = 2_u128.pow(128) - 1; //巨大的质数let a_private_key = 19; //保密let b_private_key = 23; //保密let a_send_to_b_num = pow_mod(g, a_private_key, p);let b_send_to_a_num = pow_mod(g, b_private_key, p);println!("真实环境中的A发送的值:{}", a_send_to_b_num);println!("真实环境中的B发送的值:{}", b_send_to_a_num);let a_compute_key_num = pow_mod(b_send_to_a_num, a_private_key, p);let b_compute_key_num = pow_mod(a_send_to_b_num, b_private_key, p);println!("真实环境中a_compute_key_num:{:?}", a_compute_key_num);println!("真实环境中b_compute_key_num:{:?}", b_compute_key_num);println!("mod:{}", pow_mod(48_u128, 23_u128, 187));thread::sleep(sleep_seconds);
}

四、输出结果:

可见,在元根为32的情况下,A发送给B的数值为964;B发送给A的数值为145;但是,各自都拥有了共同的密钥822.可见算法经过了验证。

需要说明的是:上述算法,并没有得到与第三方验证。目前只是一种了解性的参考。

五、为什么D-H算法会有效?

问题在,当p较大时,计算元根将非常耗时,所有本文采用选用前多少个元根。尽管如何,当p较大时,计算3-5个元根集,就是巨大的运算量。因此,暴力破解花的时间将非常长。

Rust : 用rust实现Diffe-Hellman算法相关推荐

  1. Rust:Rust语言介绍

    Rust语言介绍 相关资源 Rust官网:https://www.rust-lang.org/ Rust编译器的源码:https://github.com/rust-lang/rust 语言设计和相关 ...

  2. rust 局域网联机_腐蚀rust搭建Rust服务器及联机教程

    今天 九游和大家讲解腐蚀rust搭建Rust服务器及 联机教程 腐蚀rust服务器搭建教程.这里为大家介绍如何搭建服务器,可以进行单机也可以和小伙伴联机,下面介绍详细的方法. Steam游戏后台服务器 ...

  3. 如何编写一个 Rust 程序——Rust语言基础02

    1. Hello World! 在所有编程语言的教程中让大家接触的第一段程序便是将 "Hello World!" 这段文字打印到屏幕上,这样的开端被绝大多数语言的教学接受,并往后编 ...

  4. rust(36)-Rust and WebAssembly(3)

    线性内存 WebAssembly有一个非常简单的内存模型.一个wasm模块可以访问单个"线性内存",它本质上是一个平面字节数组.该内存可以以页面大小(64K)的倍数增长.它不能被缩 ...

  5. rust(33)-Rust and WebAssembly(1)

    具有高级人机工程学的低级控制 JavaScript Web应用程序很难获得和保持可靠的性能.JavaScript的动态类型系统和垃圾收集暂停不起作用.如果您不小心偏离了JIT的正确方向,那么看似很小的 ...

  6. 【一起学Rust】Rust的Hello Rust详细解析

    跟随本篇文章,你将学会编写Rust的Hello World,并且对Rust编程有个初步的了解. 文章目录 前言 一.创建项目目录 二.编写Hello World 三.运行程序 编译 运行 四.分析He ...

  7. 【一起学Rust】Rust学习前准备——注释和格式化输出

    提示:准备热身. 文章目录 前言 一.注释 1. 普通注释 2. 文档注释 二.格式化输出 输出字符串 输出带有占位符的字符串 输出带有指定格式占位符的字符串 指定宽度对齐 数字输出缺位补0 总结 注 ...

  8. [Rust笔记]Rust生成随机数的方法

    1.前言 在项目当中,生成随机数.随机密码等经常会使用到.这里总结下Rust随机数生成的方法.Rust我们要用到包模块 rand.具体实现如下: 2.添加模块依赖 [dependencies] ran ...

  9. 【一起学Rust】Rust包管理工具Cargo初步了解

    提示:建议学习完上一节内容再学习本章内容哦,详情请订阅本专栏. 文章目录 前言 一.使用 Cargo 创建项目 1. 新建项目 2. 指定版本管理系统 3. Cargo.toml配置文件 二.构建并运 ...

  10. rust语言与go语言_后Mozilla Rust:Rust语言的未来

    rust语言与go语言 With Mozilla shrinking in total employees, what is going to happen with Rust? 随着Mozilla员 ...

最新文章

  1. Mysql (一)Mysql 数据库增删改查
  2. 如何设置'REUSE_ALV_GRID_DISPLAY'的单个单元格的颜色
  3. Python 列表list与数组array的区别
  4. curl查看swift状态命令_HTTP 请求与响应包括哪些,如何用Chrome查看 HTTP 请求与响应内容和curl 命令的使用...
  5. zabbix使用IT services 了解服务器SLA整体情况
  6. C++ Traits技术
  7. bzoj1088 [SCOI2005]扫雷Mine
  8. 使用Java 自身Timer API实现定时器的方法
  9. CodeRunner激活
  10. uniapp 苹果安全区配置
  11. 输出一个小游戏——三子棋
  12. SQL 2012 拒绝了对对象 '表名‘' (数据库 'xxxxx',架构 'dbo')的 SELECT 权限。
  13. 通过银行卡号获取所属银行
  14. 难溶盐在盐酸中的溶解度分析
  15. c语言知识地图,【程序设计论文】C语言程序设计翻转课堂研究(共3546字)
  16. 使用Python,OpenCV制作不同风格的素描图(正常,漫画,写实风格)
  17. jason-2影像下载
  18. 使用jquery制作漂亮相册集
  19. Opencv学习笔记 图像分割三(ImageJ 分水岭)
  20. PSIM入门:简单实例讲解PSIM基本操作(PSIM Basic Simulation)

热门文章

  1. Vue.js常用开发知识简要入门(二)
  2. linux 之 sed
  3. mssql 2005/2008/2012如何添加、查询、修改分区表中的数据 .
  4. 避重就轻:Intel的垄断抗辩
  5. JGit、SvnKit - 版本提交日志(1)提取
  6. 禅道项目管理工具环境搭建
  7. ASP.NET中的TextBox下划线
  8. POJ 2752 Seek the Name, Seek the Fame (KMP)
  9. MySQL查询优化:查询慢原因和解决技巧
  10. android SDK 常见安装方法