From cf4ed2c2e6cb329f5487c1f1a2e999b86c70ef05 Mon Sep 17 00:00:00 2001 From: palaviv Date: Fri, 15 Jul 2016 14:01:31 +0300 Subject: [PATCH] feat(asymmetric::dh): Diffie-Hellman implementation --- crypto/src/asymmetric/dh/mod.rs | 112 ++++++++++++++++++++++++++++++ crypto/src/asymmetric/mod.rs | 2 + crypto/tests/asymmetric/dh/mod.rs | 20 ++++++ crypto/tests/asymmetric/mod.rs | 1 + crypto/tests/lib.rs | 1 + 5 files changed, 136 insertions(+) create mode 100644 crypto/src/asymmetric/dh/mod.rs create mode 100644 crypto/tests/asymmetric/dh/mod.rs create mode 100644 crypto/tests/asymmetric/mod.rs diff --git a/crypto/src/asymmetric/dh/mod.rs b/crypto/src/asymmetric/dh/mod.rs new file mode 100644 index 000000000..d8584a4ae --- /dev/null +++ b/crypto/src/asymmetric/dh/mod.rs @@ -0,0 +1,112 @@ +use bigint::{BigUint, RandBigInt}; +use num::FromPrimitive; +use num::{One,Zero}; + +use rand; + +use asymmetric::utils::modular::Power; + +// From rfc 2409 (https://tools.ietf.org/html/rfc2409). +pub const RFC2409_PRIME_768: [u8; 96] = [ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2, + 0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1, + 0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6, + 0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, + 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D, + 0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45, + 0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9, + 0xA6,0x3A,0x36,0x20,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + ]; + +pub const RFC2409_GENERATOR_768: u64 = 2; + +pub const RFC2409_PRIME_1024: [u8; 128] = [ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2, + 0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1, + 0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6, + 0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, + 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D, + 0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45, + 0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9, + 0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, + 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11, + 0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE6,0x53,0x81, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + ]; + +pub const RFC2409_GENERATOR_1024: u64 = 2; + + +pub struct DHPublicKey { + pub_key: BigUint, +} + +pub struct DHPrivateKey<'a> { + params: &'a DHParameters, + priv_key: BigUint, +} + +impl DHPublicKey { + pub fn new(pub_key: BigUint) -> DHPublicKey { + DHPublicKey { + pub_key: pub_key + } + } + + pub fn key(&self) -> BigUint { + self.pub_key.clone() + } +} + +impl<'a> DHPrivateKey<'a> { + pub fn key(&self) -> BigUint { + self.priv_key.clone() + } + + pub fn public_key(&self) -> DHPublicKey { + let pub_key = (&self.params.g).pow_mod(&self.priv_key, &self.params.p); + + DHPublicKey { + pub_key: pub_key + } + } + + pub fn exchange(&self, pub_key: &DHPublicKey) -> BigUint { + (&pub_key.pub_key).pow_mod(&self.priv_key, &self.params.p) + } +} + +pub struct DHParameters { + p: BigUint, + g: BigUint, +} + +impl DHParameters { + pub fn new(p: &[u8], g: u64) -> DHParameters { + DHParameters { + p: BigUint::from_bytes_be(p), + g: BigUint::from_u64(g).expect("Could not convert g") + } + } + + pub fn key_length(&self) -> usize { + self.p.bits() + } + + pub fn private_key(&self) -> DHPrivateKey { + let mut rng = match rand::OsRng::new() { + Ok(g) => g, + Err(e) => panic!("Could not load the OS' RNG! Error: {}", e) + }; + + let mut priv_key = rng.gen_biguint(self.key_length()); + while (priv_key == BigUint::one()) || (priv_key == BigUint::zero()) { + priv_key = rng.gen_biguint(self.key_length()); + } + + DHPrivateKey { + params: self, + priv_key: priv_key + } + } +} diff --git a/crypto/src/asymmetric/mod.rs b/crypto/src/asymmetric/mod.rs index 1eed20c7b..44959cc8c 100644 --- a/crypto/src/asymmetric/mod.rs +++ b/crypto/src/asymmetric/mod.rs @@ -2,4 +2,6 @@ pub mod rsa; +pub mod dh; + mod utils; diff --git a/crypto/tests/asymmetric/dh/mod.rs b/crypto/tests/asymmetric/dh/mod.rs new file mode 100644 index 000000000..2c2c7741d --- /dev/null +++ b/crypto/tests/asymmetric/dh/mod.rs @@ -0,0 +1,20 @@ +use crypto::asymmetric::dh::{DHParameters, RFC2409_PRIME_768, RFC2409_GENERATOR_768, + RFC2409_PRIME_1024, RFC2409_GENERATOR_1024}; + + +fn test_exhange_with_params(params: &DHParameters) { + let priv_key1 = params.private_key(); + let priv_key2 = params.private_key(); + let pub_key1 = priv_key1.public_key(); + let pub_key2 = priv_key2.public_key(); + let shared_key1 = priv_key2.exchange(&pub_key1); + let shared_key2 = priv_key1.exchange(&pub_key2); + assert!(shared_key1 == shared_key2); +} + +#[test] +fn test_exchange() { + test_exhange_with_params(&DHParameters::new(&[0x17], 5)); + test_exhange_with_params(&DHParameters::new(&RFC2409_PRIME_768, RFC2409_GENERATOR_768)); + test_exhange_with_params(&DHParameters::new(&RFC2409_PRIME_1024, RFC2409_GENERATOR_1024)); +} diff --git a/crypto/tests/asymmetric/mod.rs b/crypto/tests/asymmetric/mod.rs new file mode 100644 index 000000000..04b27d501 --- /dev/null +++ b/crypto/tests/asymmetric/mod.rs @@ -0,0 +1 @@ +mod dh; diff --git a/crypto/tests/lib.rs b/crypto/tests/lib.rs index 0a76a29ed..c14a03fdc 100644 --- a/crypto/tests/lib.rs +++ b/crypto/tests/lib.rs @@ -2,3 +2,4 @@ extern crate octavo_crypto as crypto; mod block; mod stream; +mod asymmetric;