Skip to content

Commit

Permalink
Merge pull request #28 from ebfull/hash-checks-of-params
Browse files Browse the repository at this point in the history
Hash checks of parameter files during initialization
  • Loading branch information
ebfull authored Aug 2, 2018
2 parents f55a654 + 48c2d3c commit f5d2afb
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 5 deletions.
5 changes: 4 additions & 1 deletion include/librustzcash.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ extern "C" {
/// paths as necessary. Only called once.
void librustzcash_init_zksnark_params(
const char* spend_path,
const char* spend_hash,
const char* output_path,
const char* sprout_path
const char* output_hash,
const char* sprout_path,
const char* sprout_hash
);

/// Validates the provided Equihash solution against
Expand Down
42 changes: 42 additions & 0 deletions src/hashreader.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use blake2_rfc::blake2b::Blake2b;
use std::io::{self, Read};

/// Abstraction over a reader which hashes the data being read.
pub struct HashReader<R: Read> {
reader: R,
hasher: Blake2b,
}

impl<R: Read> HashReader<R> {
/// Construct a new `HashReader` given an existing `reader` by value.
pub fn new(reader: R) -> Self {
HashReader {
reader: reader,
hasher: Blake2b::new(64),
}
}

/// Destroy this reader and return the hash of what was read.
pub fn into_hash(self) -> String {
let hash = self.hasher.finalize();

let mut s = String::new();
for c in hash.as_bytes().iter() {
s += &format!("{:02x}", c);
}

s
}
}

impl<R: Read> Read for HashReader<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let bytes = self.reader.read(buf)?;

if bytes > 0 {
self.hasher.update(&buf[0..bytes]);
}

Ok(bytes)
}
}
60 changes: 56 additions & 4 deletions src/rustzcash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ extern crate pairing;
extern crate rand;
extern crate sapling_crypto;

mod hashreader;

#[macro_use]
extern crate lazy_static;

Expand Down Expand Up @@ -36,7 +38,7 @@ use blake2_rfc::blake2s::Blake2s;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

use rand::{OsRng, Rand, Rng};
use std::io::BufReader;
use std::io::{self, BufReader};

use libc::{c_char, c_uchar, int64_t, size_t, uint32_t, uint64_t};
use std::ffi::CStr;
Expand Down Expand Up @@ -110,12 +112,30 @@ fn fixed_scalar_mult(from: &[u8], p_g: FixedGenerators) -> edwards::Point<Bls12,
#[no_mangle]
pub extern "system" fn librustzcash_init_zksnark_params(
spend_path: *const c_char,
spend_hash: *const c_char,
output_path: *const c_char,
output_hash: *const c_char,
sprout_path: *const c_char,
sprout_hash: *const c_char,
) {
// Initialize jubjub parameters here
lazy_static::initialize(&JUBJUB);

let spend_hash = unsafe { CStr::from_ptr(spend_hash) }
.to_str()
.expect("hash should be a valid string")
.to_string();

let output_hash = unsafe { CStr::from_ptr(output_hash) }
.to_str()
.expect("hash should be a valid string")
.to_string();

let sprout_hash = unsafe { CStr::from_ptr(sprout_hash) }
.to_str()
.expect("hash should be a valid string")
.to_string();

// These should be valid CStr's, but the decoding may fail on Windows
// so we may need to use OSStr or something.
let spend_path = unsafe { CStr::from_ptr(spend_path) }
Expand All @@ -132,20 +152,52 @@ pub extern "system" fn librustzcash_init_zksnark_params(
.to_string();

// Load from each of the paths
let mut spend_fs = File::open(spend_path).expect("couldn't load Sapling spend parameters file");
let spend_fs = File::open(spend_path).expect("couldn't load Sapling spend parameters file");
let output_fs = File::open(output_path).expect("couldn't load Sapling output parameters file");
let sprout_fs = File::open(&sprout_path).expect("couldn't load Sprout groth16 parameters file");

let mut spend_fs = hashreader::HashReader::new(BufReader::with_capacity(1024 * 1024, spend_fs));
let mut output_fs =
File::open(output_path).expect("couldn't load Sapling output parameters file");
hashreader::HashReader::new(BufReader::with_capacity(1024 * 1024, output_fs));
let mut sprout_fs =
File::open(&sprout_path).expect("couldn't load Sprout groth16 parameters file");
hashreader::HashReader::new(BufReader::with_capacity(1024 * 1024, sprout_fs));

// Deserialize params
let spend_params = Parameters::<Bls12>::read(&mut spend_fs, false)
.expect("couldn't deserialize Sapling spend parameters file");
let output_params = Parameters::<Bls12>::read(&mut output_fs, false)
.expect("couldn't deserialize Sapling spend parameters file");

// We only deserialize the verifying key for the Sprout parameters, which
// appears at the beginning of the parameter file. The rest is loaded
// during proving time.
let sprout_vk = VerifyingKey::<Bls12>::read(&mut sprout_fs)
.expect("couldn't deserialize Sprout Groth16 verifying key");

// There is extra stuff (the transcript) at the end of the parameter file which is
// used to verify the parameter validity, but we're not interested in that. We do
// want to read it, though, so that the BLAKE2b computed afterward is consistent
// with `b2sum` on the files.
let mut sink = io::sink();
io::copy(&mut spend_fs, &mut sink)
.expect("couldn't finish reading Sapling spend parameter file");
io::copy(&mut output_fs, &mut sink)
.expect("couldn't finish reading Sapling output parameter file");
io::copy(&mut sprout_fs, &mut sink)
.expect("couldn't finish reading Sprout groth16 parameter file");

if spend_fs.into_hash() != spend_hash {
panic!("Sapling spend parameter file is not correct, please clean your `~/.zcash-params/` and re-run `fetch-params`.");
}

if output_fs.into_hash() != output_hash {
panic!("Sapling output parameter file is not correct, please clean your `~/.zcash-params/` and re-run `fetch-params`.");
}

if sprout_fs.into_hash() != sprout_hash {
panic!("Sprout groth16 parameter file is not correct, please clean your `~/.zcash-params/` and re-run `fetch-params`.");
}

// Prepare verifying keys
let spend_vk = prepare_verifying_key(&spend_params.vk);
let output_vk = prepare_verifying_key(&output_params.vk);
Expand Down

0 comments on commit f5d2afb

Please sign in to comment.