Commit 7f284524 authored by Jack Doerner's avatar Jack Doerner

synchronize multi-party and ARM/embedded support from private branch

parent be349aff
[submodule "curves"]
path = curves
url = [email protected]:neucrypt/curves.git
url = https://gitlab.com/neucrypt/curves.git
branch = release
[submodule "blake2"]
path = blake2
url = https://github.com/BLAKE2/BLAKE2.git
......@@ -5,12 +5,16 @@ authors = ["abhi <[email protected]>", "Jack Doerner <[email protected]>"]
build = "build.rs"
[dependencies]
getopts = "0.2"
getopts = "0.2.21"
rand = "0.3.16"
curves = { path = "./curves" }
rust-crypto = "^0.2"
time="*"
byteorder = "1.1.0"
bit_reverse = "0.1.7"
openmp-sys = "0.1.1"
rayon = "1.0"
\ No newline at end of file
rayon = "1.1"
hex = "*"
[features]
blake2 = []
rpi3 = ["blake2"]
\ No newline at end of file
# MPECDSA
This repository contains an implementation of the 2-of-n threshold ECDSA protocol described in
_Threshold ECDSA from ECDSA assumptions_ by Jack Doerner, Yashvanth Kondi, Eysa Lee, and abhi shelat, which appeared at the IEEE Security & Privacy Conference (Oakland) 2018. A full version of this paper with complete proofs is available as [eprint 2018/499](https://eprint.iacr.org/2018/499), and the original conference version is available from the [IEEE](https://www.computer.org/csdl/proceedings/sp/2018/4353/00/435301a595-abs.html).
This repository contains a implementations of the 2-of-n threshold ECDSA protocol described in
[_Secure Two-party Threshold ECDSA from ECDSA assumptions_](https://eprint.iacr.org/2018/499) and the t-of-n threshold ECDSA protocol described in _Threshold ECDSA from ECDSA Assumptions_, both papers by Jack Doerner, Yashvanth Kondi, Eysa Lee, and abhi shelat.
## How to compile on Linux
......@@ -42,6 +42,24 @@ Our protocol requires the [```openmp```](https://www.openmp.org/) compiler featu
```
### How to cross-compile for Linux on Macos
This allows you to produce a statically-linked executable for Linux from MacOS.
```
brew install FiloSottile/musl-cross/musl-cross
brew install isl
install_name_tool -change '@@[email protected]@/opt/isl/lib/libisl.15.dylib' /usr/local/opt/isl/lib/libisl.dylib /usr/local/opt/musl-cross/libexec/libexec/gcc/x86_64-linux-musl/6.3.0/cc1
ab2017:mpecdsa_private abhi$ install_name_tool -change '@@[email protected]@/opt/isl/lib/libisl.15.dylib' /usr/local/opt/isl/lib/libisl.dylib /usr/local/opt/musl-cross/libexec/libexec/gcc/x86_64-linux-musl/6.3.0/cc1plus
ab2017:mpecdsa_private abhi$ install_name_tool -change '@@[email protected]@/opt/isl/lib/libisl.15.dylib' /usr/local/opt/isl/lib/libisl.dylib /usr/local/opt/musl-cross/libexec/libexec/gcc/x86_64-linux-musl/6.3.0/lto1
```
Finally, you can run
```
CC=/usr/local/bin/x86_64-linux-musl-gcc CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=/usr/local/bin/x86_64-linux-musl-gcc cargo build --release --target=x86_64-unknown-linux-musl
```
## Benchmarking
This repository includes three benchmark applications, which were used to generate the experimental results reported in the paper. They are:
......
Subproject commit 320c325437539ae91091ce62efec1913cd8093c2
......@@ -6,18 +6,69 @@
use std::process::Command;
use std::env;
use std::path::Path;
use std::string::String;
fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
Command::new("gcc").args(&["src/sha256_octa.c", "-c", "-mavx2", "-O3", "-fPIC", "-fopenmp", "-Wa,-q", "-o"])
.arg(&format!("{}/sha256_octa.o", out_dir))
.status().unwrap();
Command::new("ar").args(&["-crus", "libsha256_octa.a", "sha256_octa.o"])
.current_dir(&Path::new(&out_dir))
.status().unwrap();
println!("cargo:rustc-link-search=native={}", out_dir);
println!("cargo:rustc-link-lib=static=sha256_octa");
println!("cargo:rustc-link-lib=gomp");
let out_dir = env::var("OUT_DIR").unwrap();
println!("cargo:rustc-link-search=native={}", out_dir);
let extra_args = if std::env::var("TARGET").unwrap().contains("apple-darwin") {
vec!["-Wa,-q", "-O3", "-fPIC"]
} else {
vec!["-O3", "-fPIC"]
};
let cc = if std::env::var("CC").is_ok() {
std::env::var("CC").unwrap()
} else {
String::from("gcc")
};
let ar = if std::env::var("AR").is_ok() {
std::env::var("AR").unwrap()
} else {
String::from("ar")
};
if std::env::var("TARGET").unwrap().contains("x86_64") {
Command::new(&cc).args(&["src/sha256_octa.c", "-c", "-mavx2", "-o"])
.arg(&format!("{}/sha256_multi.o", out_dir))//.arg(&env::var("DEP_OPENMP_FLAG").unwrap())
.args(&extra_args).status().unwrap();
Command::new(&ar).args(&["-crus", "libsha256_multi.a", "sha256_multi.o"])
.current_dir(&Path::new(&out_dir))
.status().unwrap();
println!("cargo:rustc-link-lib=static=sha256_multi");
}
for file in ["blake2s", "blake2sp"].iter() {
if std::env::var("TARGET").unwrap().contains("x86_64") {
Command::new(&cc).args(&[&format!("blake2/sse/{}.c",file), "-c", "-mavx2", "-o"])
.arg(&format!("{}/{}.o", out_dir,file))
.args(&extra_args).status().unwrap();
} else if cfg!(feature="rpi3") {
Command::new(&cc).args(&[&format!("blake2/neon/{}.c",file), "-c", "-mcpu=cortex-a53", "-mfpu=neon-fp-armv8", "-mneon-for-64bits", "-mfloat-abi=hard", "-o"])
.arg(&format!("{}/{}.o", out_dir,file))
.args(&extra_args).status().unwrap();
} else if std::env::var("TARGET").unwrap().contains("aarch64") {
Command::new(&cc).args(&[&format!("blake2/neon/{}.c",file), "-c", "-march=armv8-a", "-mfpu=neon-fp-armv8", "-mfloat-abi=hard", "-o"])
.arg(&format!("{}/{}.o", out_dir,file))
.args(&extra_args).status().unwrap();
} else if std::env::var("TARGET").unwrap().contains("armv7") {
Command::new(&cc).args(&[&format!("blake2/neon/{}.c",file), "-c", "-march=armv7-a", "-mfpu=neon-vfpv4", "-mfloat-abi=hard", "-o"])
.arg(&format!("{}/{}.o", out_dir, file))
.args(&extra_args).status().unwrap();
} else {
Command::new(&cc).args(&[&format!("blake2/ref/{}-ref.c", file), "-c", "-o"])
.arg(&format!("{}/{}.o", out_dir,file))
.args(&extra_args).status().unwrap();
}
}
Command::new(&cc).args(&["src/blake2_multi.c", "-c", "-o"])
.arg(&format!("{}/blake2_multi.o", out_dir))//.arg(&env::var("DEP_OPENMP_FLAG").unwrap())
.args(&extra_args).status().unwrap();
Command::new(&ar).args(&["-crus", "libblake2.a", "blake2s.o", "blake2sp.o", "blake2_multi.o"])
.current_dir(&Path::new(&out_dir))
.status().unwrap();
println!("cargo:rustc-link-lib=static=blake2");
}
\ No newline at end of file
Subproject commit 67dbaf0823c0e63d72351306a4b81e3deee9bebb
Subproject commit 461899226de2812c859058014949d8e74e64168b
This diff is collapsed.
/// This program handles benchmarking for both signing and setup
///
use std::time::Duration;
use std::thread::sleep;
use std::net::{TcpListener, TcpStream};
use std::{env};
......@@ -46,7 +47,6 @@ pub fn process_options() -> Option<Matches> {
return Option::None;
}
return Option::Some(matches);
}
......@@ -68,14 +68,23 @@ fn main() {
matches.opt_str("p").unwrap_or("12345".to_owned()));
println!("Connecting to server {:?}...",port);
let mut stream1 = TcpStream::connect(port).unwrap();
let mut stream1 = TcpStream::connect(&port);
let connection_wait_time = 2*60;
let poll_interval = 100;
for _ in 0..(connection_wait_time*1000/poll_interval) {
if stream1.is_err() {
sleep(Duration::from_millis(poll_interval));
stream1 = TcpStream::connect(&port);
}
}
let stream1 = stream1.unwrap();
let stream2 = stream1.try_clone().unwrap();
(stream1, stream2)
} else {
let port = format!("0.0.0.0:{}",matches.opt_str("p").unwrap_or("12345".to_owned()));
println!("Waiting for client to connect on {}", port);
let listener = TcpListener::bind(port).unwrap_or_else(|e| {panic!(e) });
let (mut stream1, _) = listener.accept().unwrap_or_else(|e| {panic!(e) });
let (stream1, _) = listener.accept().unwrap_or_else(|e| {panic!(e) });
let stream2 = stream1.try_clone().unwrap();
(stream2, stream1)
};
......@@ -97,7 +106,7 @@ fn main() {
mpecdsa::mpecdsa::Bob2P::new(&skb, &mut rng, &mut streamrecv, &mut streamsend).unwrap();
}
let signend = PreciseTime::now();
println!("{} ms avg", (signstart.to(signend)/iters)*1000 );
println!("{:.3} ms avg", (signstart.to(signend).num_milliseconds() as f64)/(iters as f64) );
} else {
let bob = mpecdsa::mpecdsa::Bob2P::new(&skb, &mut rng, &mut streamrecv, &mut streamsend).unwrap();
......@@ -106,7 +115,7 @@ fn main() {
bob.sign(&msg, &mut rng, &mut streamrecv, &mut streamsend).unwrap();
}
let signend = PreciseTime::now();
println!("{} ms avg", (signstart.to(signend)/iters)*1000 );
println!("{:.3} ms avg", (signstart.to(signend).num_milliseconds() as f64)/(iters as f64) );
}
} else {
......@@ -117,7 +126,7 @@ fn main() {
mpecdsa::mpecdsa::Alice2P::new(&ska, &mut rng, &mut streamrecv, &mut streamsend).unwrap();
}
let signend = PreciseTime::now();
println!("{} ms avg", (signstart.to(signend)/iters)*1000 );
println!("{:.3} ms avg", (signstart.to(signend).num_milliseconds() as f64)/(iters as f64) );
} else {
let alice = mpecdsa::mpecdsa::Alice2P::new(&ska, &mut rng, &mut streamrecv, &mut streamsend).unwrap();
......@@ -126,7 +135,7 @@ fn main() {
alice.sign(&msg, &mut rng, &mut streamrecv, &mut streamsend).unwrap();
}
let signend = PreciseTime::now();
println!("{} ms avg", (signstart.to(signend)/iters)*1000 );
println!("{:.3} ms avg", (signstart.to(signend).num_milliseconds() as f64)/(iters as f64) );
}
}
......
......@@ -14,10 +14,6 @@ use rand::{Rng};
extern crate time;
use time::PreciseTime;
extern crate curves;
use curves::{Ford};
use curves::f_4141::FSecp256Ord;
extern crate mpecdsa;
extern crate getopts;
......@@ -84,16 +80,12 @@ fn main() {
let addrs = matches.opt_str("a").unwrap_or("0.0.0.0".to_owned());
let addrs: Vec<&str> = addrs.split(",").collect();
let port: usize = matches.opt_str("p").unwrap_or("12345".to_owned()).parse().unwrap();
let min_ports = parties*(parties-1)/2;
let min_ports = parties;
let mut ports = Vec::with_capacity(min_ports);
for ii in port..(port+min_ports) {
ports.push(format!("{}", ii));
}
// random sk generation from mpecdsa test
let mut _rng = rand::thread_rng();
let ski = FSecp256Ord::rand(&mut _rng);
for jj in 0..parties {
// first n-1 are party 0's ports, next n-2 party 1, ...
// given a high and a low, offset into list of ports is
......@@ -104,29 +96,38 @@ fn main() {
// (n * low) - low * (low + 1) / 2 + high - low - 1
if jj < index {
let port_index = (jj*parties)-(jj*(jj+1))/2 + (index-jj) - 1;
let port_index = jj;
let port = format!("0.0.0.0:{}", &ports[port_index]);
println!("{} waiting for {} to connect on {}", index, jj, port);
let listener = TcpListener::bind(port).unwrap_or_else(|e| { panic!(e) });
let (mut recv, _) = listener.accept().unwrap_or_else(|e| {panic!(e)} );
let (recv, _) = listener.accept().unwrap_or_else(|e| {panic!(e)} );
let send = recv.try_clone().unwrap();
recv.set_nodelay(true).expect("Could not set nodelay");
send.set_nodelay(true).expect("Could not set nodelay");
sendvec.push(Some(send));
recvvec.push(Some(recv));
} else if jj > index {
let port_index = (index*parties)-(index*(index+1))/2 + (jj-index) - 1;
let port_index = index;
let port = format!("{}:{}", addrs[jj], &ports[port_index]);
println!("{} connecting to {} server {:?}...", index, jj, port);
let mut send = TcpStream::connect(port).unwrap();
let mut recv = send.try_clone().unwrap();
let mut send = TcpStream::connect(&port);
let connection_wait_time = 2*60;
let poll_interval = 100;
for _ in 0..(connection_wait_time*1000/poll_interval) {
if send.is_err() {
sleep(Duration::from_millis(poll_interval));
send = TcpStream::connect(&port);
}
}
let send = send.unwrap();
let recv = send.try_clone().unwrap();
recv.set_nodelay(true).expect("Could not set nodelay");
send.set_nodelay(true).expect("Could not set nodelay");
sendvec.push(Some(send));
recvvec.push(Some(recv));
} else {
// pause here so the lower numbers can start their listeners?
sleep(Duration::from_millis(500));
//sleep(Duration::from_millis(500));
sendvec.push(None);
recvvec.push(None);
}
......@@ -137,23 +138,31 @@ fn main() {
let mut rng = rand::ChaChaRng::new_unseeded();
rng.set_counter(seeder.gen::<u64>(), seeder.gen::<u64>());
println!("{} connected. Initializing...", index);
if index==parties-1 {
let mut sigread = [1u8; 1];
for ii in 0..parties-1 {
recvvec[ii].as_mut().unwrap().read_exact(&mut sigread).expect(&format!("Party {} failed to send ready signal.", ii));
}
for ii in 0..parties-1 {
sendvec[ii].as_mut().unwrap().write(&[0]).expect(&format!("Party {} failed to send ready signal.", index));
sendvec[ii].as_mut().unwrap().flush().expect(&format!("Party {} failed to flush.", index));
}
} else {
let mut sigread = [1u8; 1];
recvvec[parties-1].as_mut().unwrap().read_exact(&mut sigread).expect(&format!("Party {} failed to read ready signal.", index));
sendvec[parties-1].as_mut().unwrap().write(&[0]).expect(&format!("Party {} failed to send ready signal.", index));
sendvec[parties-1].as_mut().unwrap().flush().expect(&format!("Party {} failed to flush.", index));
recvvec[parties-1].as_mut().unwrap().read_exact(&mut sigread).expect(&format!("Party {} failed to send ready signal.", parties-1));
}
println!("{} connected. Performing {} Iteration Benchmark...", index, iters);
println!("Performing {} Iteration Benchmark...", iters);
let setupstart = PreciseTime::now();
for _ in 0..iters {
mpecdsa::mpecdsa::ThresholdSigner::new(index, thres, &ski, &mut rng, sendvec.as_mut_slice(), recvvec.as_mut_slice()).unwrap();
mpecdsa::mpecdsa::ThresholdSigner::new(index, thres, &mut rng, sendvec.as_mut_slice(), recvvec.as_mut_slice()).unwrap();
}
let setupend = PreciseTime::now();
println!("{} ms avg", (setupstart.to(setupend)/iters)*1000);
println!("{:.3} ms avg", (setupstart.to(setupend).num_milliseconds() as f64)/(iters as f64));
}
\ No newline at end of file
/// Benchmarking for 2 of n signing
///
use std::time::Duration;
use std::thread::sleep;
use std::io::{Write, Read};
use std::net::{TcpListener, TcpStream};
use std::{env};
......@@ -10,10 +13,6 @@ use rand::{Rng};
extern crate time;
use time::PreciseTime;
extern crate curves;
use curves::{Ford};
use curves::f_4141::FSecp256Ord;
extern crate mpecdsa;
extern crate getopts;
......@@ -27,12 +26,16 @@ pub fn process_options() -> Option<Matches> {
let mut opts = Options::new();
opts.optopt("o", "", "set output file name", "NAME");
opts.optopt("p", "port", "set port", "PORT");
opts.optopt("p", "port", "lowest port (the required number will be allocated above)", "PORT");
opts.optopt("n", "iterations", "number of iterations", "ITERS");
opts.optopt("c", "client", "set ip address of server", "IP");
opts.optopt("a", "addresses", "comma-delimited list of IP Addresses", "IP");
opts.optflag("h", "help", "print this help menu");
opts.optflag("b", "bob", "run as bob");
// threshold flags
//opts.optopt("T", "threshold", "size of threshold", "THRES");
opts.optopt("N", "size", "number of parties", "SIZE");
opts.optopt("P", "party", "party number", "PARTY");
let matches = match opts.parse(&args[1..]) {
Ok(m) => { m }
......@@ -52,7 +55,6 @@ pub fn process_options() -> Option<Matches> {
fn main() {
let msg = "this is a test".as_bytes();
let matches = process_options();
if let None = matches {
......@@ -60,60 +62,118 @@ fn main() {
}
let matches = matches.unwrap();
// start up connections like how 2P works
let (mut streamrecv, mut streamsend) = if matches.opt_present("c") {
let port = format!("{}:{}",
matches.opt_str("c").unwrap(),
matches.opt_str("p").unwrap_or("12345".to_owned())
);
println!("Connecting to server {:?}...", port);
let mut stream1 = TcpStream::connect(port).unwrap();
let stream2 = stream1.try_clone().unwrap();
(stream1, stream2)
} else {
let port = format!("0.0.0.0:{}", matches.opt_str("p").unwrap_or("12345".to_owned()));
println!("Waiting for client to connect on {}", port);
let listener = TcpListener::bind(port).unwrap_or_else(|e| {panic!(e)} );
let (mut stream1, _) = listener.accept().unwrap_or_else(|e| {panic!(e)} );
let stream2 = stream1.try_clone().unwrap();
(stream2, stream1)
};
// number of parties
let parties = matches.opt_str("N").unwrap_or("2".to_owned()).parse::<usize>().unwrap();
//let thres = matches.opt_str("T").unwrap_or("2".to_owned()).parse::<usize>().unwrap();
// If party index isn't specified, assume 2P
let index = matches.opt_str("P").unwrap().parse::<usize>().unwrap();
let mut sendvec:Vec<Option<std::net::TcpStream>> = Vec::with_capacity(parties);
let mut recvvec: Vec<Option<std::net::TcpStream>> = Vec::with_capacity(parties);
streamsend.set_nodelay(true).expect("Could not set nodelay");
streamrecv.set_nodelay(true).expect("Could not set nodelay");
if !matches.opt_present("p") && parties!=2 {
println!("Please add ports");
::std::process::exit(1);
}
// ports should be separated by commas
let addrs = matches.opt_str("a").unwrap_or("0.0.0.0".to_owned());
let addrs: Vec<&str> = addrs.split(",").collect();
let port: usize = matches.opt_str("p").unwrap_or("12345".to_owned()).parse().unwrap();
let min_ports = parties;
let mut ports = Vec::with_capacity(min_ports);
for ii in port..(port+min_ports) {
ports.push(format!("{}", ii));
}
for jj in 0..parties {
// first n-1 are party 0's ports, next n-2 party 1, ...
// given a high and a low, offset into list of ports is
// sum i =1...low (n-i) => n*low - low*(low+1)/2
// corresponding port for high is given as the difference between high and low -1
// high - low - 1
// port_index for pair high, low becomes
// (n * low) - low * (low + 1) / 2 + high - low - 1
if jj < index {
let port_index = jj;
let port = format!("0.0.0.0:{}", &ports[port_index]);
println!("{} waiting for {} to connect on {}", index, jj, port);
let listener = TcpListener::bind(port).unwrap_or_else(|e| { panic!(e) });
let (recv, _) = listener.accept().unwrap_or_else(|e| {panic!(e)} );
let send = recv.try_clone().unwrap();
recv.set_nodelay(true).expect("Could not set nodelay");
send.set_nodelay(true).expect("Could not set nodelay");
sendvec.push(Some(send));
recvvec.push(Some(recv));
} else if jj > index {
let port_index = index;
let port = format!("{}:{}", addrs[jj], &ports[port_index]);
println!("{} connecting to {} server {:?}...", index, jj, port);
let mut send = TcpStream::connect(&port);
let connection_wait_time = 2*60;
let poll_interval = 100;
for _ in 0..(connection_wait_time*1000/poll_interval) {
if send.is_err() {
sleep(Duration::from_millis(poll_interval));
send = TcpStream::connect(&port);
}
}
let send = send.unwrap();
let recv = send.try_clone().unwrap();
recv.set_nodelay(true).expect("Could not set nodelay");
send.set_nodelay(true).expect("Could not set nodelay");
sendvec.push(Some(send));
recvvec.push(Some(recv));
} else {
// pause here so the lower numbers can start their listeners?
//sleep(Duration::from_millis(500));
sendvec.push(None);
recvvec.push(None);
}
}
let iters = matches.opt_str("n").unwrap_or("1000".to_owned()).parse::<i32>().unwrap();
let mut seeder = rand::os::OsRng::new().unwrap();
let mut rng = rand::ChaChaRng::new_unseeded();
rng.set_counter(seeder.gen::<u64>(), seeder.gen::<u64>());
println!("Connected. Performing {} Iteration Benchmark...", iters);
if index==parties-1 {
for ii in 0..parties-1 {
sendvec[ii].as_mut().unwrap().write(&[0]).expect(&format!("Party {} failed to send ready signal.", index));
sendvec[ii].as_mut().unwrap().flush().expect(&format!("Party {} failed to flush.", index));
}
} else {
let mut sigread = [1u8; 1];
recvvec[parties-1].as_mut().unwrap().read_exact(&mut sigread).expect(&format!("Party {} failed to read ready signal.", index));
}
if matches.opt_present("b") {
let skb = FSecp256Ord::from_slice(&[0xb75db4463a602ff0, 0x83b6a76e7fad1ec, 0xa33f33b8e9c84dbd, 0xb94fceb9fff7cfb2]);
let bob = mpecdsa::mpecdsa::ThresholdSigner::new(1, 2, &skb, &mut rng, &mut [Some(&mut streamrecv), None], &mut [Some(&mut streamsend), None]).unwrap();
println!("{} connected. Initializing...", index);
let signstart = PreciseTime::now();
for _ in 0..iters {
bob.sign(&[0], &msg, &mut rng, &mut streamrecv, &mut streamsend).unwrap();
}
let signend = PreciseTime::now();
println!("{} ms avg", (signstart.to(signend)/iters)*1000);
} else {
let ska = FSecp256Ord::from_slice(&[0xc93d9fa738a8b4b6, 0xe8dd5f4af65e7462, 0xcbdf97aeca50c5c4, 0x67498f7dcab40d3]);
let alice = mpecdsa::mpecdsa::ThresholdSigner::new(0, 2, &ska, &mut rng, &mut [None, Some(&mut streamrecv)], &mut [None, Some(&mut streamsend)]).unwrap();
let mut signer = mpecdsa::mpecdsa::ThresholdSigner::new(index, parties, &mut rng, sendvec.as_mut_slice(), recvvec.as_mut_slice()).unwrap();
let signstart = PreciseTime::now();
for _ in 0..iters {
alice.sign(&[1], &msg, &mut rng, &mut streamrecv, &mut streamsend).unwrap();
if index==parties-1 {
let mut sigread = [1u8; 1];
for ii in 0..parties-1 {
recvvec[ii].as_mut().unwrap().read_exact(&mut sigread).expect(&format!("Party {} failed to send ready signal.", ii));
}
let signend = PreciseTime::now();
println!("{} ms avg", (signstart.to(signend)/iters)*1000);
for ii in 0..parties-1 {
sendvec[ii].as_mut().unwrap().write(&[0]).expect(&format!("Party {} failed to send ready signal.", index));
sendvec[ii].as_mut().unwrap().flush().expect(&format!("Party {} failed to flush.", index));
}
} else {
let mut sigread = [1u8; 1];
sendvec[parties-1].as_mut().unwrap().write(&[0]).expect(&format!("Party {} failed to send ready signal.", index));
sendvec[parties-1].as_mut().unwrap().flush().expect(&format!("Party {} failed to flush.", index));
recvvec[parties-1].as_mut().unwrap().read_exact(&mut sigread).expect(&format!("Party {} failed to send ready signal.", parties-1));
}
println!("Performing {} Iteration Benchmark...", iters);
let setupstart = PreciseTime::now();
for _ in 0..iters {
signer.sign(&(0usize..index).chain((index+1)..(parties)).collect::<Vec<usize>>(), &"etaoin shrdlu".as_bytes(), &mut rng, &mut recvvec, &mut sendvec).unwrap();
}
let setupend = PreciseTime::now();
println!("{:.3} ms avg", (setupstart.to(setupend).num_milliseconds() as f64)/(iters as f64));
}
\ No newline at end of file
#include "../blake2/ref/blake2.h"
void blake2s_multi_raw(const unsigned char* buf, unsigned char* out, size_t count) {
size_t ii;
//#pragma omp parallel for
for (ii = 0; ii < count; ii++) {
blake2s(&out[32*ii], 32, &buf[64*ii], 64, 0, 0);
}
}
\ No newline at end of file
/***********
* This module implements Write and Read traits for Rust mpsc message channels. This is used in the test code for mpecdsa.rs.
* by Megan Chen
***********/
//! This module implements 'Write' and 'Read' traits for Rust message channels ('std::sync::mpsc'). The intended use case for this is testing network applications without using of TCP/IP.
//! 'ChannelWriter' implements the 'Write' trait for 'mpsc::Sender' and 'ChannelReader' implements the 'Read' trait for 'mpsc::Reader'.
//! We will refer to a corresponding 'ChannelWriter', 'ChannelReader' pair as a channelstream.
use std::sync::mpsc;
use std::io::prelude::*;
/// Writing half of a 'ChannelStream'. This contains a 'mpsc::Sender'. This can be cloned.
/// Messages can be sent with 'write'
#[derive(Clone)]
pub struct ChannelWriter {
inner: mpsc::Sender<Vec<u8>>
}
impl ChannelWriter {
/// Constructs a new 'ChannelWriter'.
///
/// # Example
///
/// '''
/// let (sender, receiver) = mpsc::channel();
/// let channelwriter = ChannelWriter::new(sender);
/// '''
fn new(sender: mpsc::Sender<Vec<u8>>) -> ChannelWriter {
ChannelWriter {
inner: sender
}
}
}
impl Write for ChannelWriter {
/// Attempts to write a message to the channelstream
fn write(&mut self, buf: &[u8]) -> Result<usize, ::std::io::Error> {
self.inner.send(buf.to_vec()).unwrap();
Ok(buf.len())
}
/// Does nothing. This was implemented to act fulfill the trait and interface with applications that require networking
fn flush(&mut self) -> Result<(), ::std::io::Error> { Ok(()) }
}
/// Reading half of a 'ChannelStream'. This contains a 'mpsc::Receiver'.
/// Messages can be read with 'read' or 'read_exact'
pub struct ChannelReader {
inner: mpsc::Receiver<Vec<u8>>,
read_buf: Vec<u8>,
}
impl ChannelReader {
/// Constructs a new 'ChannelReader'.
///
/// # Example
///
/// '''
/// let (sender, receiver) = mpsc::channel();
/// let channelreader = ChannelReader::new(receiver);
/// '''
fn new(recv: mpsc::Receiver<Vec<u8>>) -> ChannelReader {
ChannelReader {
inner: recv,
read_buf: Vec::new(),
}
}
}
impl Read for ChannelReader {
/// Reads all the values that have been sent by the 'ChannelWriter'
fn read(&mut self, buf: &mut [u8]) -> Result<usize, ::std::io::Error> {
let mut received_vec = self.inner.recv().unwrap();
let received_vals = &mut received_vec[..];
buf.clone_from_slice(&received_vals);