Diffie Hellman

1. Readme

迪菲-赫尔曼

迪菲-赫尔曼密钥交换

Alice 和 Bob 使用 迪菲-赫尔曼密钥来共享秘密。它们以素数开头,选择私钥,生成和共享公钥,然后生成共享密钥.

第 0 步

测试程序提供素数 p 和 g.

步骤 1

Alice 选择一个大于 1 ,且小于 p 的私钥。鲍勃做同样的事情来选择私钥 b.

第 2 步

Alice 计算公钥 A.

A = g**a mod p

使用相同的 p 和 g, Bob 类似地从他的私钥 b 计算公钥 B.

第 3 步

Alice 和 Bob 交换公钥.Alice 计算密钥 s.

s = B**a mod p

鲍勃计算

s = A**b mod p

计算产生相同的结果! 爱丽丝和鲍勃现在分享秘密.

本练习的一种可能解决方案是实现您自己的模幂运算函数。要了解更多信息,请参阅following page.

资源

2. 开始你的表演

pub fn private_key(p: u64) -> u64 {
   unimplemented!("Pick a private key greater than 1 and less than {}", p)
}

pub fn public_key(p: u64, g: u64, a: u64) -> u64 {
   unimplemented!(
       "Calculate public key using prime numbers {} and {}, and private key {}",
       p,
       g,
       a
   )
}

pub fn secret(p: u64, b_pub: u64, a: u64) -> u64 {
   unimplemented!(
       "Calculate secret key using prime number {}, public key {}, and private key {}",
       p,
       b_pub,
       a
   )
}

3. 测试代码查看


# #![allow(unused_variables)]
#fn main() {
#[test]
fn test_private_key_in_range_key() {
   let primes: Vec<u64> = vec![
       5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 773, 967, 3461, 6131,
   ];
   let private_keys: Vec<u64> = primes.iter().map(|x| private_key(*x)).collect();

   for i in 0..primes.len() {
       assert!(1 < private_keys[i] && private_keys[i] < primes[i]);
   }
}

#[test]
//#[ignore]
fn test_public_key_correct() {
   let p: u64 = 23;
   let g: u64 = 5;

   let private_key: u64 = 6;
   let expected: u64 = 8;

   assert_eq!(public_key(p, g, private_key), expected);
}

#[test]
//#[ignore]
fn test_secret_key_correct() {
   let p: u64 = 11;

   let private_key_a = 7;
   let public_key_b = 8;
   let secret = secret(p, public_key_b, private_key_a);
   let expected = 2;

   assert_eq!(secret, expected);
}

#[test]
//#[ignore]
fn test_public_key_correct_big_numbers() {
   let p: u64 = 4_294_967_299;

   let g: u64 = 8;

   let private_key: u64 = 4_294_967_296;

   let expected: u64 = 4096;

   assert_eq!(public_key(p, g, private_key), expected);
}

#[test]
//#[ignore]
fn test_secret_key_correct_big_numbers() {
   let p: u64 = 4_294_967_927;

   let private_key_a = 4_294_967_300;

   let public_key_b = 843;

   let secret = secret(p, public_key_b, private_key_a);

   let expected = 1_389_354_282;

   assert_eq!(secret, expected);
}

#[test]
//#[ignore]
fn test_changed_secret_key() {
   let p: u64 = 13;
   let g: u64 = 11;

   let private_key_a = private_key(p);
   let private_key_b = private_key(p);

   let public_key_a = public_key(p, g, private_key_a);
   let public_key_b = public_key(p, g, private_key_b);

   // Key exchange
   let secret_a = secret(p, public_key_b, private_key_a);
   let secret_b = secret(p, public_key_a, private_key_b);

   assert_eq!(secret_a, secret_b);
}

#}

4. 答案


# #![allow(unused_variables)]
#fn main() {
extern crate rand;
use rand::{thread_rng, Rng};


/// Right-to-left modular exponentiation implementation
/// For more information see https://en.wikipedia.org/wiki/Modular_exponentiation
fn modular_exponentiation(base: u64, exponent: u64, modulus: u64) -> u64 {
   let mut result = 1;

   let mut e = exponent;

   let mut b = base;

   while e > 0 {
       if (e & 1) == 1 {
           result = (result * b) % modulus;
       }

       e >>= 1;

       b = (b * b) % modulus;
   }

   result
}

pub fn private_key(p: u64) -> u64 {
   let mut rng = thread_rng();
   rng.gen_range(2, p)
}

pub fn public_key(p: u64, g: u64, a: u64) -> u64 {
   modular_exponentiation(g, a, p)
}

pub fn secret(p: u64, b_pub: u64, a: u64) -> u64 {
   modular_exponentiation(b_pub, a, p)
}

#}



填充/相关