From aa2a3fe20145da34ebb63ca1c221541e5edde135 Mon Sep 17 00:00:00 2001 From: Stephen Akridge Date: Thu, 27 Sep 2018 10:48:40 -0700 Subject: [PATCH] Add chacha module to encrypt ledger files --- Cargo.toml | 6 +++ benches/chacha.rs | 29 ++++++++++++++ build.rs | 3 +- ci/test-stable-perf.sh | 2 +- fetch-perf-libs.sh | 2 +- src/bin/replicator.rs | 19 +++++++++ src/chacha.rs | 88 ++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + 8 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 benches/chacha.rs create mode 100644 src/chacha.rs diff --git a/Cargo.toml b/Cargo.toml index f3df85d57..f1b8875f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ name = "solana-drone" path = "src/bin/drone.rs" [[bin]] +required-features = ["chacha"] name = "solana-replicator" path = "src/bin/replicator.rs" @@ -70,6 +71,7 @@ ipv6 = [] cuda = [] erasure = [] test = [] +chacha = [] [dependencies] atty = "0.2" @@ -131,6 +133,10 @@ name = "signature" [[bench]] name = "sigverify" +[[bench]] +required-features = ["chacha"] +name = "chacha" + [workspace] members = [ ".", diff --git a/benches/chacha.rs b/benches/chacha.rs new file mode 100644 index 000000000..088acaf0e --- /dev/null +++ b/benches/chacha.rs @@ -0,0 +1,29 @@ +#![feature(test)] + +extern crate solana; +extern crate test; + +use solana::chacha::chacha_cbc_encrypt_files; +use std::fs::remove_file; +use std::fs::File; +use std::io::Write; +use std::path::Path; +use test::Bencher; + +#[bench] +fn bench_chacha_encrypt(bench: &mut Bencher) { + let in_path = Path::new("bench_chacha_encrypt_file_input.txt"); + let out_path = Path::new("bench_chacha_encrypt_file_output.txt.enc"); + { + let mut in_file = File::create(in_path).unwrap(); + for _ in 0..1024 { + in_file.write("123456foobar".as_bytes()).unwrap(); + } + } + bench.iter(move || { + chacha_cbc_encrypt_files(in_path, out_path, "thetestkey".to_string()).unwrap(); + }); + + remove_file(in_path).unwrap(); + remove_file(out_path).unwrap(); +} diff --git a/build.rs b/build.rs index 3c17f9fde..0516dd42c 100644 --- a/build.rs +++ b/build.rs @@ -16,8 +16,9 @@ fn main() { let cuda = !env::var("CARGO_FEATURE_CUDA").is_err(); let erasure = !env::var("CARGO_FEATURE_ERASURE").is_err(); + let chacha = !env::var("CARGO_FEATURE_CHACHA").is_err(); - if cuda || erasure { + if cuda || erasure || chacha { println!("cargo:rustc-link-search=native=target/perf-libs"); } if cuda { diff --git a/ci/test-stable-perf.sh b/ci/test-stable-perf.sh index 55c039ff0..50eaf200b 100755 --- a/ci/test-stable-perf.sh +++ b/ci/test-stable-perf.sh @@ -20,7 +20,7 @@ _() { "$@" } -_ cargo test --features=cuda,erasure +_ cargo test --features=cuda,erasure,chacha echo --- ci/localnet-sanity.sh ( diff --git a/fetch-perf-libs.sh b/fetch-perf-libs.sh index c8214871b..ec74534e5 100755 --- a/fetch-perf-libs.sh +++ b/fetch-perf-libs.sh @@ -15,7 +15,7 @@ mkdir -p target/perf-libs cd target/perf-libs ( set -x - curl https://solana-perf.s3.amazonaws.com/v0.9.0/x86_64-unknown-linux-gnu/solana-perf.tgz | tar zxvf - + curl https://solana-perf.s3.amazonaws.com/v0.9.1/x86_64-unknown-linux-gnu/solana-perf.tgz | tar zxvf - ) if [[ -r /usr/local/cuda/version.txt && -r cuda-version.txt ]]; then diff --git a/src/bin/replicator.rs b/src/bin/replicator.rs index f823bfeae..b0839f9f6 100644 --- a/src/bin/replicator.rs +++ b/src/bin/replicator.rs @@ -6,6 +6,7 @@ extern crate serde_json; extern crate solana; use clap::{App, Arg}; +use solana::chacha::chacha_cbc_encrypt_files; use solana::crdt::Node; use solana::fullnode::Config; use solana::logger; @@ -13,6 +14,7 @@ use solana::replicator::Replicator; use solana::signature::{Keypair, KeypairUtil}; use std::fs::File; use std::net::{Ipv4Addr, SocketAddr}; +use std::path::Path; use std::process::exit; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; @@ -21,6 +23,7 @@ use std::time::Duration; fn main() { logger::setup(); + let matches = App::new("replicator") .version(crate_version!()) .arg( @@ -102,5 +105,21 @@ fn main() { println!("Done downloading ledger"); + let ledger_path = Path::new(ledger_path.unwrap()); + let ledger_data_file = ledger_path.join("data"); + let ledger_data_file_encrypted = ledger_path.join("data.enc"); + let key = "abc123"; + + if let Err(e) = chacha_cbc_encrypt_files( + &ledger_data_file, + &ledger_data_file_encrypted, + key.to_string(), + ) { + println!("Error while encrypting ledger: {:?}", e); + return; + } + + println!("Done encrypting the ledger"); + replicator.join(); } diff --git a/src/chacha.rs b/src/chacha.rs new file mode 100644 index 000000000..a2e2bb1a2 --- /dev/null +++ b/src/chacha.rs @@ -0,0 +1,88 @@ +use std::fs::File; +use std::io; +use std::io::Read; +use std::io::Write; +use std::io::{BufReader, BufWriter}; +use std::path::Path; + +const CHACHA_IVEC_SIZE: usize = 64; + +#[link(name = "cpu-crypt")] +extern "C" { + fn chacha20_cbc_encrypt( + input: *const u8, + output: *mut u8, + in_len: usize, + key: *const u8, + ivec: *mut u8, + ); +} + +pub fn chacha_cbc_encrypt(input: &[u8], output: &mut [u8], key: &[u8], ivec: &mut [u8]) { + unsafe { + chacha20_cbc_encrypt( + input.as_ptr(), + output.as_mut_ptr(), + input.len(), + key.as_ptr(), + ivec.as_mut_ptr(), + ); + } +} + +pub fn chacha_cbc_encrypt_files(in_path: &Path, out_path: &Path, key: String) -> io::Result<()> { + let mut in_file = BufReader::new(File::open(in_path).expect("Can't open ledger data file")); + let mut out_file = + BufWriter::new(File::create(out_path).expect("Can't open ledger encrypted data file")); + let mut buffer = [0; 4 * 1024]; + let mut encrypted_buffer = [0; 4 * 1024]; + let mut ivec = [0; CHACHA_IVEC_SIZE]; + + while let Ok(size) = in_file.read(&mut buffer) { + info!("read {} bytes", size); + if size == 0 { + break; + } + chacha_cbc_encrypt( + &buffer[..size], + &mut encrypted_buffer[..size], + key.as_bytes(), + &mut ivec, + ); + if let Err(res) = out_file.write(&encrypted_buffer[..size]) { + println!("Error writing file! {:?}", res); + return Err(res); + } + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use chacha::chacha_cbc_encrypt_files; + use std::fs::remove_file; + use std::fs::File; + use std::io::Read; + use std::io::Write; + use std::path::Path; + + #[test] + fn test_encrypt_file() { + let in_path = Path::new("test_chacha_encrypt_file_input.txt"); + let out_path = Path::new("test_chacha_encrypt_file_output.txt.enc"); + { + let mut in_file = File::create(in_path).unwrap(); + in_file.write("123456foobar".as_bytes()).unwrap(); + } + assert!(chacha_cbc_encrypt_files(in_path, out_path, "thetestkey".to_string()).is_ok()); + let mut out_file = File::open(out_path).unwrap(); + let mut buf = vec![]; + let size = out_file.read_to_end(&mut buf).unwrap(); + assert_eq!( + buf[..size], + [106, 186, 59, 108, 165, 33, 118, 212, 70, 238, 205, 185] + ); + remove_file(in_path).unwrap(); + remove_file(out_path).unwrap(); + } +} diff --git a/src/lib.rs b/src/lib.rs index 97f44cabb..f97239fc1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,8 @@ pub mod broadcast_stage; pub mod budget; pub mod budget_instruction; pub mod budget_transaction; +#[cfg(feature = "chacha")] +pub mod chacha; pub mod choose_gossip_peer_strategy; pub mod client; #[macro_use]