Rust and 3-way Diffie-Hellman

C is responsible for some many problems in Cybersecurity. So what’s the alterative? Well, we can use Python and Node.js, but they are…

Photo by Sixteen Miles Out on Unsplash

Rust and 3-way Diffie-Hellman

C is responsible for some many problems in Cybersecurity. So what’s the alterative? Well, we can use Python and Node.js, but they are generally slower than C and reveal their source code. We can then turn to Golang, but it is still a language in transistion, and the libraries are still not as extensive as Python and Node.js. But, for seriously secure code, the focus should be on Rust, and which makes sure that the code and the build process is done correctly. So let’s do a bit of 3-way Diffie-Hellman key exchange between Bob, Alice and Carol, using Rust.

Bob, Alice and Carol

Elliptic curves are used fairly extensively in public key encryption (such as in Bitcoin and Tor). A BN-curve (Barreto-Naehrig curve) defines an elliptic curve which can be used for pairings that allow for a high security and efficiency level. This page implements the tripartite Diffie-Hellman algorithm and where Bob, Alice and Carol can share a secret key. In this case we will not be using crypto pairing, but have two rounds of exchange. In this case we have a curve (G1) and a generator point (G), and Bob, Alice and Carol determine their private key value (a, b and c). Next they exchange their public key values of aG, bG and cG, and go through two rounds of exchange, to eventually end up with abcG.

Initally, we generate a scalar value of the private key, and then an (x,y) point on the G1 curve:

0422971d5eb242dfa51c74585cfbca5e8e7eecb19e9b33220761b1401320b343951e0b84773b4a92de731800374ec40d1f44f8b726e42ec6c2bcb8b24f766a33d7

In this case we have:

04 22971d5eb242dfa51c74585cfbca5e8e7eecb19e9b33220761b1401320b34395, 1e0b84773b4a92de731800374ec40d1f44f8b726e42ec6c2bcb8b24f766a33d7

and where 04 identifies a point, and we then get an x and a y value (64 bytes each — 256 bits).

A sample run is [here]:

Base point "0400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"
Alice priv: "0dc7e1f2bfd65268bdc1157a157cbcd2f022d72cfaac32b02279e2b699089374"
Bob priv "2dc0c0c8893736c98d1806733f5fb2ac9beecf95e6d03e1ad52b2784447f3b59"
Carol priv "1b258c15e22c29e22f97f55f623b7bb9189adf78ed9b88cde3b8a99b0c74d245"
Alice pub: "041eb34aa5b9f67c301ba5a5c2ff12d5c1a2edfd63ac8984e9186857e2e7822437284b4cc8811d925a21392e29c06324c4b430fb9361a6473def8701cb28c866f9"
Bob pub "042f70b1e97911e70ae8ae38dcc2e4417f976131411265eda478c980e61d982c431f102a0e7eb05a027d76c8ff858f7ef7c07316533b3745fde5ee39abe3b351f3"
Carol pub "04224582dd038b27abd06abed8565ca1a5d7b25377297154c81183032370df37ff168828953a2e81583762495f4587c0a51b01f2b10459409f19de6eb3e5f5a036"
Alice share: "041609af48251c0eb556415c5884ef10c11ce59586767e76033e9d5192a22325902e90747a66c2b2b5133ae390b76634348b1ef9ac66b5ce6650e93a143c8afe88"
Bob share "041609af48251c0eb556415c5884ef10c11ce59586767e76033e9d5192a22325902e90747a66c2b2b5133ae390b76634348b1ef9ac66b5ce6650e93a143c8afe88"
Carol share "041609af48251c0eb556415c5884ef10c11ce59586767e76033e9d5192a22325902e90747a66c2b2b5133ae390b76634348b1ef9ac66b5ce6650e93a143c8afe88"

The code used for this is [here]:

extern crate bn;
extern crate rand;
use bn::{G1,Fr};
use crate::bn::Group;
extern crate bincode;
extern crate rustc_serialize;
use bincode::SizeLimit::Infinite;
use bincode::rustc_serialize::{encode};
use rustc_serialize::{Encodable};
use rustc_serialize::hex::{ ToHex};
pub fn into_hex(obj: S) -> Option {
encode(&obj, Infinite).ok().map(|e| e.to_hex())
}
fn main() {
print!("Base point {:?}", into_hex(G1::one()).unwrap());
    let rng = &mut rand::thread_rng();
    // Construct private keys
let a = Fr::random(rng);
let b = Fr::random(rng);
let c = Fr::random(rng);
    print!("\n\nAlice priv: {:?}\n\nBob priv {:?}\n\nCarol priv {:?}",  into_hex(a).unwrap(), into_hex(b).unwrap(), into_hex(c).unwrap());

// Public keys
let alice_pk = G1::one() * a;
let bob_pk = G1::one() * b;
let carol_pk = G1::one() * c;
  
print!("\n\nAlice pub: {:?}\n\nBob pub {:?}\n\nCarol pub {:?}", into_hex(alice_pk).unwrap(), into_hex(bob_pk).unwrap(), into_hex(carol_pk).unwrap());

    // Round 1
let alice_1 = bob_pk * c;
let bob_1 = carol_pk * a;
let carol_1 = alice_pk * b;
    // Round 2
let alice_share =alice_1 * a;
let bob_share = bob_1 * b;
let carol_share = carol_1 * c;
    print!("\n\nAlice share: {:?}\n\nBob share {:?}\n\nCarol share {:?}",  into_hex(alice_share).unwrap(), into_hex(bob_share).unwrap(), into_hex(carol_share).unwrap());
 
}

and the Cargo.toml file is:

[package]
name = "pair01"
version = "0.1.0"
authors = ["billbuchanan]
edition = "2018"

[dependencies]
bn = "0.4.3"
rand = "0.4"
rustc-serialize = "~0.3.19"
bincode = "0.6.1"

A running version of the code is here:

https://asecuritysite.com/rust/rust_3way

Conclusions

If you are serious about writing secure code, investigate Rust.