From 999dcbfcab0171678824f775bdfad87d7592cea0 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 4 Jun 2019 13:15:12 +0100 Subject: [PATCH] Migrate to blake2b_simd and blake2s_simd crates The primary reason for migrating is that these crates provide APIs for setting the personalisation string. This enables us to depend solely on published crates, and thus publish our own crates. The SIMD implementations are ported from libsodium. Closes #67. --- Cargo.lock | 43 ++++++--- librustzcash/Cargo.toml | 6 +- librustzcash/src/equihash.rs | 15 +-- librustzcash/src/rustzcash.rs | 10 +- sapling-crypto/Cargo.toml | 6 +- sapling-crypto/src/circuit/blake2s.rs | 4 +- sapling-crypto/src/circuit/test/mod.rs | 6 +- sapling-crypto/src/group_hash.rs | 16 ++-- sapling-crypto/src/lib.rs | 3 +- sapling-crypto/src/primitives/mod.rs | 21 ++-- sapling-crypto/src/util.rs | 4 +- zcash_primitives/Cargo.toml | 5 +- zcash_primitives/src/keys.rs | 13 ++- zcash_primitives/src/lib.rs | 2 +- zcash_primitives/src/note_encryption.rs | 20 ++-- zcash_primitives/src/transaction/sighash.rs | 100 +++++++++++--------- zcash_primitives/src/zip32.rs | 14 ++- zcash_proofs/Cargo.toml | 5 +- zcash_proofs/src/hashreader.rs | 6 +- zcash_proofs/src/lib.rs | 2 +- 20 files changed, 172 insertions(+), 129 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34b20d28e..ab8b62829 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,9 +30,14 @@ dependencies = [ "stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayref" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayvec" -version = "0.4.7" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -70,12 +75,22 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "blake2-rfc" -version = "0.2.18" -source = "git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9#7a5b5fc99ae483a0043db7547fb79a6fa44b88a9" +name = "blake2b_simd" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "blake2s_simd" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -292,7 +307,8 @@ name = "librustzcash" version = "0.1.0" dependencies = [ "bellman 0.1.0", - "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", + "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2s_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -435,7 +451,8 @@ name = "sapling-crypto" version = "0.0.1" dependencies = [ "bellman 0.1.0", - "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", + "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2s_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", @@ -529,7 +546,7 @@ name = "zcash_primitives" version = "0.0.0" dependencies = [ "aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", + "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "crypto_api_chachapoly 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", @@ -547,7 +564,7 @@ name = "zcash_proofs" version = "0.0.0" dependencies = [ "bellman 0.1.0", - "blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)", + "blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ff 0.4.0", "pairing 0.14.2", @@ -559,11 +576,13 @@ dependencies = [ "checksum aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6fb1737cdc8da3db76e90ca817a194249a38fcb500c2e6ecec39b29448aa873" "checksum aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67cc03b0a090a05cb01e96998a01905d7ceedce1bc23b756c0bb7faa0682ccb1" "checksum aesni 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6810b7fb9f2bb4f76f05ac1c170b8dde285b6308955dc3afd89710268c958d9e" -"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum bech32 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58946044516aa9dc922182e0d6e9d124a31aafe6b421614654eb27cf90cec09c" "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" -"checksum blake2-rfc 0.2.18 (git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9)" = "" +"checksum blake2b_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d909f9ef55928e57e7de9638828bc9407233b5cb0904066a7edebbaa9946db2f" +"checksum blake2s_simd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fa20660ff9f1e6d0a05444b5ebbbae13e4c018d4c66cc78c7e421e3396358a52" "checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d" "checksum block-cipher-trait 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "370424437b9459f3dfd68428ed9376ddfe03d8b70ede29cc533b3557df186ab4" "checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3" diff --git a/librustzcash/Cargo.toml b/librustzcash/Cargo.toml index 3edc928e9..e75a71c04 100644 --- a/librustzcash/Cargo.toml +++ b/librustzcash/Cargo.toml @@ -15,6 +15,8 @@ crate-type = ["staticlib"] [dependencies] bellman = { path = "../bellman" } +blake2b_simd = "0.5" +blake2s_simd = "0.5" ff = { path = "../ff" } libc = "0.2" pairing = { path = "../pairing" } @@ -24,7 +26,3 @@ rand = "0.4" sapling-crypto = { path = "../sapling-crypto" } zcash_primitives = { path = "../zcash_primitives" } zcash_proofs = { path = "../zcash_proofs" } - -[dependencies.blake2-rfc] -git = "https://github.com/gtank/blake2-rfc" -rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9" diff --git a/librustzcash/src/equihash.rs b/librustzcash/src/equihash.rs index da2693bc5..d251bc193 100644 --- a/librustzcash/src/equihash.rs +++ b/librustzcash/src/equihash.rs @@ -1,4 +1,4 @@ -use blake2_rfc::blake2b::{Blake2b, Blake2bResult}; +use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams, State as Blake2bState}; use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt}; use std::io::Cursor; use std::mem::size_of; @@ -33,7 +33,7 @@ impl Params { } impl Node { - fn new(p: &Params, state: &Blake2b, i: u32) -> Self { + fn new(p: &Params, state: &Blake2bState, i: u32) -> Self { let hash = generate_hash(state, i / p.indices_per_hash_output()); let start = ((i % p.indices_per_hash_output()) * p.n / 8) as usize; let end = start + (p.n as usize) / 8; @@ -99,15 +99,18 @@ impl Node { } } -fn initialise_state(n: u32, k: u32, digest_len: u8) -> Blake2b { +fn initialise_state(n: u32, k: u32, digest_len: u8) -> Blake2bState { let mut personalization: Vec = Vec::from("ZcashPoW"); personalization.write_u32::(n).unwrap(); personalization.write_u32::(k).unwrap(); - Blake2b::with_params(digest_len as usize, &[], &[], &personalization) + Blake2bParams::new() + .hash_length(digest_len as usize) + .personal(&personalization) + .to_state() } -fn generate_hash(base_state: &Blake2b, i: u32) -> Blake2bResult { +fn generate_hash(base_state: &Blake2bState, i: u32) -> Blake2bHash { let mut lei = [0u8; 4]; (&mut lei[..]).write_u32::(i).unwrap(); @@ -249,7 +252,7 @@ pub fn is_valid_solution_iterative( return rows[0].is_zero(hash_len); } -fn tree_validator(p: &Params, state: &Blake2b, indices: &[u32]) -> Option { +fn tree_validator(p: &Params, state: &Blake2bState, indices: &[u32]) -> Option { if indices.len() > 1 { let end = indices.len(); let mid = end / 2; diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index fb728270c..51a980e81 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -1,5 +1,6 @@ extern crate bellman; -extern crate blake2_rfc; +extern crate blake2b_simd; +extern crate blake2s_simd; extern crate byteorder; extern crate ff; extern crate libc; @@ -33,7 +34,7 @@ use bellman::groth16::{ create_random_proof, verify_proof, Parameters, PreparedVerifyingKey, Proof, }; -use blake2_rfc::blake2s::Blake2s; +use blake2s_simd::Params as Blake2sParams; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; @@ -336,7 +337,10 @@ pub extern "system" fn librustzcash_crh_ivk( let ak = unsafe { &*ak }; let nk = unsafe { &*nk }; - let mut h = Blake2s::with_params(32, &[], &[], CRH_IVK_PERSONALIZATION); + let mut h = Blake2sParams::new() + .hash_length(32) + .personal(CRH_IVK_PERSONALIZATION) + .to_state(); h.update(ak); h.update(nk); let mut h = h.finalize().as_ref().to_vec(); diff --git a/sapling-crypto/Cargo.toml b/sapling-crypto/Cargo.toml index d98521918..7d4377450 100644 --- a/sapling-crypto/Cargo.toml +++ b/sapling-crypto/Cargo.toml @@ -14,15 +14,13 @@ features = ["expose-arith"] [dependencies] bellman = { path = "../bellman" } +blake2b_simd = "0.5" +blake2s_simd = "0.5" ff = { path = "../ff" } rand = "0.4" digest = "0.7" byteorder = "1" -[dependencies.blake2-rfc] -git = "https://github.com/gtank/blake2-rfc" -rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9" - [dev-dependencies] hex-literal = "0.1" rust-crypto = "0.2" diff --git a/sapling-crypto/src/circuit/blake2s.rs b/sapling-crypto/src/circuit/blake2s.rs index 93af8069c..46bbe6763 100644 --- a/sapling-crypto/src/circuit/blake2s.rs +++ b/sapling-crypto/src/circuit/blake2s.rs @@ -320,13 +320,13 @@ pub fn blake2s>( #[cfg(test)] mod test { + use blake2s_simd::Params as Blake2sParams; use rand::{XorShiftRng, SeedableRng, Rng}; use pairing::bls12_381::{Bls12}; use ::circuit::boolean::{Boolean, AllocatedBit}; use ::circuit::test::TestConstraintSystem; use super::blake2s; use bellman::{ConstraintSystem}; - use blake2_rfc::blake2s::Blake2s; #[test] fn test_blank_hash() { @@ -392,7 +392,7 @@ mod test { for input_len in (0..32).chain((32..256).filter(|a| a % 8 == 0)) { - let mut h = Blake2s::with_params(32, &[], &[], b"12345678"); + let mut h = Blake2sParams::new().hash_length(32).personal(b"12345678").to_state(); let data: Vec = (0..input_len).map(|_| rng.gen()).collect(); diff --git a/sapling-crypto/src/circuit/test/mod.rs b/sapling-crypto/src/circuit/test/mod.rs index 18a77ba4a..79d128a53 100644 --- a/sapling-crypto/src/circuit/test/mod.rs +++ b/sapling-crypto/src/circuit/test/mod.rs @@ -16,7 +16,7 @@ use byteorder::{BigEndian, ByteOrder}; use std::cmp::Ordering; use std::collections::BTreeMap; -use blake2_rfc::blake2s::Blake2s; +use blake2s_simd::{Params as Blake2sParams, State as Blake2sState}; #[derive(Debug)] enum NamedObject { @@ -96,7 +96,7 @@ fn proc_lc( fn hash_lc( terms: &[(Variable, E::Fr)], - h: &mut Blake2s + h: &mut Blake2sState ) { let map = proc_lc::(terms); @@ -226,7 +226,7 @@ impl TestConstraintSystem { } pub fn hash(&self) -> String { - let mut h = Blake2s::new(32); + let mut h = Blake2sParams::new().hash_length(32).to_state(); { let mut buf = [0u8; 24]; diff --git a/sapling-crypto/src/group_hash.rs b/sapling-crypto/src/group_hash.rs index 43e87e8fe..7369e0473 100644 --- a/sapling-crypto/src/group_hash.rs +++ b/sapling-crypto/src/group_hash.rs @@ -8,7 +8,7 @@ use ff::{ PrimeField }; -use blake2_rfc::blake2s::Blake2s; +use blake2s_simd::Params; use constants; /// Produces a random point in the Jubjub curve. @@ -25,13 +25,15 @@ pub fn group_hash( // Check to see that scalar field is 255 bits assert!(E::Fr::NUM_BITS == 255); - let mut h = Blake2s::with_params(32, &[], &[], personalization); - h.update(constants::GH_FIRST_BLOCK); - h.update(tag); - let h = h.finalize().as_ref().to_vec(); - assert!(h.len() == 32); + let h = Params::new() + .hash_length(32) + .personal(personalization) + .to_state() + .update(constants::GH_FIRST_BLOCK) + .update(tag) + .finalize(); - match edwards::Point::::read(&h[..], params) { + match edwards::Point::::read(h.as_ref(), params) { Ok(p) => { let p = p.mul_by_cofactor(params); diff --git a/sapling-crypto/src/lib.rs b/sapling-crypto/src/lib.rs index ae3757361..0535d9a2b 100644 --- a/sapling-crypto/src/lib.rs +++ b/sapling-crypto/src/lib.rs @@ -1,6 +1,7 @@ extern crate pairing; extern crate bellman; -extern crate blake2_rfc; +extern crate blake2b_simd; +extern crate blake2s_simd; extern crate digest; extern crate ff; extern crate rand; diff --git a/sapling-crypto/src/primitives/mod.rs b/sapling-crypto/src/primitives/mod.rs index fea332c9c..4026392cd 100644 --- a/sapling-crypto/src/primitives/mod.rs +++ b/sapling-crypto/src/primitives/mod.rs @@ -22,7 +22,7 @@ use jubjub::{ FixedGenerators }; -use blake2_rfc::blake2s::Blake2s; +use blake2s_simd::Params as Blake2sParams; #[derive(Clone)] pub struct ValueCommitment { @@ -87,9 +87,12 @@ impl ViewingKey { self.ak.write(&mut preimage[0..32]).unwrap(); self.nk.write(&mut preimage[32..64]).unwrap(); - let mut h = Blake2s::with_params(32, &[], &[], constants::CRH_IVK_PERSONALIZATION); - h.update(&preimage); - let mut h = h.finalize().as_ref().to_vec(); + let mut h = [0; 32]; + h.copy_from_slice(Blake2sParams::new() + .hash_length(32) + .personal(constants::CRH_IVK_PERSONALIZATION) + .hash(&preimage) + .as_bytes()); // Drop the most significant five bits, so it can be interpreted as a scalar. h[31] &= 0b0000_0111; @@ -255,10 +258,12 @@ impl Note { let mut nf_preimage = [0u8; 64]; viewing_key.nk.write(&mut nf_preimage[0..32]).unwrap(); rho.write(&mut nf_preimage[32..64]).unwrap(); - let mut h = Blake2s::with_params(32, &[], &[], constants::PRF_NF_PERSONALIZATION); - h.update(&nf_preimage); - - h.finalize().as_ref().to_vec() + Blake2sParams::new() + .hash_length(32) + .personal(constants::PRF_NF_PERSONALIZATION) + .hash(&nf_preimage) + .as_bytes() + .to_vec() } /// Computes the note commitment diff --git a/sapling-crypto/src/util.rs b/sapling-crypto/src/util.rs index e67e66089..1e759ba73 100644 --- a/sapling-crypto/src/util.rs +++ b/sapling-crypto/src/util.rs @@ -1,9 +1,9 @@ -use blake2_rfc::blake2b::Blake2b; +use blake2b_simd::Params; use jubjub::{JubjubEngine, ToUniform}; pub fn hash_to_scalar(persona: &[u8], a: &[u8], b: &[u8]) -> E::Fs { - let mut hasher = Blake2b::with_params(64, &[], &[], persona); + let mut hasher = Params::new().hash_length(64).personal(persona).to_state(); hasher.update(a); hasher.update(b); let ret = hasher.finalize(); diff --git a/zcash_primitives/Cargo.toml b/zcash_primitives/Cargo.toml index 06a117b37..771f35118 100644 --- a/zcash_primitives/Cargo.toml +++ b/zcash_primitives/Cargo.toml @@ -7,6 +7,7 @@ authors = [ [dependencies] aes = "0.2" +blake2b_simd = "0.5" byteorder = "1" crypto_api_chachapoly = "0.1" ff = { path = "../ff" } @@ -17,7 +18,3 @@ pairing = { path = "../pairing" } rand = "0.4" sapling-crypto = { path = "../sapling-crypto" } sha2 = "0.8" - -[dependencies.blake2-rfc] -git = "https://github.com/gtank/blake2-rfc" -rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9" diff --git a/zcash_primitives/src/keys.rs b/zcash_primitives/src/keys.rs index e6066e3ee..fca31ed24 100644 --- a/zcash_primitives/src/keys.rs +++ b/zcash_primitives/src/keys.rs @@ -2,7 +2,7 @@ //! //! Implements section 4.2.2 of the Zcash Protocol Specification. -use blake2_rfc::blake2b::{Blake2b, Blake2bResult}; +use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams}; use ff::{PrimeField, PrimeFieldRepr}; use sapling_crypto::{ jubjub::{edwards, FixedGenerators, JubjubEngine, JubjubParams, ToUniform, Unknown}, @@ -13,12 +13,15 @@ use std::io::{self, Read, Write}; pub const PRF_EXPAND_PERSONALIZATION: &'static [u8; 16] = b"Zcash_ExpandSeed"; /// PRF^expand(sk, t) := BLAKE2b-512("Zcash_ExpandSeed", sk || t) -pub fn prf_expand(sk: &[u8], t: &[u8]) -> Blake2bResult { - prf_expand_vec(sk, &[t]) +pub fn prf_expand(sk: &[u8], t: &[u8]) -> Blake2bHash { + prf_expand_vec(sk, &vec![t]) } -pub fn prf_expand_vec(sk: &[u8], ts: &[&[u8]]) -> Blake2bResult { - let mut h = Blake2b::with_params(64, &[], &[], PRF_EXPAND_PERSONALIZATION); +pub fn prf_expand_vec(sk: &[u8], ts: &[&[u8]]) -> Blake2bHash { + let mut h = Blake2bParams::new() + .hash_length(64) + .personal(PRF_EXPAND_PERSONALIZATION) + .to_state(); h.update(sk); for t in ts { h.update(t); diff --git a/zcash_primitives/src/lib.rs b/zcash_primitives/src/lib.rs index 962811ebf..eb33461a8 100644 --- a/zcash_primitives/src/lib.rs +++ b/zcash_primitives/src/lib.rs @@ -2,7 +2,7 @@ extern crate lazy_static; extern crate aes; -extern crate blake2_rfc; +extern crate blake2b_simd; extern crate byteorder; extern crate crypto_api_chachapoly; extern crate ff; diff --git a/zcash_primitives/src/note_encryption.rs b/zcash_primitives/src/note_encryption.rs index 3d1c55bef..610b746fe 100644 --- a/zcash_primitives/src/note_encryption.rs +++ b/zcash_primitives/src/note_encryption.rs @@ -1,6 +1,6 @@ //! Implementation of in-band secret distribution for Zcash transactions. -use blake2_rfc::blake2b::{Blake2b, Blake2bResult}; +use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use crypto_api_chachapoly::{ChaCha20Ietf, ChachaPolyIetf}; use ff::{PrimeField, PrimeFieldRepr}; @@ -168,14 +168,15 @@ where fn kdf_sapling( dhsecret: edwards::Point, epk: &edwards::Point, -) -> Blake2bResult { +) -> Blake2bHash { let mut input = [0u8; 64]; dhsecret.write(&mut input[0..32]).unwrap(); epk.write(&mut input[32..64]).unwrap(); - let mut h = Blake2b::with_params(32, &[], &[], KDF_SAPLING_PERSONALIZATION); - h.update(&input); - h.finalize() + Blake2bParams::new() + .hash_length(32) + .personal(KDF_SAPLING_PERSONALIZATION) + .hash(&input) } /// Sapling PRF^ock. @@ -186,16 +187,17 @@ fn prf_ock( cv: &edwards::Point, cmu: &Fr, epk: &edwards::Point, -) -> Blake2bResult { +) -> Blake2bHash { let mut ock_input = [0u8; 128]; ock_input[0..32].copy_from_slice(&ovk.0); cv.write(&mut ock_input[32..64]).unwrap(); cmu.into_repr().write_le(&mut ock_input[64..96]).unwrap(); epk.write(&mut ock_input[96..128]).unwrap(); - let mut h = Blake2b::with_params(32, &[], &[], PRF_OCK_PERSONALIZATION); - h.update(&ock_input); - h.finalize() + Blake2bParams::new() + .hash_length(32) + .personal(PRF_OCK_PERSONALIZATION) + .hash(&ock_input) } /// An API for encrypting Sapling notes. diff --git a/zcash_primitives/src/transaction/sighash.rs b/zcash_primitives/src/transaction/sighash.rs index 85302ee0a..774e7b472 100644 --- a/zcash_primitives/src/transaction/sighash.rs +++ b/zcash_primitives/src/transaction/sighash.rs @@ -1,4 +1,4 @@ -use blake2_rfc::blake2b::Blake2b; +use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams}; use byteorder::{LittleEndian, WriteBytesExt}; use ff::{PrimeField, PrimeFieldRepr}; @@ -39,7 +39,7 @@ macro_rules! update_i64 { macro_rules! update_hash { ($h:expr, $cond:expr, $value:expr) => { if $cond { - $h.update(&$value); + $h.update(&$value.as_ref()); } else { $h.update(&[0; 32]); } @@ -67,47 +67,51 @@ impl SigHashVersion { } } -fn prevout_hash(tx: &TransactionData) -> Vec { +fn prevout_hash(tx: &TransactionData) -> Blake2bHash { let mut data = Vec::with_capacity(tx.vin.len() * 36); for t_in in &tx.vin { t_in.prevout.write(&mut data).unwrap(); } - let mut h = Blake2b::with_params(32, &[], &[], ZCASH_PREVOUTS_HASH_PERSONALIZATION); - h.update(&data); - h.finalize().as_ref().to_vec() + Blake2bParams::new() + .hash_length(32) + .personal(ZCASH_PREVOUTS_HASH_PERSONALIZATION) + .hash(&data) } -fn sequence_hash(tx: &TransactionData) -> Vec { +fn sequence_hash(tx: &TransactionData) -> Blake2bHash { let mut data = Vec::with_capacity(tx.vin.len() * 4); for t_in in &tx.vin { (&mut data) .write_u32::(t_in.sequence) .unwrap(); } - let mut h = Blake2b::with_params(32, &[], &[], ZCASH_SEQUENCE_HASH_PERSONALIZATION); - h.update(&data); - h.finalize().as_ref().to_vec() + Blake2bParams::new() + .hash_length(32) + .personal(ZCASH_SEQUENCE_HASH_PERSONALIZATION) + .hash(&data) } -fn outputs_hash(tx: &TransactionData) -> Vec { +fn outputs_hash(tx: &TransactionData) -> Blake2bHash { let mut data = Vec::with_capacity(tx.vout.len() * (4 + 1)); for t_out in &tx.vout { t_out.write(&mut data).unwrap(); } - let mut h = Blake2b::with_params(32, &[], &[], ZCASH_OUTPUTS_HASH_PERSONALIZATION); - h.update(&data); - h.finalize().as_ref().to_vec() + Blake2bParams::new() + .hash_length(32) + .personal(ZCASH_OUTPUTS_HASH_PERSONALIZATION) + .hash(&data) } -fn single_output_hash(tx_out: &TxOut) -> Vec { +fn single_output_hash(tx_out: &TxOut) -> Blake2bHash { let mut data = vec![]; tx_out.write(&mut data).unwrap(); - let mut h = Blake2b::with_params(32, &[], &[], ZCASH_OUTPUTS_HASH_PERSONALIZATION); - h.update(&data); - h.finalize().as_ref().to_vec() + Blake2bParams::new() + .hash_length(32) + .personal(ZCASH_OUTPUTS_HASH_PERSONALIZATION) + .hash(&data) } -fn joinsplits_hash(tx: &TransactionData) -> Vec { +fn joinsplits_hash(tx: &TransactionData) -> Blake2bHash { let mut data = Vec::with_capacity( tx.joinsplits.len() * if tx.version < SAPLING_TX_VERSION { @@ -120,12 +124,13 @@ fn joinsplits_hash(tx: &TransactionData) -> Vec { js.write(&mut data).unwrap(); } data.extend_from_slice(&tx.joinsplit_pubkey.unwrap()); - let mut h = Blake2b::with_params(32, &[], &[], ZCASH_JOINSPLITS_HASH_PERSONALIZATION); - h.update(&data); - h.finalize().as_ref().to_vec() + Blake2bParams::new() + .hash_length(32) + .personal(ZCASH_JOINSPLITS_HASH_PERSONALIZATION) + .hash(&data) } -fn shielded_spends_hash(tx: &TransactionData) -> Vec { +fn shielded_spends_hash(tx: &TransactionData) -> Blake2bHash { let mut data = Vec::with_capacity(tx.shielded_spends.len() * 384); for s_spend in &tx.shielded_spends { s_spend.cv.write(&mut data).unwrap(); @@ -134,19 +139,21 @@ fn shielded_spends_hash(tx: &TransactionData) -> Vec { s_spend.rk.write(&mut data).unwrap(); data.extend_from_slice(&s_spend.zkproof); } - let mut h = Blake2b::with_params(32, &[], &[], ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION); - h.update(&data); - h.finalize().as_ref().to_vec() + Blake2bParams::new() + .hash_length(32) + .personal(ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION) + .hash(&data) } -fn shielded_outputs_hash(tx: &TransactionData) -> Vec { +fn shielded_outputs_hash(tx: &TransactionData) -> Blake2bHash { let mut data = Vec::with_capacity(tx.shielded_outputs.len() * 948); for s_out in &tx.shielded_outputs { s_out.write(&mut data).unwrap(); } - let mut h = Blake2b::with_params(32, &[], &[], ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION); - h.update(&data); - h.finalize().as_ref().to_vec() + Blake2bParams::new() + .hash_length(32) + .personal(ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION) + .hash(&data) } pub fn signature_hash_data( @@ -158,26 +165,16 @@ pub fn signature_hash_data( let sigversion = SigHashVersion::from_tx(tx); match sigversion { SigHashVersion::Overwinter | SigHashVersion::Sapling => { - let hash_outputs = if (hash_type & SIGHASH_MASK) != SIGHASH_SINGLE - && (hash_type & SIGHASH_MASK) != SIGHASH_NONE - { - outputs_hash(tx) - } else if (hash_type & SIGHASH_MASK) == SIGHASH_SINGLE - && transparent_input.is_some() - && transparent_input.as_ref().unwrap().0 < tx.vout.len() - { - single_output_hash(&tx.vout[transparent_input.as_ref().unwrap().0]) - } else { - vec![0; 32] - }; - let mut personal = [0; 16]; (&mut personal[..12]).copy_from_slice(ZCASH_SIGHASH_PERSONALIZATION_PREFIX); (&mut personal[12..]) .write_u32::(consensus_branch_id) .unwrap(); - let mut h = Blake2b::with_params(32, &[], &[], &personal); + let mut h = Blake2bParams::new() + .hash_length(32) + .personal(&personal) + .to_state(); let mut tmp = [0; 8]; update_u32!(h, tx.header(), tmp); @@ -190,7 +187,20 @@ pub fn signature_hash_data( && (hash_type & SIGHASH_MASK) != SIGHASH_NONE, sequence_hash(tx) ); - h.update(&hash_outputs); + if (hash_type & SIGHASH_MASK) != SIGHASH_SINGLE + && (hash_type & SIGHASH_MASK) != SIGHASH_NONE + { + h.update(outputs_hash(tx).as_ref()); + } else if (hash_type & SIGHASH_MASK) == SIGHASH_SINGLE + && transparent_input.is_some() + && transparent_input.as_ref().unwrap().0 < tx.vout.len() + { + h.update( + single_output_hash(&tx.vout[transparent_input.as_ref().unwrap().0]).as_ref(), + ); + } else { + h.update(&[0; 32]); + }; update_hash!(h, !tx.joinsplits.is_empty(), joinsplits_hash(tx)); if sigversion == SigHashVersion::Sapling { update_hash!(h, !tx.shielded_spends.is_empty(), shielded_spends_hash(tx)); diff --git a/zcash_primitives/src/zip32.rs b/zcash_primitives/src/zip32.rs index db5adcda9..a34ae1837 100644 --- a/zcash_primitives/src/zip32.rs +++ b/zcash_primitives/src/zip32.rs @@ -1,5 +1,5 @@ use aes::Aes256; -use blake2_rfc::blake2b::Blake2b; +use blake2b_simd::Params as Blake2bParams; use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt}; use ff::Field; use fpe::ff1::{BinaryNumeralString, FF1}; @@ -33,7 +33,10 @@ struct FVKFingerprint([u8; 32]); impl From<&FullViewingKey> for FVKFingerprint { fn from(fvk: &FullViewingKey) -> Self { - let mut h = Blake2b::with_params(32, &[], &[], ZIP32_SAPLING_FVFP_PERSONALIZATION); + let mut h = Blake2bParams::new() + .hash_length(32) + .personal(ZIP32_SAPLING_FVFP_PERSONALIZATION) + .to_state(); h.update(&fvk.to_bytes()); let mut fvfp = [0u8; 32]; fvfp.copy_from_slice(h.finalize().as_bytes()); @@ -225,9 +228,10 @@ impl std::fmt::Debug for ExtendedFullViewingKey { impl ExtendedSpendingKey { pub fn master(seed: &[u8]) -> Self { - let mut h = Blake2b::with_params(64, &[], &[], ZIP32_SAPLING_MASTER_PERSONALIZATION); - h.update(seed); - let i = h.finalize(); + let i = Blake2bParams::new() + .hash_length(64) + .personal(ZIP32_SAPLING_MASTER_PERSONALIZATION) + .hash(seed); let sk_m = &i.as_bytes()[..32]; let mut c_m = [0u8; 32]; diff --git a/zcash_proofs/Cargo.toml b/zcash_proofs/Cargo.toml index 5bcdb2663..2139749ae 100644 --- a/zcash_proofs/Cargo.toml +++ b/zcash_proofs/Cargo.toml @@ -7,12 +7,9 @@ authors = [ [dependencies] bellman = { path = "../bellman" } +blake2b_simd = "0.5" byteorder = "1" ff = { path = "../ff" } pairing = { path = "../pairing" } rand = "0.4" sapling-crypto = { path = "../sapling-crypto" } - -[dependencies.blake2-rfc] -git = "https://github.com/gtank/blake2-rfc" -rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9" diff --git a/zcash_proofs/src/hashreader.rs b/zcash_proofs/src/hashreader.rs index a422d5203..dbe686ff6 100644 --- a/zcash_proofs/src/hashreader.rs +++ b/zcash_proofs/src/hashreader.rs @@ -1,10 +1,10 @@ -use blake2_rfc::blake2b::Blake2b; +use blake2b_simd::State; use std::io::{self, Read}; /// Abstraction over a reader which hashes the data being read. pub struct HashReader { reader: R, - hasher: Blake2b, + hasher: State, } impl HashReader { @@ -12,7 +12,7 @@ impl HashReader { pub fn new(reader: R) -> Self { HashReader { reader: reader, - hasher: Blake2b::new(64), + hasher: State::new(), } } diff --git a/zcash_proofs/src/lib.rs b/zcash_proofs/src/lib.rs index ca17a8b89..d0618182a 100644 --- a/zcash_proofs/src/lib.rs +++ b/zcash_proofs/src/lib.rs @@ -1,5 +1,5 @@ extern crate bellman; -extern crate blake2_rfc; +extern crate blake2b_simd; extern crate byteorder; extern crate ff; extern crate pairing;