diff --git a/Cargo.toml b/Cargo.toml index 46e95a0..1fa00ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,11 +12,11 @@ version = "0.0.3" arrayref = "0.3" rand = "0.4" ff = { version = "0.4", features = ["derive"] } -# sha3 = "0.8" +sha3 = "0.8" -[dependencies.merlin] -version = "1.1.0" -# features = ["debug-transcript"] +# [dependencies.merlin] +# version = "1.1.0" +## features = ["debug-transcript"] [dependencies.paired] version = "0.15" diff --git a/src/delinear.rs b/src/delinear.rs index db42f53..5c7f6e7 100644 --- a/src/delinear.rs +++ b/src/delinear.rs @@ -15,6 +15,7 @@ use ff::{PrimeField, PrimeFieldRepr}; // Field, ScalarEngine, SqrtField, PrimeFieldDecodingError use pairing::{CurveAffine, CurveProjective}; // Engine, EncodedPoint, GroupDecodingError use rand::{Rng, thread_rng}; +use sha3::{Shake128, digest::{Input,ExtendableOutput,XofReader}}; use std::collections::HashMap; @@ -34,7 +35,7 @@ use super::verifiers::verify_with_distinct_messages; /// should consider a proof-of-possession scheme, which requiees all /// signers register in advance. pub struct Delinearized { - key: ::merlin::Transcript, + key: Shake128, messages_n_publickeys: HashMap>, signature: Signature, } @@ -68,7 +69,7 @@ impl<'a,E: EngineBLS> Signed for &'a Delinearized { } impl Delinearized { - pub fn new(key: ::merlin::Transcript) -> Delinearized { + pub fn new(key: Shake128) -> Delinearized { Delinearized { key, messages_n_publickeys: HashMap::new(), @@ -76,8 +77,11 @@ impl Delinearized { } } pub fn new_keyed(key: &[u8]) -> Delinearized { - let mut t = ::merlin::Transcript::new(b"Delinearised BLS"); - t.append_message(b"key",key); + let mut t = Shake128::default(); + t.input(b"Delinearised BLS with key:"); + let l = key.len() as u64; + t.input(l.to_le_bytes()); + t.input(key); Delinearized::new(t) } pub fn new_batched_rng(mut rng: R) -> Delinearized { @@ -95,9 +99,9 @@ impl Delinearized { /// our return type here changes. pub fn mask(&self, publickey: &PublicKey) -> E::Scalar { let mut t = self.key.clone(); - t.append_message(b"",publickey.0.into_affine().into_uncompressed().as_ref()); + t.input(publickey.0.into_affine().into_uncompressed().as_ref()); let mut b = [0u8; 16]; - t.challenge_bytes(b"",&mut b[..]); + t.xof_result().read(&mut b[..]); let (x,y) = array_refs!(&b,8,8); let mut x: ::Repr = u64::from_le_bytes(*x).into(); let y: ::Repr = u64::from_le_bytes(*y).into(); @@ -153,8 +157,8 @@ impl Delinearized { // TODO: See https://github.com/dalek-cryptography/merlin/pull/37 pub fn agreement(&self, other: &Delinearized) -> bool { let mut c = [[0u8; 16]; 2]; - self.key.clone().challenge_bytes(b"",&mut c[0]); - other.key.clone().challenge_bytes(b"",&mut c[1]); + self.key.clone().xof_result().read(&mut c[0]); + other.key.clone().xof_result().read(&mut c[1]); c[0] == c[1] } @@ -182,7 +186,7 @@ type PublicKeyUncompressed = <<::$group as CurveProjective>:: #[derive(Clone)] pub struct DelinearizedRepeatedSigners { - key: ::merlin::Transcript, + key: Shake128, messages_n_publickeys: HashMap,(Message,PublicKey)>, signature: Signature, } diff --git a/src/lib.rs b/src/lib.rs index 216eac1..ba271e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,10 +90,9 @@ extern crate arrayref; // #[macro_use] extern crate ff; -extern crate merlin; extern crate paired as pairing; extern crate rand; -// extern crate sha3; +extern crate sha3; use std::borrow::Borrow; @@ -125,15 +124,17 @@ pub struct Message(pub [u8; MESSAGE_SIZE]); impl Message { pub fn new(context: &'static [u8], message: &[u8]) -> Message { - // use sha3::{Shake128, digest::{Input,ExtendableOutput,XofReader}}; - // let mut h = Shake128::default(); - // h.input(self.message.borrow()); - // h.input(self.signature.0.into_affine().into_uncompressed().as_ref()); - let mut t = ::merlin::Transcript::new(context); - t.append_message(b"", message); + use sha3::{Shake128, digest::{Input,ExtendableOutput,XofReader}}; + let mut h = Shake128::default(); + h.input(context); + let l = message.len() as u64; + h.input(l.to_le_bytes()); + h.input(message); + // let mut t = ::merlin::Transcript::new(context); + // t.append_message(b"", message); let mut msg = [0u8; MESSAGE_SIZE]; - // h.xof_result().read(&mut msg[..]); - t.challenge_bytes(b"", &mut msg); + h.xof_result().read(&mut msg[..]); + // t.challenge_bytes(b"", &mut msg); Message(msg) } diff --git a/src/single.rs b/src/single.rs index bdfd6dc..a78355c 100644 --- a/src/single.rs +++ b/src/single.rs @@ -28,6 +28,7 @@ use pairing::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError}; use rand::{Rng, thread_rng, SeedableRng, chacha::ChaChaRng}; // use rand::prelude::*; // ThreadRng,thread_rng // use rand_chacha::ChaChaRng; +use sha3::{Shake128, digest::{Input,ExtendableOutput,XofReader}}; // use std::borrow::{Borrow,BorrowMut}; use std::iter::once; @@ -619,7 +620,7 @@ impl SignedMessage { E::pairing(g1_one, self.signature.0.into_affine()) == E::pairing(self.publickey.0.into_affine(), message) } - /// Raw bytes output from a BLS signature regarded as a VRF. + /// Hash output from a BLS signature regarded as a VRF. /// /// If you are not the signer then you must verify the VRF before calling this method. /// @@ -629,17 +630,24 @@ impl SignedMessage { /// construction from Theorem 2 on page 32 in appendex C of /// ["Ouroboros Praos: An adaptively-secure, semi-synchronous proof-of-stake blockchain"](https://eprint.iacr.org/2017/573.pdf) /// by Bernardo David, Peter Gazi, Aggelos Kiayias, and Alexander Russell. - pub fn make_bytes>(&self, context: &'static [u8]) -> Out { - // use sha3::{Shake128, digest::{Input,ExtendableOutput,XofReader}}; - // let mut h = Shake128::default(); - // h.input(&self.message.0[..]); - // h.input(self.signature.0.into_affine().into_uncompressed().as_ref()); - let mut t = ::merlin::Transcript::new(context); - t.append_message(b"msg",&self.message.0[..]); - t.append_message(b"out",self.signature.0.into_affine().into_uncompressed().as_ref()); + pub fn vrf_hash(&self, h: &mut H) { + h.input(b"msg"); + h.input(&self.message.0[..]); + h.input(b"out"); + h.input(self.signature.0.into_affine().into_uncompressed().as_ref()); + } + + /// Raw bytes output from a BLS signature regarded as a VRF. + /// + /// If you are not the signer then you must verify the VRF before calling this method. + /// + /// If called with distinct contexts then outputs should be independent. + pub fn make_bytes>(&self, context: &[u8]) -> Out { + let mut t = Shake128::default(); + t.input(context); + self.vrf_hash(&mut t); let mut seed = Out::default(); - // h.xof_result().read(seed.as_mut()); - t.challenge_bytes(b"", seed.as_mut()); + t.xof_result().read(seed.as_mut()); seed } @@ -649,7 +657,7 @@ impl SignedMessage { /// If you are not the signer then you must verify the VRF before calling this method. /// /// We expect most users would prefer the less generic `VRFInOut::make_chacharng` method. - pub fn make_rng(&self, context: &'static [u8]) -> R { + pub fn make_rng(&self, context: &[u8]) -> R { R::from_seed(self.make_bytes::(context)) } */ @@ -665,7 +673,7 @@ impl SignedMessage { /// construction from Theorem 2 on page 32 in appendex C of /// ["Ouroboros Praos: An adaptively-secure, semi-synchronous proof-of-stake blockchain"](https://eprint.iacr.org/2017/573.pdf) /// by Bernardo David, Peter Gazi, Aggelos Kiayias, and Alexander Russell. - pub fn make_chacharng(&self, context: &'static [u8]) -> ChaChaRng { + pub fn make_chacharng(&self, context: &[u8]) -> ChaChaRng { // self.make_rng::(context) // TODO: Remove this ugly hack whenever rand gets updated to 0.5 or later let bytes = self.make_bytes::<[u8;32]>(context);