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.
This commit is contained in:
Jack Grigg 2019-06-04 13:15:12 +01:00
parent 91c6b0b3f0
commit 999dcbfcab
No known key found for this signature in database
GPG Key ID: 9E8255172BBF9898
20 changed files with 172 additions and 129 deletions

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)",
]
[[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)" = "<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-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"

View File

@ -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"

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 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<u8> = Vec::from("ZcashPoW");
personalization.write_u32::<LittleEndian>(n).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];
(&mut lei[..]).write_u32::<LittleEndian>(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<Node> {
fn tree_validator(p: &Params, state: &Blake2bState, indices: &[u32]) -> Option<Node> {
if indices.len() > 1 {
let end = indices.len();
let mid = end / 2;

View File

@ -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();

View File

@ -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"

View File

@ -320,13 +320,13 @@ pub fn blake2s<E: Engine, CS: ConstraintSystem<E>>(
#[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<u8> = (0..input_len).map(|_| rng.gen()).collect();

View File

@ -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<E: Engine>(
fn hash_lc<E: Engine>(
terms: &[(Variable, E::Fr)],
h: &mut Blake2s
h: &mut Blake2sState
)
{
let map = proc_lc::<E>(terms);
@ -226,7 +226,7 @@ impl<E: Engine> TestConstraintSystem<E> {
}
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];

View File

@ -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<E: JubjubEngine>(
// 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::<E, _>::read(&h[..], params) {
match edwards::Point::<E, _>::read(h.as_ref(), params) {
Ok(p) => {
let p = p.mul_by_cofactor(params);

View File

@ -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;

View File

@ -22,7 +22,7 @@ use jubjub::{
FixedGenerators
};
use blake2_rfc::blake2s::Blake2s;
use blake2s_simd::Params as Blake2sParams;
#[derive(Clone)]
pub struct ValueCommitment<E: JubjubEngine> {
@ -87,9 +87,12 @@ impl<E: JubjubEngine> ViewingKey<E> {
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<E: JubjubEngine> Note<E> {
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

View File

@ -1,9 +1,9 @@
use blake2_rfc::blake2b::Blake2b;
use blake2b_simd::Params;
use jubjub::{JubjubEngine, ToUniform};
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(b);
let ret = hasher.finalize();

View File

@ -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"

View File

@ -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);

View File

@ -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;

View File

@ -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<Bls12, PrimeOrder>,
epk: &edwards::Point<Bls12, PrimeOrder>,
) -> 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<Bls12, Unknown>,
cmu: &Fr,
epk: &edwards::Point<Bls12, PrimeOrder>,
) -> 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.

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 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<u8> {
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<u8> {
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::<LittleEndian>(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<u8> {
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<u8> {
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<u8> {
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<u8> {
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<u8> {
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<u8> {
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<u8> {
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::<LittleEndian>(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));

View File

@ -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<E: JubjubEngine> From<&FullViewingKey<E>> for FVKFingerprint {
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());
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];

View File

@ -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"

View File

@ -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<R: Read> {
reader: R,
hasher: Blake2b,
hasher: State,
}
impl<R: Read> HashReader<R> {
@ -12,7 +12,7 @@ impl<R: Read> HashReader<R> {
pub fn new(reader: R) -> Self {
HashReader {
reader: reader,
hasher: Blake2b::new(64),
hasher: State::new(),
}
}

View File

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