Merge pull request #83 from str4d/blake2_simd

Migrate to blake2b_simd and blake2s_simd crates
This commit is contained in:
str4d
2019-07-18 17:41:59 +01:00
committed by GitHub
21 changed files with 173 additions and 130 deletions

View File

@@ -1,6 +1,6 @@
language: rust language: rust
rust: rust:
- 1.32.0 - 1.36.0
cache: cargo cache: cargo

43
Cargo.lock generated
View File

@@ -30,9 +30,14 @@ dependencies = [
"stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "arrayvec" name = "arrayvec"
version = "0.4.7" version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "blake2-rfc" name = "blake2b_simd"
version = "0.2.18" version = "0.5.1"
source = "git+https://github.com/gtank/blake2-rfc?rev=7a5b5fc99ae483a0043db7547fb79a6fa44b88a9#7a5b5fc99ae483a0043db7547fb79a6fa44b88a9" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.2 (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)", "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" version = "0.1.0"
dependencies = [ dependencies = [
"bellman 0.1.0", "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)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ff 0.4.0", "ff 0.4.0",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "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" version = "0.0.1"
dependencies = [ dependencies = [
"bellman 0.1.0", "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)", "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)", "digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ff 0.4.0", "ff 0.4.0",
@@ -529,7 +546,7 @@ name = "zcash_primitives"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "crypto_api_chachapoly 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ff 0.4.0", "ff 0.4.0",
@@ -547,7 +564,7 @@ name = "zcash_proofs"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"bellman 0.1.0", "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)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ff 0.4.0", "ff 0.4.0",
"pairing 0.14.2", "pairing 0.14.2",
@@ -560,11 +577,13 @@ dependencies = [
"checksum aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6fb1737cdc8da3db76e90ca817a194249a38fcb500c2e6ecec39b29448aa873" "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 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 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 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 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 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)" = "<none>" "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-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-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" "checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3"

View File

@@ -15,6 +15,8 @@ crate-type = ["staticlib"]
[dependencies] [dependencies]
bellman = { path = "../bellman" } bellman = { path = "../bellman" }
blake2b_simd = "0.5"
blake2s_simd = "0.5"
ff = { path = "../ff" } ff = { path = "../ff" }
libc = "0.2" libc = "0.2"
pairing = { path = "../pairing" } pairing = { path = "../pairing" }
@@ -24,7 +26,3 @@ rand = "0.4"
sapling-crypto = { path = "../sapling-crypto" } sapling-crypto = { path = "../sapling-crypto" }
zcash_primitives = { path = "../zcash_primitives" } zcash_primitives = { path = "../zcash_primitives" }
zcash_proofs = { path = "../zcash_proofs" } zcash_proofs = { path = "../zcash_proofs" }
[dependencies.blake2-rfc]
git = "https://github.com/gtank/blake2-rfc"
rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9"

View File

@@ -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 byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt};
use std::io::Cursor; use std::io::Cursor;
use std::mem::size_of; use std::mem::size_of;
@@ -33,7 +33,7 @@ impl Params {
} }
impl Node { 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 hash = generate_hash(state, i / p.indices_per_hash_output());
let start = ((i % p.indices_per_hash_output()) * p.n / 8) as usize; let start = ((i % p.indices_per_hash_output()) * p.n / 8) as usize;
let end = start + (p.n as usize) / 8; 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<u8> = Vec::from("ZcashPoW"); let mut personalization: Vec<u8> = Vec::from("ZcashPoW");
personalization.write_u32::<LittleEndian>(n).unwrap(); personalization.write_u32::<LittleEndian>(n).unwrap();
personalization.write_u32::<LittleEndian>(k).unwrap(); personalization.write_u32::<LittleEndian>(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]; let mut lei = [0u8; 4];
(&mut lei[..]).write_u32::<LittleEndian>(i).unwrap(); (&mut lei[..]).write_u32::<LittleEndian>(i).unwrap();
@@ -249,7 +252,7 @@ pub fn is_valid_solution_iterative(
return rows[0].is_zero(hash_len); return rows[0].is_zero(hash_len);
} }
fn tree_validator(p: &Params, state: &Blake2b, indices: &[u32]) -> Option<Node> { fn tree_validator(p: &Params, state: &Blake2bState, indices: &[u32]) -> Option<Node> {
if indices.len() > 1 { if indices.len() > 1 {
let end = indices.len(); let end = indices.len();
let mid = end / 2; let mid = end / 2;

View File

@@ -1,5 +1,6 @@
extern crate bellman; extern crate bellman;
extern crate blake2_rfc; extern crate blake2b_simd;
extern crate blake2s_simd;
extern crate byteorder; extern crate byteorder;
extern crate ff; extern crate ff;
extern crate libc; extern crate libc;
@@ -32,7 +33,7 @@ use bellman::groth16::{
create_random_proof, verify_proof, Parameters, PreparedVerifyingKey, Proof, create_random_proof, verify_proof, Parameters, PreparedVerifyingKey, Proof,
}; };
use blake2_rfc::blake2s::Blake2s; use blake2s_simd::Params as Blake2sParams;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
@@ -319,7 +320,10 @@ pub extern "system" fn librustzcash_crh_ivk(
let ak = unsafe { &*ak }; let ak = unsafe { &*ak };
let nk = unsafe { &*nk }; 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(ak);
h.update(nk); h.update(nk);
let mut h = h.finalize().as_ref().to_vec(); let mut h = h.finalize().as_ref().to_vec();

View File

@@ -14,15 +14,13 @@ features = ["expose-arith"]
[dependencies] [dependencies]
bellman = { path = "../bellman" } bellman = { path = "../bellman" }
blake2b_simd = "0.5"
blake2s_simd = "0.5"
ff = { path = "../ff" } ff = { path = "../ff" }
rand = "0.4" rand = "0.4"
digest = "0.7" digest = "0.7"
byteorder = "1" byteorder = "1"
[dependencies.blake2-rfc]
git = "https://github.com/gtank/blake2-rfc"
rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9"
[dev-dependencies] [dev-dependencies]
hex-literal = "0.1" hex-literal = "0.1"
rust-crypto = "0.2" rust-crypto = "0.2"

View File

@@ -320,13 +320,13 @@ pub fn blake2s<E: Engine, CS: ConstraintSystem<E>>(
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use blake2s_simd::Params as Blake2sParams;
use rand::{XorShiftRng, SeedableRng, Rng}; use rand::{XorShiftRng, SeedableRng, Rng};
use pairing::bls12_381::{Bls12}; use pairing::bls12_381::{Bls12};
use ::circuit::boolean::{Boolean, AllocatedBit}; use ::circuit::boolean::{Boolean, AllocatedBit};
use ::circuit::test::TestConstraintSystem; use ::circuit::test::TestConstraintSystem;
use super::blake2s; use super::blake2s;
use bellman::{ConstraintSystem}; use bellman::{ConstraintSystem};
use blake2_rfc::blake2s::Blake2s;
#[test] #[test]
fn test_blank_hash() { fn test_blank_hash() {
@@ -392,7 +392,7 @@ mod test {
for input_len in (0..32).chain((32..256).filter(|a| a % 8 == 0)) 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<u8> = (0..input_len).map(|_| rng.gen()).collect(); let data: Vec<u8> = (0..input_len).map(|_| rng.gen()).collect();

View File

@@ -16,7 +16,7 @@ use byteorder::{BigEndian, ByteOrder};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use blake2_rfc::blake2s::Blake2s; use blake2s_simd::{Params as Blake2sParams, State as Blake2sState};
#[derive(Debug)] #[derive(Debug)]
enum NamedObject { enum NamedObject {
@@ -96,7 +96,7 @@ fn proc_lc<E: Engine>(
fn hash_lc<E: Engine>( fn hash_lc<E: Engine>(
terms: &[(Variable, E::Fr)], terms: &[(Variable, E::Fr)],
h: &mut Blake2s h: &mut Blake2sState
) )
{ {
let map = proc_lc::<E>(terms); let map = proc_lc::<E>(terms);
@@ -226,7 +226,7 @@ impl<E: Engine> TestConstraintSystem<E> {
} }
pub fn hash(&self) -> String { 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]; let mut buf = [0u8; 24];

View File

@@ -8,7 +8,7 @@ use ff::{
PrimeField PrimeField
}; };
use blake2_rfc::blake2s::Blake2s; use blake2s_simd::Params;
use constants; use constants;
/// Produces a random point in the Jubjub curve. /// Produces a random point in the Jubjub curve.
@@ -25,13 +25,15 @@ pub fn group_hash<E: JubjubEngine>(
// Check to see that scalar field is 255 bits // Check to see that scalar field is 255 bits
assert!(E::Fr::NUM_BITS == 255); assert!(E::Fr::NUM_BITS == 255);
let mut h = Blake2s::with_params(32, &[], &[], personalization); let h = Params::new()
h.update(constants::GH_FIRST_BLOCK); .hash_length(32)
h.update(tag); .personal(personalization)
let h = h.finalize().as_ref().to_vec(); .to_state()
assert!(h.len() == 32); .update(constants::GH_FIRST_BLOCK)
.update(tag)
.finalize();
match edwards::Point::<E, _>::read(&h[..], params) { match edwards::Point::<E, _>::read(h.as_ref(), params) {
Ok(p) => { Ok(p) => {
let p = p.mul_by_cofactor(params); let p = p.mul_by_cofactor(params);

View File

@@ -1,6 +1,7 @@
extern crate pairing; extern crate pairing;
extern crate bellman; extern crate bellman;
extern crate blake2_rfc; extern crate blake2b_simd;
extern crate blake2s_simd;
extern crate digest; extern crate digest;
extern crate ff; extern crate ff;
extern crate rand; extern crate rand;

View File

@@ -22,7 +22,7 @@ use jubjub::{
FixedGenerators FixedGenerators
}; };
use blake2_rfc::blake2s::Blake2s; use blake2s_simd::Params as Blake2sParams;
#[derive(Clone)] #[derive(Clone)]
pub struct ValueCommitment<E: JubjubEngine> { pub struct ValueCommitment<E: JubjubEngine> {
@@ -87,9 +87,12 @@ impl<E: JubjubEngine> ViewingKey<E> {
self.ak.write(&mut preimage[0..32]).unwrap(); self.ak.write(&mut preimage[0..32]).unwrap();
self.nk.write(&mut preimage[32..64]).unwrap(); self.nk.write(&mut preimage[32..64]).unwrap();
let mut h = Blake2s::with_params(32, &[], &[], constants::CRH_IVK_PERSONALIZATION); let mut h = [0; 32];
h.update(&preimage); h.copy_from_slice(Blake2sParams::new()
let mut h = h.finalize().as_ref().to_vec(); .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. // Drop the most significant five bits, so it can be interpreted as a scalar.
h[31] &= 0b0000_0111; h[31] &= 0b0000_0111;
@@ -255,10 +258,12 @@ impl<E: JubjubEngine> Note<E> {
let mut nf_preimage = [0u8; 64]; let mut nf_preimage = [0u8; 64];
viewing_key.nk.write(&mut nf_preimage[0..32]).unwrap(); viewing_key.nk.write(&mut nf_preimage[0..32]).unwrap();
rho.write(&mut nf_preimage[32..64]).unwrap(); rho.write(&mut nf_preimage[32..64]).unwrap();
let mut h = Blake2s::with_params(32, &[], &[], constants::PRF_NF_PERSONALIZATION); Blake2sParams::new()
h.update(&nf_preimage); .hash_length(32)
.personal(constants::PRF_NF_PERSONALIZATION)
h.finalize().as_ref().to_vec() .hash(&nf_preimage)
.as_bytes()
.to_vec()
} }
/// Computes the note commitment /// Computes the note commitment

View File

@@ -1,9 +1,9 @@
use blake2_rfc::blake2b::Blake2b; use blake2b_simd::Params;
use jubjub::{JubjubEngine, ToUniform}; use jubjub::{JubjubEngine, ToUniform};
pub fn hash_to_scalar<E: JubjubEngine>(persona: &[u8], a: &[u8], b: &[u8]) -> E::Fs { pub fn hash_to_scalar<E: JubjubEngine>(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(a);
hasher.update(b); hasher.update(b);
let ret = hasher.finalize(); let ret = hasher.finalize();

View File

@@ -7,6 +7,7 @@ authors = [
[dependencies] [dependencies]
aes = "0.2" aes = "0.2"
blake2b_simd = "0.5"
byteorder = "1" byteorder = "1"
crypto_api_chachapoly = "0.1" crypto_api_chachapoly = "0.1"
ff = { path = "../ff" } ff = { path = "../ff" }
@@ -17,7 +18,3 @@ pairing = { path = "../pairing" }
rand = "0.4" rand = "0.4"
sapling-crypto = { path = "../sapling-crypto" } sapling-crypto = { path = "../sapling-crypto" }
sha2 = "0.8" sha2 = "0.8"
[dependencies.blake2-rfc]
git = "https://github.com/gtank/blake2-rfc"
rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9"

View File

@@ -2,7 +2,7 @@
//! //!
//! Implements section 4.2.2 of the Zcash Protocol Specification. //! 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 ff::{PrimeField, PrimeFieldRepr};
use sapling_crypto::{ use sapling_crypto::{
jubjub::{edwards, FixedGenerators, JubjubEngine, JubjubParams, ToUniform, Unknown}, 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"; pub const PRF_EXPAND_PERSONALIZATION: &'static [u8; 16] = b"Zcash_ExpandSeed";
/// PRF^expand(sk, t) := BLAKE2b-512("Zcash_ExpandSeed", sk || t) /// PRF^expand(sk, t) := BLAKE2b-512("Zcash_ExpandSeed", sk || t)
pub fn prf_expand(sk: &[u8], t: &[u8]) -> Blake2bResult { pub fn prf_expand(sk: &[u8], t: &[u8]) -> Blake2bHash {
prf_expand_vec(sk, &[t]) prf_expand_vec(sk, &vec![t])
} }
pub fn prf_expand_vec(sk: &[u8], ts: &[&[u8]]) -> Blake2bResult { pub fn prf_expand_vec(sk: &[u8], ts: &[&[u8]]) -> Blake2bHash {
let mut h = Blake2b::with_params(64, &[], &[], PRF_EXPAND_PERSONALIZATION); let mut h = Blake2bParams::new()
.hash_length(64)
.personal(PRF_EXPAND_PERSONALIZATION)
.to_state();
h.update(sk); h.update(sk);
for t in ts { for t in ts {
h.update(t); h.update(t);

View File

@@ -2,7 +2,7 @@
extern crate lazy_static; extern crate lazy_static;
extern crate aes; extern crate aes;
extern crate blake2_rfc; extern crate blake2b_simd;
extern crate byteorder; extern crate byteorder;
extern crate crypto_api_chachapoly; extern crate crypto_api_chachapoly;
extern crate ff; extern crate ff;

View File

@@ -1,6 +1,6 @@
//! Implementation of in-band secret distribution for Zcash transactions. //! 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 byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crypto_api_chachapoly::{ChaCha20Ietf, ChachaPolyIetf}; use crypto_api_chachapoly::{ChaCha20Ietf, ChachaPolyIetf};
use ff::{PrimeField, PrimeFieldRepr}; use ff::{PrimeField, PrimeFieldRepr};
@@ -168,14 +168,15 @@ where
fn kdf_sapling( fn kdf_sapling(
dhsecret: edwards::Point<Bls12, PrimeOrder>, dhsecret: edwards::Point<Bls12, PrimeOrder>,
epk: &edwards::Point<Bls12, PrimeOrder>, epk: &edwards::Point<Bls12, PrimeOrder>,
) -> Blake2bResult { ) -> Blake2bHash {
let mut input = [0u8; 64]; let mut input = [0u8; 64];
dhsecret.write(&mut input[0..32]).unwrap(); dhsecret.write(&mut input[0..32]).unwrap();
epk.write(&mut input[32..64]).unwrap(); epk.write(&mut input[32..64]).unwrap();
let mut h = Blake2b::with_params(32, &[], &[], KDF_SAPLING_PERSONALIZATION); Blake2bParams::new()
h.update(&input); .hash_length(32)
h.finalize() .personal(KDF_SAPLING_PERSONALIZATION)
.hash(&input)
} }
/// Sapling PRF^ock. /// Sapling PRF^ock.
@@ -186,16 +187,17 @@ fn prf_ock(
cv: &edwards::Point<Bls12, Unknown>, cv: &edwards::Point<Bls12, Unknown>,
cmu: &Fr, cmu: &Fr,
epk: &edwards::Point<Bls12, PrimeOrder>, epk: &edwards::Point<Bls12, PrimeOrder>,
) -> Blake2bResult { ) -> Blake2bHash {
let mut ock_input = [0u8; 128]; let mut ock_input = [0u8; 128];
ock_input[0..32].copy_from_slice(&ovk.0); ock_input[0..32].copy_from_slice(&ovk.0);
cv.write(&mut ock_input[32..64]).unwrap(); cv.write(&mut ock_input[32..64]).unwrap();
cmu.into_repr().write_le(&mut ock_input[64..96]).unwrap(); cmu.into_repr().write_le(&mut ock_input[64..96]).unwrap();
epk.write(&mut ock_input[96..128]).unwrap(); epk.write(&mut ock_input[96..128]).unwrap();
let mut h = Blake2b::with_params(32, &[], &[], PRF_OCK_PERSONALIZATION); Blake2bParams::new()
h.update(&ock_input); .hash_length(32)
h.finalize() .personal(PRF_OCK_PERSONALIZATION)
.hash(&ock_input)
} }
/// An API for encrypting Sapling notes. /// An API for encrypting Sapling notes.

View File

@@ -1,4 +1,4 @@
use blake2_rfc::blake2b::Blake2b; use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
use byteorder::{LittleEndian, WriteBytesExt}; use byteorder::{LittleEndian, WriteBytesExt};
use ff::{PrimeField, PrimeFieldRepr}; use ff::{PrimeField, PrimeFieldRepr};
@@ -39,7 +39,7 @@ macro_rules! update_i64 {
macro_rules! update_hash { macro_rules! update_hash {
($h:expr, $cond:expr, $value:expr) => { ($h:expr, $cond:expr, $value:expr) => {
if $cond { if $cond {
$h.update(&$value); $h.update(&$value.as_ref());
} else { } else {
$h.update(&[0; 32]); $h.update(&[0; 32]);
} }
@@ -67,47 +67,51 @@ impl SigHashVersion {
} }
} }
fn prevout_hash(tx: &TransactionData) -> Vec<u8> { fn prevout_hash(tx: &TransactionData) -> Blake2bHash {
let mut data = Vec::with_capacity(tx.vin.len() * 36); let mut data = Vec::with_capacity(tx.vin.len() * 36);
for t_in in &tx.vin { for t_in in &tx.vin {
t_in.prevout.write(&mut data).unwrap(); t_in.prevout.write(&mut data).unwrap();
} }
let mut h = Blake2b::with_params(32, &[], &[], ZCASH_PREVOUTS_HASH_PERSONALIZATION); Blake2bParams::new()
h.update(&data); .hash_length(32)
h.finalize().as_ref().to_vec() .personal(ZCASH_PREVOUTS_HASH_PERSONALIZATION)
.hash(&data)
} }
fn sequence_hash(tx: &TransactionData) -> Vec<u8> { fn sequence_hash(tx: &TransactionData) -> Blake2bHash {
let mut data = Vec::with_capacity(tx.vin.len() * 4); let mut data = Vec::with_capacity(tx.vin.len() * 4);
for t_in in &tx.vin { for t_in in &tx.vin {
(&mut data) (&mut data)
.write_u32::<LittleEndian>(t_in.sequence) .write_u32::<LittleEndian>(t_in.sequence)
.unwrap(); .unwrap();
} }
let mut h = Blake2b::with_params(32, &[], &[], ZCASH_SEQUENCE_HASH_PERSONALIZATION); Blake2bParams::new()
h.update(&data); .hash_length(32)
h.finalize().as_ref().to_vec() .personal(ZCASH_SEQUENCE_HASH_PERSONALIZATION)
.hash(&data)
} }
fn outputs_hash(tx: &TransactionData) -> Vec<u8> { fn outputs_hash(tx: &TransactionData) -> Blake2bHash {
let mut data = Vec::with_capacity(tx.vout.len() * (4 + 1)); let mut data = Vec::with_capacity(tx.vout.len() * (4 + 1));
for t_out in &tx.vout { for t_out in &tx.vout {
t_out.write(&mut data).unwrap(); t_out.write(&mut data).unwrap();
} }
let mut h = Blake2b::with_params(32, &[], &[], ZCASH_OUTPUTS_HASH_PERSONALIZATION); Blake2bParams::new()
h.update(&data); .hash_length(32)
h.finalize().as_ref().to_vec() .personal(ZCASH_OUTPUTS_HASH_PERSONALIZATION)
.hash(&data)
} }
fn single_output_hash(tx_out: &TxOut) -> Vec<u8> { fn single_output_hash(tx_out: &TxOut) -> Blake2bHash {
let mut data = vec![]; let mut data = vec![];
tx_out.write(&mut data).unwrap(); tx_out.write(&mut data).unwrap();
let mut h = Blake2b::with_params(32, &[], &[], ZCASH_OUTPUTS_HASH_PERSONALIZATION); Blake2bParams::new()
h.update(&data); .hash_length(32)
h.finalize().as_ref().to_vec() .personal(ZCASH_OUTPUTS_HASH_PERSONALIZATION)
.hash(&data)
} }
fn joinsplits_hash(tx: &TransactionData) -> Vec<u8> { fn joinsplits_hash(tx: &TransactionData) -> Blake2bHash {
let mut data = Vec::with_capacity( let mut data = Vec::with_capacity(
tx.joinsplits.len() tx.joinsplits.len()
* if tx.version < SAPLING_TX_VERSION { * if tx.version < SAPLING_TX_VERSION {
@@ -120,12 +124,13 @@ fn joinsplits_hash(tx: &TransactionData) -> Vec<u8> {
js.write(&mut data).unwrap(); js.write(&mut data).unwrap();
} }
data.extend_from_slice(&tx.joinsplit_pubkey.unwrap()); data.extend_from_slice(&tx.joinsplit_pubkey.unwrap());
let mut h = Blake2b::with_params(32, &[], &[], ZCASH_JOINSPLITS_HASH_PERSONALIZATION); Blake2bParams::new()
h.update(&data); .hash_length(32)
h.finalize().as_ref().to_vec() .personal(ZCASH_JOINSPLITS_HASH_PERSONALIZATION)
.hash(&data)
} }
fn shielded_spends_hash(tx: &TransactionData) -> Vec<u8> { fn shielded_spends_hash(tx: &TransactionData) -> Blake2bHash {
let mut data = Vec::with_capacity(tx.shielded_spends.len() * 384); let mut data = Vec::with_capacity(tx.shielded_spends.len() * 384);
for s_spend in &tx.shielded_spends { for s_spend in &tx.shielded_spends {
s_spend.cv.write(&mut data).unwrap(); s_spend.cv.write(&mut data).unwrap();
@@ -134,19 +139,21 @@ fn shielded_spends_hash(tx: &TransactionData) -> Vec<u8> {
s_spend.rk.write(&mut data).unwrap(); s_spend.rk.write(&mut data).unwrap();
data.extend_from_slice(&s_spend.zkproof); data.extend_from_slice(&s_spend.zkproof);
} }
let mut h = Blake2b::with_params(32, &[], &[], ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION); Blake2bParams::new()
h.update(&data); .hash_length(32)
h.finalize().as_ref().to_vec() .personal(ZCASH_SHIELDED_SPENDS_HASH_PERSONALIZATION)
.hash(&data)
} }
fn shielded_outputs_hash(tx: &TransactionData) -> Vec<u8> { fn shielded_outputs_hash(tx: &TransactionData) -> Blake2bHash {
let mut data = Vec::with_capacity(tx.shielded_outputs.len() * 948); let mut data = Vec::with_capacity(tx.shielded_outputs.len() * 948);
for s_out in &tx.shielded_outputs { for s_out in &tx.shielded_outputs {
s_out.write(&mut data).unwrap(); s_out.write(&mut data).unwrap();
} }
let mut h = Blake2b::with_params(32, &[], &[], ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION); Blake2bParams::new()
h.update(&data); .hash_length(32)
h.finalize().as_ref().to_vec() .personal(ZCASH_SHIELDED_OUTPUTS_HASH_PERSONALIZATION)
.hash(&data)
} }
pub fn signature_hash_data( pub fn signature_hash_data(
@@ -158,26 +165,16 @@ pub fn signature_hash_data(
let sigversion = SigHashVersion::from_tx(tx); let sigversion = SigHashVersion::from_tx(tx);
match sigversion { match sigversion {
SigHashVersion::Overwinter | SigHashVersion::Sapling => { 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]; let mut personal = [0; 16];
(&mut personal[..12]).copy_from_slice(ZCASH_SIGHASH_PERSONALIZATION_PREFIX); (&mut personal[..12]).copy_from_slice(ZCASH_SIGHASH_PERSONALIZATION_PREFIX);
(&mut personal[12..]) (&mut personal[12..])
.write_u32::<LittleEndian>(consensus_branch_id) .write_u32::<LittleEndian>(consensus_branch_id)
.unwrap(); .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]; let mut tmp = [0; 8];
update_u32!(h, tx.header(), tmp); update_u32!(h, tx.header(), tmp);
@@ -190,7 +187,20 @@ pub fn signature_hash_data(
&& (hash_type & SIGHASH_MASK) != SIGHASH_NONE, && (hash_type & SIGHASH_MASK) != SIGHASH_NONE,
sequence_hash(tx) 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)); update_hash!(h, !tx.joinsplits.is_empty(), joinsplits_hash(tx));
if sigversion == SigHashVersion::Sapling { if sigversion == SigHashVersion::Sapling {
update_hash!(h, !tx.shielded_spends.is_empty(), shielded_spends_hash(tx)); update_hash!(h, !tx.shielded_spends.is_empty(), shielded_spends_hash(tx));

View File

@@ -1,5 +1,5 @@
use aes::Aes256; use aes::Aes256;
use blake2_rfc::blake2b::Blake2b; use blake2b_simd::Params as Blake2bParams;
use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
use ff::Field; use ff::Field;
use fpe::ff1::{BinaryNumeralString, FF1}; use fpe::ff1::{BinaryNumeralString, FF1};
@@ -33,7 +33,10 @@ struct FVKFingerprint([u8; 32]);
impl<E: JubjubEngine> From<&FullViewingKey<E>> for FVKFingerprint { impl<E: JubjubEngine> From<&FullViewingKey<E>> for FVKFingerprint {
fn from(fvk: &FullViewingKey<E>) -> Self { fn from(fvk: &FullViewingKey<E>) -> 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()); h.update(&fvk.to_bytes());
let mut fvfp = [0u8; 32]; let mut fvfp = [0u8; 32];
fvfp.copy_from_slice(h.finalize().as_bytes()); fvfp.copy_from_slice(h.finalize().as_bytes());
@@ -225,9 +228,10 @@ impl std::fmt::Debug for ExtendedFullViewingKey {
impl ExtendedSpendingKey { impl ExtendedSpendingKey {
pub fn master(seed: &[u8]) -> Self { pub fn master(seed: &[u8]) -> Self {
let mut h = Blake2b::with_params(64, &[], &[], ZIP32_SAPLING_MASTER_PERSONALIZATION); let i = Blake2bParams::new()
h.update(seed); .hash_length(64)
let i = h.finalize(); .personal(ZIP32_SAPLING_MASTER_PERSONALIZATION)
.hash(seed);
let sk_m = &i.as_bytes()[..32]; let sk_m = &i.as_bytes()[..32];
let mut c_m = [0u8; 32]; let mut c_m = [0u8; 32];

View File

@@ -7,13 +7,10 @@ authors = [
[dependencies] [dependencies]
bellman = { path = "../bellman" } bellman = { path = "../bellman" }
blake2b_simd = "0.5"
byteorder = "1" byteorder = "1"
ff = { path = "../ff" } ff = { path = "../ff" }
pairing = { path = "../pairing" } pairing = { path = "../pairing" }
rand = "0.4" rand = "0.4"
sapling-crypto = { path = "../sapling-crypto" } sapling-crypto = { path = "../sapling-crypto" }
zcash_primitives = { path = "../zcash_primitives" } zcash_primitives = { path = "../zcash_primitives" }
[dependencies.blake2-rfc]
git = "https://github.com/gtank/blake2-rfc"
rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9"

View File

@@ -1,10 +1,10 @@
use blake2_rfc::blake2b::Blake2b; use blake2b_simd::State;
use std::io::{self, Read}; use std::io::{self, Read};
/// Abstraction over a reader which hashes the data being read. /// Abstraction over a reader which hashes the data being read.
pub struct HashReader<R: Read> { pub struct HashReader<R: Read> {
reader: R, reader: R,
hasher: Blake2b, hasher: State,
} }
impl<R: Read> HashReader<R> { impl<R: Read> HashReader<R> {
@@ -12,7 +12,7 @@ impl<R: Read> HashReader<R> {
pub fn new(reader: R) -> Self { pub fn new(reader: R) -> Self {
HashReader { HashReader {
reader: reader, reader: reader,
hasher: Blake2b::new(64), hasher: State::new(),
} }
} }

View File

@@ -1,5 +1,5 @@
extern crate bellman; extern crate bellman;
extern crate blake2_rfc; extern crate blake2b_simd;
extern crate byteorder; extern crate byteorder;
extern crate ff; extern crate ff;
extern crate pairing; extern crate pairing;