1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
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
        }
    }
}