From 4c2424f2f0426f9ad4a55a9ed35ecd29fe87e0c7 Mon Sep 17 00:00:00 2001 From: SW van Heerden Date: Tue, 18 Jul 2023 11:29:25 +0200 Subject: [PATCH] feat: update dependancies (#185) Updates the following dependencies: tari_utilities digest blake2 sha3 bulletproofs_plus curve25519-dalek lazy_static merlin rand/rand-core borsh Some of these like digest and borsh require code changes. `Blake256` is now replaced with the raw type `Blake2b` --- Cargo.toml | 58 +++--- src/commitment.rs | 7 +- src/errors.rs | 10 +- src/ffi/keys.rs | 16 +- src/hash/blake2.rs | 189 ------------------ src/hash/error.rs | 14 -- src/hash/mod.rs | 6 - src/hashing.rs | 165 +++++++++------ src/lib.rs | 1 - src/ristretto/bulletproofs_plus.rs | 8 +- src/ristretto/constants.rs | 2 +- src/ristretto/pedersen/commitment_factory.rs | 2 +- .../pedersen/extended_commitment_factory.rs | 4 +- src/ristretto/pedersen/mod.rs | 2 +- src/ristretto/ristretto_com_and_pub_sig.rs | 37 ++-- src/ristretto/ristretto_com_sig.rs | 36 ++-- src/ristretto/ristretto_keys.rs | 47 +++-- src/ristretto/ristretto_sig.rs | 39 ++-- src/ristretto/utils.rs | 4 +- src/signatures/commitment_signature.rs | 2 +- src/signatures/schnorr.rs | 9 +- src/wasm/key_utils.rs | 18 +- 22 files changed, 262 insertions(+), 414 deletions(-) delete mode 100644 src/hash/blake2.rs delete mode 100644 src/hash/error.rs delete mode 100644 src/hash/mod.rs diff --git a/Cargo.toml b/Cargo.toml index 5768c594..71adbfea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,46 +11,37 @@ version = "0.17.0" edition = "2018" [dependencies] -tari_utilities = { version = "0.4.10" } - -base64 = "0.10.1" -blake2 = "0.9.1" -borsh = { version = "0.9.3", optional = true } -bulletproofs = { package = "tari_bulletproofs", version= "4.4.1" } -bulletproofs_plus = { package = "tari_bulletproofs_plus", version="0.2.3" } -curve25519-dalek = {package="tari-curve25519-dalek", version = "4.0.2", default-features = false, features = ["serde", "alloc"] } -digest = "0.9.0" -getrandom = { version = "0.2.3", default-features = false, optional = true } -lazy_static = "1.3.0" -log = "0.4.0" -merlin = { version = "2.0.1", default-features = false } -once_cell = "1.8.0" -rand = { version = "0.7.3", default-features = false } -rand_chacha = "0.3.1" -rand_core = "0.6.4" -serde = "1.0" -serde_json = "1.0" +tari_utilities = { version = "0.5", features = ["zero", "std"] } +blake2 = { version = "0.10" } +borsh = { version = "0.10" , optional = true } +bulletproofs_plus = { package = "tari_bulletproofs_plus", version = "0.3.1" } +curve25519-dalek = { package = "tari-curve25519-dalek", version = "4.0.3", default-features = false, features = ["serde", "alloc", "rand_core", "precomputed-tables"] } +digest = { version = "0.10" } +getrandom = { version = "0.2" } +lazy_static = { version = "1.3" } +log = { version = "0.4" } +once_cell = { version = "1.8" } +rand_chacha = { version = "0.3" } +rand_core = { version = "0.6" } +serde = { version = "1.0" } serde-wasm-bindgen = { version = "0.4", optional = true } -sha3 = "0.9.0" -thiserror = "1.0.20" +sha3 = { version = "0.10" } +thiserror = { version = "1.0" } wasm-bindgen = { version = "^0.2", features = ["serde-serialize"], optional = true } -zeroize = "1" +zeroize = {version = "1" } +rand = { version = "0.8" } [dev-dependencies] -bincode = "1.1.4" -criterion = "0.3.4" -rand_chacha = "0.3.1" -sha2 = "0.9.5" -wasm-bindgen-test = "0.3.24" +bincode = { version = "1.1" } +criterion = { version = "0.5", default-features = false } +sha2 = { version = "0.10" } +wasm-bindgen-test = { version = "0.3" } [build-dependencies] -cbindgen = "0.17.0" +cbindgen = {version = "0.24" } [features] -default = ["u64_backend"] -u64_backend = ["curve25519-dalek/u64_backend"] -simd_backend = ["curve25519-dalek/simd_backend", "bulletproofs/simd_backend"] -wasm = ["wasm-bindgen", "getrandom/js", "rand/wasm-bindgen", "serde-wasm-bindgen"] +wasm = ["wasm-bindgen", "getrandom/js", "serde-wasm-bindgen"] ffi = [] musig = [] @@ -66,3 +57,6 @@ harness = false [package.metadata.wasm-pack.profile.release] wasm-opt = ["-Oz"] + +[package.metadata.cargo-machete] +ignored = ["getrandom"] \ No newline at end of file diff --git a/src/commitment.rs b/src/commitment.rs index 06b47356..faa8c13b 100644 --- a/src/commitment.rs +++ b/src/commitment.rs @@ -37,8 +37,9 @@ pub struct HomomorphicCommitment

(pub(crate) P); #[cfg(feature = "borsh")] impl borsh::BorshDeserialize for HomomorphicCommitment

{ - fn deserialize(buf: &mut &[u8]) -> std::io::Result { - Ok(Self(P::deserialize(buf)?)) + fn deserialize_reader(reader: &mut R) -> Result + where R: std::io::Read { + Ok(Self(P::deserialize_reader(reader)?)) } } @@ -80,7 +81,7 @@ impl

PartialOrd for HomomorphicCommitment

where P: PublicKey { fn partial_cmp(&self, other: &Self) -> Option { - Some(self.0.cmp(&other.0)) + Some(self.cmp(other)) } } diff --git a/src/errors.rs b/src/errors.rs index 1776b846..6a0b440a 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -45,13 +45,19 @@ pub enum HashingError { #[error("The input to the hashing function is too short.")] InputTooShort, /// Converting a byte string into a secret key failed - #[error("Converting a byte string into a secret key failed. {0}")] - ConversionFromBytes(#[from] ByteArrayError), + #[error("Converting a byte string into a secret key failed: {0}")] + ConversionFromBytes(String), /// The digest does not produce enough output #[error("The digest does produce enough output. {0} bytes are required.")] DigestTooShort(usize), } +impl From for HashingError { + fn from(byte_error: ByteArrayError) -> Self { + HashingError::ConversionFromBytes(byte_error.to_string()) + } +} + /// Errors encountered when copying to a buffer #[derive(Debug, Clone, Error, PartialEq, Eq, Serialize, Deserialize)] pub enum SliceError { diff --git a/src/ffi/keys.rs b/src/ffi/keys.rs index d4a15c57..98aca9c4 100644 --- a/src/ffi/keys.rs +++ b/src/ffi/keys.rs @@ -6,14 +6,14 @@ use std::{ os::raw::{c_char, c_int}, }; -use digest::Digest; +use blake2::Blake2b; +use digest::{consts::U32, Digest}; use rand::rngs::OsRng; use tari_utilities::ByteArray; use crate::{ commitment::{HomomorphicCommitment, HomomorphicCommitmentFactory}, ffi::error::{INVALID_SECRET_KEY_SER, NULL_POINTER, OK, SIGNING_ERROR, STR_CONV_ERR}, - hash::blake2::Blake256, keys::{PublicKey, SecretKey}, ristretto::{ pedersen::commitment_factory::PedersenCommitmentFactory, @@ -79,7 +79,7 @@ pub unsafe extern "C" fn sign( Ok(s) => s, _ => return STR_CONV_ERR, }; - let e = RistrettoSchnorr::construct_domain_separated_challenge::<_, Blake256>(&pub_r, &pubkey, msg.as_bytes()); + let e = RistrettoSchnorr::construct_domain_separated_challenge::<_, Blake2b>(&pub_r, &pubkey, msg.as_bytes()); let sig = match RistrettoSchnorr::sign_raw(&k, r, e.as_ref()) { Ok(sig) => sig, _ => return SIGNING_ERROR, @@ -200,7 +200,7 @@ pub unsafe extern "C" fn sign_comsig( Ok(s) => s, _ => return STR_CONV_ERR, }; - let challenge = Blake256::digest(msg.as_bytes()).to_vec(); + let challenge = Blake2b::::digest(msg.as_bytes()).to_vec(); let factory = PedersenCommitmentFactory::default(); let sig = match RistrettoComSig::sign(&secret_a, &secret_x, &nonce_a, &nonce_x, &challenge, &factory) { Ok(sig) => sig, @@ -254,7 +254,7 @@ pub unsafe extern "C" fn verify_comsig( _ => return false, }; let sig = RistrettoComSig::new(r_pub, u, v); - let challenge = Blake256::digest(msg.as_bytes()); + let challenge = Blake2b::::digest(msg.as_bytes()); let challenge = match RistrettoSecretKey::from_bytes(challenge.as_slice()) { Ok(e) => e, _ => return false, @@ -314,7 +314,7 @@ pub unsafe extern "C" fn sign_comandpubsig( Ok(s) => s, _ => return STR_CONV_ERR, }; - let challenge = Blake256::digest(msg.as_bytes()).to_vec(); + let challenge = Blake2b::::digest(msg.as_bytes()).to_vec(); let factory = PedersenCommitmentFactory::default(); let sig = match RistrettoComAndPubSig::sign(&a, &x, &y, &r_a, &r_x, &r_y, &challenge, &factory) { Ok(sig) => sig, @@ -394,7 +394,7 @@ pub unsafe extern "C" fn verify_comandpubsig( _ => return false, }; let sig = RistrettoComAndPubSig::new(ephemeral_commitment, ephemeral_pubkey, u_a, u_x, u_y); - let challenge = Blake256::digest(msg.as_bytes()); + let challenge = Blake2b::::digest(msg.as_bytes()); let challenge = match RistrettoSecretKey::from_bytes(challenge.as_slice()) { Ok(e) => e, _ => return false, @@ -438,7 +438,7 @@ mod test { } assert_ne!(priv_key, priv_key_before); assert_eq!( - RistrettoPublicKey::from_secret_key(&RistrettoSecretKey(Scalar::from_bits(priv_key))).as_bytes(), + RistrettoPublicKey::from_secret_key(&RistrettoSecretKey(Scalar::from_bytes_mod_order(priv_key))).as_bytes(), pub_key ); } diff --git a/src/hash/blake2.rs b/src/hash/blake2.rs deleted file mode 100644 index 8f1b3ea7..00000000 --- a/src/hash/blake2.rs +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2020. The Tari Project -// SPDX-License-Identifier: BSD-3-Clause - -//! A convenience wrapper produce 256 bit hashes from Blake2b - -use blake2::{digest::VariableOutput, VarBlake2b}; -use digest::{ - consts::{U32, U64}, - generic_array::{typenum::Unsigned, GenericArray}, - FixedOutput, - Reset, - Update, -}; - -use super::error::HashError; -use crate::hashing::LengthExtensionAttackResistant; - -/// A convenience wrapper produce 256 bit hashes from Blake2b -#[derive(Clone, Debug)] -pub struct Blake256(VarBlake2b); - -impl Blake256 { - /// Constructs a `Blake256` hashing context with parameters that allow hash keying, salting and personalization. - pub fn with_params(key: &[u8], salt: &[u8], persona: &[u8]) -> Result { - Self::with_params_var_size(key, salt, persona, ::OutputSize::USIZE) - } - - /// Constructs a `Blake256` hashing context with an explicitly specified output size. - pub fn with_params_var_size( - key: &[u8], - salt: &[u8], - persona: &[u8], - output_size: usize, - ) -> Result { - if key.len() > 64 || salt.len() > 16 || persona.len() > 16 || output_size < 1 || output_size > U64::to_usize() { - Err(HashError::WrongLength) - } else { - Ok(Self(VarBlake2b::with_params(key, salt, persona, output_size))) - } - } -} - -impl Default for Blake256 { - fn default() -> Self { - let h = VariableOutput::new(::OutputSize::USIZE).unwrap(); - Blake256(h) - } -} - -impl FixedOutput for Blake256 { - type OutputSize = U32; - - fn finalize_into(self, out: &mut GenericArray) { - self.0.finalize_variable(|res| out.copy_from_slice(res)); - } - - fn finalize_into_reset(&mut self, out: &mut GenericArray) { - self.0.finalize_variable_reset(|res| out.copy_from_slice(res)); - } -} - -impl Reset for Blake256 { - fn reset(&mut self) { - (self.0).reset() - } -} - -impl Update for Blake256 { - fn update(&mut self, data: impl AsRef<[u8]>) { - self.0.update(data); - } -} - -impl LengthExtensionAttackResistant for Blake256 {} - -#[cfg(test)] -mod test { - use blake2::digest::FixedOutput; - use digest::{generic_array::GenericArray, Digest}; - use tari_utilities::hex; - - use crate::hash::blake2::Blake256; - - #[test] - fn blake256() { - let e = Blake256::new().chain(b"one").chain(b"two").finalize().to_vec(); - let h = hex::to_hex(&e); - assert_eq!( - h.as_str(), - "03521c1777639fc6e5c3d8c3b4600870f18becc155ad7f8053d2c65bc78e4aa0" - ); - } - - #[test] - fn reset() { - let mut e = Blake256::default().chain(b"foobar"); - e.reset(); - let v = e.chain(b"onetwo").finalize().to_vec(); - let h = hex::to_hex(&v); - assert_eq!( - h.as_str(), - "03521c1777639fc6e5c3d8c3b4600870f18becc155ad7f8053d2c65bc78e4aa0" - ); - } - - #[test] - fn finalise_reset() { - let mut e = Blake256::default().chain(b"onetwo"); - let mut out = GenericArray::default(); - e.finalize_into_reset(&mut out); - let h = hex::to_hex(out.as_slice()); - assert_eq!( - h.as_str(), - "03521c1777639fc6e5c3d8c3b4600870f18becc155ad7f8053d2c65bc78e4aa0" - ); - let v = e.chain(b"onetwo").finalize().to_vec(); - let h = hex::to_hex(&v); - assert_eq!( - h.as_str(), - "03521c1777639fc6e5c3d8c3b4600870f18becc155ad7f8053d2c65bc78e4aa0" - ); - } - - #[test] - fn derived_functions() { - let mut e = Blake256::default(); - e.update(b"onetwo"); - // test Clone impl - let e2 = e.clone(); - // test Debug impl - assert_eq!(format!("{e:?}"), "Blake256(VarBlake2b { ... })"); - assert_eq!(e.finalize(), e2.finalize()); - } - - #[test] - fn personalisation() { - let default = Blake256::new().chain(b"onetwo").finalize(); - let personalised = Blake256::with_params(&[], &[], b"unit-test") - .unwrap() - .chain(b"onetwo") - .finalize(); - let salted = Blake256::with_params(&[], b"unit-test", &[]) - .unwrap() - .chain(b"onetwo") - .finalize(); - let keyed = Blake256::with_params(&[1u8; 64], &[], &[]) - .unwrap() - .chain(b"onetwo") - .finalize(); - - assert_ne!(default, personalised); - assert_ne!(default, salted); - assert_ne!(salted, personalised); - assert_ne!(salted, keyed); - assert_ne!(keyed, personalised); - assert_ne!(keyed, salted); - } - - #[test] - fn bad_parameters() { - // A valid key is at most 64 bytes - let key = [1u8; 64]; - let bad_key = [1u8; 65]; - - // A valid salt is at most 16 bytes - let salt = [1u8; 16]; - let bad_salt = [1u8; 17]; - - // A valid persona is at most 16 bytes - let persona = [1u8; 16]; - let bad_persona = [1u8; 17]; - - // A valid output is at least 1 byte and at most 64 bytes - let output = 64; - let bad_output_short = 0; - let bad_output_long = 65; - - // Valid parameter sets - assert!(Blake256::with_params(&key, &salt, &persona).is_ok()); - assert!(Blake256::with_params_var_size(&key, &salt, &persona, output).is_ok()); - - // Invalid parameter sets - assert!(Blake256::with_params(&bad_key, &salt, &persona).is_err()); - assert!(Blake256::with_params(&key, &bad_salt, &persona).is_err()); - assert!(Blake256::with_params(&key, &salt, &bad_persona).is_err()); - assert!(Blake256::with_params_var_size(&key, &salt, &persona, bad_output_short).is_err()); - assert!(Blake256::with_params_var_size(&key, &salt, &persona, bad_output_long).is_err()); - } -} diff --git a/src/hash/error.rs b/src/hash/error.rs deleted file mode 100644 index 38e88141..00000000 --- a/src/hash/error.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2022. The Tari Project -// SPDX-License-Identifier: BSD-3-Clause - -//! Error types for hash funcions - -use thiserror::Error; - -/// Hash error type -#[derive(Debug, Error)] -pub enum HashError { - /// Length of input data exceeded a limit - #[error("wrong length")] - WrongLength, -} diff --git a/src/hash/mod.rs b/src/hash/mod.rs deleted file mode 100644 index 3b1fcadc..00000000 --- a/src/hash/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2020. The Tari Project -// SPDX-License-Identifier: BSD-3-Clause - -//! Convenience wrappers for hash functions -pub mod blake2; -pub mod error; diff --git a/src/hashing.rs b/src/hashing.rs index 7d81567c..903f9b0a 100644 --- a/src/hashing.rs +++ b/src/hashing.rs @@ -30,8 +30,8 @@ use std::{marker::PhantomData, ops::Deref}; -use blake2::VarBlake2b; -use digest::{Digest, FixedOutput, Output, Update}; +use blake2::{Blake2b, Blake2bVar}; +use digest::{consts::U32, Digest, FixedOutput, FixedOutputReset, Output, OutputSizeUser, Update}; use sha3::Sha3_256; use tari_utilities::ByteArray; @@ -40,8 +40,8 @@ use crate::{ keys::SecretKey, }; -/// The `DomainSeparation` trait is used to inject domain separation tags into the [`DomainSeparatedHasher`] in a way -/// that can be applied consistently, but without hard-coding anything into the hasher itself. +/// The `DomainSeparation` trait is used to inject domain separation tags into the [`DomainSeparatedHasher`] in a +/// way that can be applied consistently, but without hard-coding anything into the hasher itself. /// /// Using a trait is more flexible than const strings, and lets us leverage the type system to have more fine-grained /// control over allowable use cases. @@ -126,7 +126,7 @@ fn byte_to_decimal_ascii_bytes(mut byte: u8) -> (usize, [u8; 3]) { /// `DomainSeparatedHash` implements `AsRef`, so it is easy to use this type as a slice. /// /// The domain separation information is retained with the hash, and can be queried using -/// [`DomainSeparatedHash::domain_separation_tag_string`]. +/// [`DomainSeparatedHash::domain_separation_tag("")`]. /// /// To preserve the guarantee that the hash is properly domain separated, you cannot create an instance of this struct /// directly. It is the result of using [`DomainSeparatedHasher`]. @@ -174,6 +174,7 @@ impl AsRef<[u8]> for DomainSeparatedHash { /// # use sha2::Sha256; /// # use tari_crypto::{hash_domain, hashing::{ DomainSeparatedHash, DomainSeparatedHasher, DomainSeparation}}; /// # use tari_utilities::hex::{to_hex, Hex}; +/// # use blake2::Blake2b; /// /// hash_domain!(CardHashDomain, "com.cards"); /// @@ -207,8 +208,9 @@ impl AsRef<[u8]> for DomainSeparatedHash { /// /// ``` /// # use tari_utilities::hex::{to_hex, Hex}; +/// use blake2::{Blake2b, Digest}; +/// use digest::consts::U32; /// use tari_crypto::{ -/// hash::blake2::Blake256, /// hash_domain, /// hashing::{DomainSeparatedHash, DomainSeparatedHasher, DomainSeparation}, /// }; @@ -220,9 +222,9 @@ impl AsRef<[u8]> for DomainSeparatedHash { /// strength: u8, /// } /// -/// fn calculate_challenge(msg: &str) -> DomainSeparatedHash { -/// DomainSeparatedHasher::::new_with_label("schnorr_challenge") -/// .chain(msg.as_bytes()) +/// fn calculate_challenge(msg: &str) -> DomainSeparatedHash> { +/// DomainSeparatedHasher::, CardHashDomain>::new_with_label("schnorr_challenge") +/// .chain_update(msg.as_bytes()) /// .finalize() /// } /// @@ -311,35 +313,54 @@ pub trait AsFixedBytes: AsRef<[u8]> { } } +impl OutputSizeUser + for DomainSeparatedHasher +{ + type OutputSize = TInnerDigest::OutputSize; +} + +impl Update for DomainSeparatedHasher { + fn update(&mut self, data: &[u8]) { + self.inner.update(data); + } +} + impl AsFixedBytes for DomainSeparatedHash {} impl FixedOutput for DomainSeparatedHasher { - type OutputSize = TInnerDigest::OutputSize; - - fn finalize_into(self, out: &mut digest::generic_array::GenericArray) { + fn finalize_into(self, out: &mut Output) { self.inner.finalize_into(out); } +} - fn finalize_into_reset(&mut self, out: &mut digest::generic_array::GenericArray) { +impl DomainSeparatedHasher { + /// Finalize and reset the hasher and return the hash result. + pub fn finalize_into_reset(&mut self, out: &mut Output) { self.inner.finalize_into_reset(out); } } -/// Implements Digest so that it can be used for other crates -impl Digest for DomainSeparatedHasher { - type OutputSize = TInnerDigest::OutputSize; - +// Implements Digest so that it can be used for other crates +impl Digest + for DomainSeparatedHasher +{ fn new() -> Self { DomainSeparatedHasher::::new() } + // Create new hasher instance which has processed the provided data. + fn new_with_prefix(data: impl AsRef<[u8]>) -> Self { + let hasher = DomainSeparatedHasher::::new(); + hasher.chain_update(data) + } + fn update(&mut self, data: impl AsRef<[u8]>) { self.update(data); } - fn chain(self, data: impl AsRef<[u8]>) -> Self + fn chain_update(self, data: impl AsRef<[u8]>) -> Self where Self: Sized { self.chain(data) } @@ -354,16 +375,25 @@ impl Digest for DomainSeparated value } + fn finalize_into_reset(&mut self, out: &mut Output) { + Digest::finalize_into_reset(&mut self.inner, out); + } + + // Write result into provided array and consume the hasher instance. + fn finalize_into(self, out: &mut Output) { + Digest::finalize_into(self.inner, out); + } + fn reset(&mut self) { - self.inner.reset(); + Digest::reset(&mut self.inner); TDomain::add_domain_separation_tag(&mut self.inner, self.label); } fn output_size() -> usize { - TInnerDigest::output_size() + ::output_size() } - fn digest(data: &[u8]) -> Output { + fn digest(data: impl AsRef<[u8]>) -> Output { let mut hasher = Self::new(); hasher.update(data); hasher.finalize().output @@ -377,10 +407,12 @@ impl Digest for DomainSeparated /// Notably, the SHA-2 family does *not* have this trait. pub trait LengthExtensionAttackResistant {} -impl LengthExtensionAttackResistant for VarBlake2b {} +impl LengthExtensionAttackResistant for Blake2bVar {} impl LengthExtensionAttackResistant for Sha3_256 {} +impl LengthExtensionAttackResistant for Blake2b {} + //------------------------------------------------ HMAC ------------------------------------------------------------ /// A domain separation tag for use in MAC derivation algorithms. pub struct MacDomain; @@ -477,23 +509,28 @@ impl Deref for Mac { /// /// ## Example /// -/// [`RistrettoKdf`] is an implementation of [`DerivedKeyDomain`] that generates Ristretto keys. +/// `RistrettoKdf` is an implementation of [`DerivedKeyDomain`] that generates Ristretto keys. /// /// ``` /// # use tari_utilities::ByteArray; /// # use tari_utilities::hex::Hex; -/// # use tari_crypto::hash::blake2::Blake256; /// # use tari_crypto::errors::HashingError; /// # use tari_crypto::hashing::{DerivedKeyDomain, MacDomain}; /// # use tari_crypto::keys::SecretKey; /// # use tari_crypto::ristretto::ristretto_keys::RistrettoKdf; /// # use tari_crypto::ristretto::RistrettoSecretKey; +/// # use digest::consts::U32; +/// # use blake2::Blake2b; /// /// fn wallet_keys( /// primary_key: &RistrettoSecretKey, /// index: usize, /// ) -> Result { -/// RistrettoKdf::generate::(primary_key.as_bytes(), &index.to_le_bytes(), "wallet") +/// RistrettoKdf::generate::>( +/// primary_key.as_bytes(), +/// &index.to_le_bytes(), +/// "wallet", +/// ) /// } /// /// let key = RistrettoSecretKey::from_hex( @@ -523,8 +560,8 @@ pub trait DerivedKeyDomain: DomainSeparation { Self: Sized, D: Digest + Update, { - if primary_key.as_ref().len() < D::output_size() { - return Err(HashingError::InputTooShort); + if primary_key.as_ref().len() < ::output_size() { + return Err(HashingError::InputTooShort {}); } let hash = DomainSeparatedHasher::::new_with_label(label) .chain(primary_key) @@ -590,12 +627,21 @@ pub fn create_hasher() -> DomainSeparatedHasher #[cfg(test)] mod test { use blake2::Blake2b; - use digest::{generic_array::GenericArray, Digest, FixedOutput}; + use digest::{ + consts::{U32, U64}, + generic_array::GenericArray, + Digest, + Update, + }; use tari_utilities::hex::{from_hex, to_hex}; - use crate::{ - hash::blake2::Blake256, - hashing::{byte_to_decimal_ascii_bytes, AsFixedBytes, DomainSeparatedHasher, DomainSeparation, Mac, MacDomain}, + use crate::hashing::{ + byte_to_decimal_ascii_bytes, + AsFixedBytes, + DomainSeparatedHasher, + DomainSeparation, + Mac, + MacDomain, }; mod util { @@ -619,7 +665,7 @@ mod test { #[test] fn hasher_macro_tests() { { - hasher!(Blake256, MyDemoHasher, "com.macro.test"); + hasher!(Blake2b, MyDemoHasher, "com.macro.test"); util::hash_from_digest( MyDemoHasher::new(), @@ -628,7 +674,7 @@ mod test { ); } { - hasher!(Blake256, MyDemoHasher2, "com.macro.test", 1); + hasher!(Blake2b, MyDemoHasher2, "com.macro.test", 1); util::hash_from_digest( MyDemoHasher2::new(), @@ -650,20 +696,20 @@ mod test { #[test] fn finalize_into() { hash_domain!(TestHasher, "com.example.test"); - let mut hasher = DomainSeparatedHasher::::new(); + let mut hasher = DomainSeparatedHasher::, TestHasher>::new(); hasher.update([0, 0, 0]); - let mut output = GenericArray::::OutputSize>::default(); + let mut output = GenericArray::::default(); hasher.finalize_into(&mut output); } #[test] fn finalize_into_reset() { hash_domain!(TestHasher, "com.example.test"); - let mut hasher = DomainSeparatedHasher::::new(); + let mut hasher = DomainSeparatedHasher::, TestHasher>::new(); hasher.update([0, 0, 0]); - let mut output = GenericArray::::OutputSize>::default(); + let mut output = GenericArray::::default(); hasher.finalize_into_reset(&mut output); } @@ -673,7 +719,7 @@ mod test { use zeroize::Zeroize; hash_domain!(TestHasher, "com.example.test"); - let mut hasher = DomainSeparatedHasher::::new(); + let mut hasher = DomainSeparatedHasher::, TestHasher>::new(); hasher.update([0, 0, 0]); hidden_type!(Key, SafeArray); @@ -685,10 +731,10 @@ mod test { fn dst_hasher() { hash_domain!(GenericHashDomain, "com.tari.generic"); assert_eq!(GenericHashDomain::domain_separation_tag(""), "com.tari.generic.v1"); - let hash = DomainSeparatedHasher::::new_with_label("test_hasher") + let hash = DomainSeparatedHasher::, GenericHashDomain>::new_with_label("test_hasher") .chain("some foo") .finalize(); - let mut hash2 = DomainSeparatedHasher::::new_with_label("test_hasher"); + let mut hash2 = DomainSeparatedHasher::, GenericHashDomain>::new_with_label("test_hasher"); hash2.update("some foo"); let hash2 = hash2.finalize(); assert_eq!(hash.as_ref(), hash2.as_ref()); @@ -698,8 +744,8 @@ mod test { ); let hash_1 = - DomainSeparatedHasher::::new_with_label("mynewtest").digest(b"rincewind"); - let hash_2 = DomainSeparatedHasher::::new_with_label("mynewtest") + DomainSeparatedHasher::, GenericHashDomain>::new_with_label("mynewtest").digest(b"rincewind"); + let hash_2 = DomainSeparatedHasher::, GenericHashDomain>::new_with_label("mynewtest") .chain(b"rincewind") .finalize(); assert_eq!(hash_1.as_ref(), hash_2.as_ref()); @@ -709,12 +755,12 @@ mod test { fn digest_is_the_same_as_standard_api() { hash_domain!(MyDemoHasher, "com.macro.test"); assert_eq!(MyDemoHasher::domain_separation_tag(""), "com.macro.test.v1"); - util::hash_test::>( + util::hash_test::, MyDemoHasher>>( &[0, 0, 0], "d4cbf5b6b97485a991973db8a6ce4d3fc660db5dff5f55f2b0cb363fca34b0a2", ); - let mut hasher = DomainSeparatedHasher::::new(); + let mut hasher = DomainSeparatedHasher::, MyDemoHasher>::new(); hasher.update([0, 0, 0]); let hash = hasher.finalize(); assert_eq!( @@ -722,7 +768,7 @@ mod test { "d4cbf5b6b97485a991973db8a6ce4d3fc660db5dff5f55f2b0cb363fca34b0a2" ); - let mut hasher = DomainSeparatedHasher::::new_with_label(""); + let mut hasher = DomainSeparatedHasher::, MyDemoHasher>::new_with_label(""); hasher.update([0, 0, 0]); let hash = hasher.finalize(); assert_eq!( @@ -736,21 +782,21 @@ mod test { fn can_be_used_as_digest() { hash_domain!(MyDemoHasher, "com.macro.test"); assert_eq!(MyDemoHasher::domain_separation_tag(""), "com.macro.test.v1"); - util::hash_test::>( + util::hash_test::, MyDemoHasher>>( &[0, 0, 0], "d4cbf5b6b97485a991973db8a6ce4d3fc660db5dff5f55f2b0cb363fca34b0a2", ); hash_domain!(MyDemoHasher2, "com.macro.test", 2); assert_eq!(MyDemoHasher2::domain_separation_tag(""), "com.macro.test.v2"); - util::hash_test::>( + util::hash_test::, MyDemoHasher2>>( &[0, 0, 0], "ce327b02271d035bad4dcc1e69bc292392ee4ee497f1f8467d54bf4b4c72639a", ); hash_domain!(TariHasher, "com.tari.hasher"); assert_eq!(TariHasher::domain_separation_tag(""), "com.tari.hasher.v1"); - util::hash_test::>( + util::hash_test::, TariHasher>>( &[0, 0, 0], "ae359f05bb76c646c6767d25f53893fc38b0c7b56f8a74a1cbb008ea3ffc183f", ); @@ -760,7 +806,7 @@ mod test { #[test] fn hash_to_fixed_bytes_conversion() { hash_domain!(TestDomain, "com.tari.generic"); - let hash = DomainSeparatedHasher::::new_with_label("mytest") + let hash = DomainSeparatedHasher::, TestDomain>::new_with_label("mytest") .chain("some data") .finalize(); let hash_to_bytes_7: [u8; 7] = hash.as_fixed_bytes().unwrap(); @@ -775,11 +821,11 @@ mod test { fn deconstruction() { hash_domain!(TestDomain, "com.tari.generic"); // Illustrate exactly what gets hashed and how we try and avoid collisions - let hash = DomainSeparatedHasher::::new_with_label("mytest") + let hash = DomainSeparatedHasher::, TestDomain>::new_with_label("mytest") .chain("rincewind") .chain("hex") .finalize(); - let expected = Blake256::new() + let expected = Blake2b::::new() .chain(26u64.to_le_bytes()) .chain("com.tari.generic.v1.mytest".as_bytes()) .chain(9u64.to_le_bytes()) @@ -805,21 +851,24 @@ mod test { } let domain = "com.discworld.v42.turtles"; assert_eq!(MyDemoHasher::domain_separation_tag("turtles"), domain); - let hash = DomainSeparatedHasher::::new_with_label("turtles").finalize(); - let expected = Blake2b::default() + let hash = DomainSeparatedHasher::, MyDemoHasher>::new_with_label("turtles").finalize(); + let expected = Blake2b::::default() .chain((domain.len() as u64).to_le_bytes()) .chain(domain) .finalize(); - assert_eq!(hash.as_ref(), expected.as_ref()); + assert_eq!(hash.as_ref(), expected.as_slice()); } #[test] fn update_domain_separation_tag() { hash_domain!(TestDomain, "com.test"); let s_tag = TestDomain::domain_separation_tag("mytest"); - let expected_hash = Blake256::new().chain(s_tag.len().to_le_bytes()).chain(s_tag).finalize(); + let expected_hash = Blake2b::::default() + .chain(s_tag.len().to_le_bytes()) + .chain(s_tag) + .finalize(); - let mut digest = Blake256::new(); + let mut digest = Blake2b::::default(); TestDomain::add_domain_separation_tag(&mut digest, "mytest"); assert_eq!(digest.finalize(), expected_hash); } @@ -837,7 +886,7 @@ mod test { "com.discworld" } } - let hash = DomainSeparatedHasher::::new_with_label("turtles") + let hash = DomainSeparatedHasher::, MyDemoHasher>::new_with_label("turtles") .chain("elephants") .finalize(); assert_eq!(to_hex(hash.as_ref()), "64a89c7160a1076a725fac97d3f67803abd0991d82518a595072fa62df4c870bddee9160f591231c381087831bf6925616013de317ce0b02846585caf41942ac"); @@ -850,7 +899,7 @@ mod test { // let mac = Mac::generate::(&key, "test message", "test"); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `LengthExtensionAttackResistant` is not implemented for // `Sha256` - let mac = Mac::::generate(key, "test message", "test"); + let mac = Mac::>::generate(key, "test message", "test"); assert_eq!(MacDomain::domain_separation_tag("test"), "com.tari.mac.v1.test"); assert_eq!( to_hex(mac.as_ref()), diff --git a/src/lib.rs b/src/lib.rs index 3e744feb..f64deb90 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,6 @@ mod macros; pub mod commitment; pub mod deterministic_randomizer; pub mod dhke; -pub mod hash; pub mod hashing; pub mod keys; pub mod range_proof; diff --git a/src/ristretto/bulletproofs_plus.rs b/src/ristretto/bulletproofs_plus.rs index 936f4f99..0171b8c2 100644 --- a/src/ristretto/bulletproofs_plus.rs +++ b/src/ristretto/bulletproofs_plus.rs @@ -659,7 +659,7 @@ mod test { let mut statements = vec![]; let mut extended_witnesses = vec![]; for m in 0..aggregation_size { - let value = rng.gen_range(value_min, value_max); + let value = rng.gen_range(value_min..value_max); let minimum_value_promise = if m == 0 { value / 3 } else { 0 }; let secrets = vec![RistrettoSecretKey(Scalar::random_not_zero(&mut rng)); extension_degree as usize]; @@ -797,7 +797,7 @@ mod test { let mut statements = vec![]; let mut extended_witnesses = vec![]; for _m in 0..aggregation_size { - let value = rng.gen_range(value_min, value_max); + let value = rng.gen_range(value_min..value_max); let minimum_value_promise = value / 3; let secrets = vec![RistrettoSecretKey(Scalar::random_not_zero(&mut rng)); extension_degree as usize]; @@ -851,7 +851,7 @@ mod test { provers_bulletproofs_plus_service.custom_transcript_label("123 range proof"); // 2. Create witness data - let value = rng.gen_range(value_min, value_max); + let value = rng.gen_range(value_min..value_max); let minimum_value_promise = value / 3; let secrets = vec![RistrettoSecretKey(Scalar::random_not_zero(&mut rng)); extension_degree as usize]; let extended_mask = RistrettoExtendedMask::assign(extension_degree, secrets.clone()).unwrap(); @@ -958,7 +958,7 @@ mod test { provers_bulletproofs_plus_service.custom_transcript_label("123 range proof"); // 2. Create witness data - let value = rng.gen_range(value_min, value_max); + let value = rng.gen_range(value_min..value_max); let mask = RistrettoSecretKey(Scalar::random_not_zero(&mut rng)); let commitment = factory.commit_value(&mask, value); diff --git a/src/ristretto/constants.rs b/src/ristretto/constants.rs index df1ad65b..1588cc53 100644 --- a/src/ristretto/constants.rs +++ b/src/ristretto/constants.rs @@ -133,7 +133,7 @@ mod test { #[test] pub fn check_tables() { // Perform test multiplications - assert_eq!(&*RISTRETTO_NUMS_TABLE_0 * &Scalar::zero(), RistrettoPoint::identity()); + assert_eq!(&*RISTRETTO_NUMS_TABLE_0 * &Scalar::ZERO, RistrettoPoint::identity()); for j in 0..15u8 { assert_eq!( diff --git a/src/ristretto/pedersen/commitment_factory.rs b/src/ristretto/pedersen/commitment_factory.rs index 4cb13e45..edae45a1 100644 --- a/src/ristretto/pedersen/commitment_factory.rs +++ b/src/ristretto/pedersen/commitment_factory.rs @@ -109,7 +109,7 @@ mod test { #[test] /// Verify that the identity point is equal to a commitment to zero with a zero blinding factor on the base point fn check_zero() { - let c = RistrettoPoint::multiscalar_mul(&[Scalar::zero(), Scalar::zero()], &[ + let c = RistrettoPoint::multiscalar_mul(&[Scalar::ZERO, Scalar::ZERO], &[ RISTRETTO_PEDERSEN_G, *RISTRETTO_PEDERSEN_H, ]); diff --git a/src/ristretto/pedersen/extended_commitment_factory.rs b/src/ristretto/pedersen/extended_commitment_factory.rs index 1941ccc9..5c55beaf 100644 --- a/src/ristretto/pedersen/extended_commitment_factory.rs +++ b/src/ristretto/pedersen/extended_commitment_factory.rs @@ -264,7 +264,7 @@ mod test { /// points fn check_zero_both_traits() { for extension_degree in EXTENSION_DEGREE { - let zero_values = vec![Scalar::zero(); extension_degree as usize + 1]; + let zero_values = vec![Scalar::ZERO; extension_degree as usize + 1]; let mut points = Vec::with_capacity(extension_degree as usize + 1); let factory = ExtendedPedersenCommitmentFactory::new_with_extension_degree(extension_degree).unwrap(); points.push(factory.h_base); @@ -407,7 +407,7 @@ mod test { fn scalar_random_not_zero(rng: &mut ThreadRng) -> Scalar { loop { let value = Scalar::random(rng); - if value != Scalar::zero() { + if value != Scalar::ZERO { return value; } } diff --git a/src/ristretto/pedersen/mod.rs b/src/ristretto/pedersen/mod.rs index 47f294b7..8e7c2af0 100644 --- a/src/ristretto/pedersen/mod.rs +++ b/src/ristretto/pedersen/mod.rs @@ -52,7 +52,7 @@ where T: Borrow } pub(crate) fn scalar_mul_with_pre_computation_tables(k: &Scalar, v: &Scalar) -> RistrettoPoint { - &RISTRETTO_BASEPOINT_TABLE * k + &*RISTRETTO_NUMS_TABLE_0 * v + RISTRETTO_BASEPOINT_TABLE * k + &*RISTRETTO_NUMS_TABLE_0 * v } #[cfg(test)] diff --git a/src/ristretto/ristretto_com_and_pub_sig.rs b/src/ristretto/ristretto_com_and_pub_sig.rs index 3ce9ad8a..907b5beb 100644 --- a/src/ristretto/ristretto_com_and_pub_sig.rs +++ b/src/ristretto/ristretto_com_and_pub_sig.rs @@ -42,12 +42,13 @@ use crate::{ /// ```rust /// # use tari_crypto::ristretto::*; /// # use tari_crypto::keys::*; -/// # use tari_crypto::hash::blake2::Blake256; +/// # use blake2::Blake2b; /// # use digest::Digest; /// # use tari_crypto::commitment::HomomorphicCommitmentFactory; /// # use tari_crypto::ristretto::pedersen::*; /// use tari_crypto::ristretto::pedersen::commitment_factory::PedersenCommitmentFactory; /// use tari_utilities::hex::Hex; +/// use digest::consts::U32; /// /// let mut rng = rand::thread_rng(); /// let a_val = RistrettoSecretKey::random(&mut rng); @@ -56,7 +57,7 @@ use crate::{ /// let a_nonce = RistrettoSecretKey::random(&mut rng); /// let x_nonce = RistrettoSecretKey::random(&mut rng); /// let y_nonce = RistrettoSecretKey::random(&mut rng); -/// let e = Blake256::digest(b"Maskerade"); // In real life, this should be strong Fiat-Shamir! +/// let e = Blake2b::::digest(b"Maskerade"); // In real life, this should be strong Fiat-Shamir! /// let factory = PedersenCommitmentFactory::default(); /// let commitment = factory.commit(&x_val, &a_val); /// let pubkey = RistrettoPublicKey::from_secret_key(&y_val); @@ -70,12 +71,12 @@ pub type RistrettoComAndPubSig = CommitmentAndPublicKeySignature::new() + .chain_update(commitment.as_bytes()) + .chain_update(pubkey.as_bytes()) + .chain_update(ephemeral_commitment.as_bytes()) + .chain_update(ephemeral_pubkey.as_bytes()) + .chain_update(b"Small Gods") .finalize(); let e_key = RistrettoSecretKey::from_bytes(&challenge).unwrap(); @@ -177,7 +178,7 @@ mod test { assert!(!sig.verify_challenge(&commitment, &evil_pubkey, &challenge, &factory, &mut rng)); // A different challenge should fail - let evil_challenge = Blake256::digest(b"Guards! Guards!"); + let evil_challenge = Blake2b::::digest(b"Guards! Guards!"); assert!(!sig.verify_challenge(&commitment, &pubkey, &evil_challenge, &factory, &mut rng)); } @@ -204,12 +205,12 @@ mod test { let ephemeral_pubkey = RistrettoPublicKey::from_secret_key(&r_y); // Challenge; doesn't use proper Fiat-Shamir, so it's for testing only! - let challenge = Blake256::new() - .chain(commitment.as_bytes()) - .chain(pubkey.as_bytes()) - .chain(ephemeral_commitment.as_bytes()) - .chain(ephemeral_pubkey.as_bytes()) - .chain(b"Small Gods") + let challenge = Blake2b::::new() + .chain_update(commitment.as_bytes()) + .chain_update(pubkey.as_bytes()) + .chain_update(ephemeral_commitment.as_bytes()) + .chain_update(ephemeral_pubkey.as_bytes()) + .chain_update(b"Small Gods") .finalize(); let sig_total = @@ -291,7 +292,7 @@ mod test { let ephemeral_pubkey_bob = RistrettoPublicKey::from_secret_key(&r_y_bob); // The challenge is common to Alice and Bob; here we use an arbitrary hash - let challenge = Blake256::digest(b"Test challenge"); + let challenge = Blake2b::::digest(b"Test challenge"); // Alice's signature let sig_alice = RistrettoComAndPubSig::sign( diff --git a/src/ristretto/ristretto_com_sig.rs b/src/ristretto/ristretto_com_sig.rs index 6e506e7e..6e81fc73 100644 --- a/src/ristretto/ristretto_com_sig.rs +++ b/src/ristretto/ristretto_com_sig.rs @@ -37,19 +37,20 @@ use crate::{ /// ```rust /// # use tari_crypto::ristretto::*; /// # use tari_crypto::keys::*; -/// # use tari_crypto::hash::blake2::Blake256; /// # use digest::Digest; /// # use tari_crypto::commitment::HomomorphicCommitmentFactory; /// # use tari_crypto::ristretto::pedersen::*; /// use tari_crypto::ristretto::pedersen::commitment_factory::PedersenCommitmentFactory; /// use tari_utilities::hex::Hex; +/// use blake2::Blake2b; +/// use digest::consts::U32; /// /// let mut rng = rand::thread_rng(); /// let a_val = RistrettoSecretKey::random(&mut rng); /// let x_val = RistrettoSecretKey::random(&mut rng); /// let a_nonce = RistrettoSecretKey::random(&mut rng); /// let x_nonce = RistrettoSecretKey::random(&mut rng); -/// let e = Blake256::digest(b"Maskerade"); +/// let e = Blake2b::::digest(b"Maskerade"); /// let factory = PedersenCommitmentFactory::default(); /// let commitment = factory.commit(&x_val, &a_val); /// // println!("commitment: {:?}", commitment.to_hex()); @@ -68,10 +69,11 @@ use crate::{ /// # use tari_crypto::keys::*; /// # use tari_crypto::commitment::HomomorphicCommitment; /// # use tari_crypto::ristretto::pedersen::*; -/// # use tari_crypto::hash::blake2::Blake256; /// # use tari_utilities::hex::*; /// # use tari_utilities::ByteArray; /// # use digest::Digest; +/// use blake2::Blake2b; +/// use digest::consts::U32; /// use tari_crypto::ristretto::pedersen::commitment_factory::PedersenCommitmentFactory; /// /// let commitment = HomomorphicCommitment::from_hex( @@ -91,7 +93,7 @@ use crate::{ /// ) /// .unwrap(); /// let sig = RistrettoComSig::new(r_nonce, u, v); -/// let e = Blake256::digest(b"Maskerade"); +/// let e = Blake2b::::digest(b"Maskerade"); /// let factory = PedersenCommitmentFactory::default(); /// assert!(sig.verify_challenge(&commitment, &e, &factory)); /// ``` @@ -99,12 +101,12 @@ pub type RistrettoComSig = CommitmentSignature::new() + .chain_update(commitment.as_bytes()) + .chain_update(nonce_commitment.as_bytes()) + .chain_update(b"Small Gods") .finalize(); let e_key = RistrettoSecretKey::from_bytes(&challenge).unwrap(); let u_value = &k_1 + e_key.clone() * &x_value; @@ -157,7 +159,7 @@ mod test { // Doesn't work for invalid credentials assert!(!sig.verify_challenge(&nonce_commitment, &challenge, &factory)); // Doesn't work for different challenge - let wrong_challenge = Blake256::digest(b"Guards! Guards!"); + let wrong_challenge = Blake2b::::digest(b"Guards! Guards!"); assert!(!sig.verify_challenge(&commitment, &wrong_challenge, &factory)); } @@ -183,12 +185,12 @@ mod test { let k_2_bob = RistrettoSecretKey::random(&mut rng); let nonce_commitment_bob = factory.commit(&k_1_bob, &k_2_bob); // Each of them creates the Challenge committing to both commitments of both parties - let challenge = Blake256::new() - .chain(commitment_alice.as_bytes()) - .chain(commitment_bob.as_bytes()) - .chain(nonce_commitment_alice.as_bytes()) - .chain(nonce_commitment_bob.as_bytes()) - .chain(b"Moving Pictures") + let challenge = Blake2b::::new() + .chain_update(commitment_alice.as_bytes()) + .chain_update(commitment_bob.as_bytes()) + .chain_update(nonce_commitment_alice.as_bytes()) + .chain_update(nonce_commitment_bob.as_bytes()) + .chain_update(b"Moving Pictures") .finalize(); // Calculate Alice's signature let sig_alice = RistrettoComSig::sign( diff --git a/src/ristretto/ristretto_keys.rs b/src/ristretto/ristretto_keys.rs index 5fb7b647..665ca318 100644 --- a/src/ristretto/ristretto_keys.rs +++ b/src/ristretto/ristretto_keys.rs @@ -19,7 +19,10 @@ use curve25519_dalek::{ scalar::Scalar, traits::MultiscalarMul, }; -use digest::Digest; +use digest::{ + consts::{U32, U64}, + Digest, +}; use once_cell::sync::OnceCell; use rand::{CryptoRng, Rng}; use tari_utilities::{hex::Hex, ByteArray, ByteArrayError, Hashable}; @@ -64,8 +67,9 @@ impl borsh::BorshSerialize for RistrettoSecretKey { #[cfg(feature = "borsh")] impl borsh::BorshDeserialize for RistrettoSecretKey { - fn deserialize(buf: &mut &[u8]) -> io::Result { - let bytes: Vec = borsh::BorshDeserialize::deserialize(buf)?; + fn deserialize_reader(reader: &mut R) -> Result + where R: io::Read { + let bytes: Vec = borsh::BorshDeserialize::deserialize_reader(reader)?; Self::from_bytes(bytes.as_slice()).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e.to_string())) } } @@ -89,7 +93,7 @@ impl ByteArray for RistrettoSecretKey { fn from_bytes(bytes: &[u8]) -> Result where Self: Sized { if bytes.len() != 32 { - return Err(ByteArrayError::IncorrectLength); + return Err(ByteArrayError::IncorrectLength {}); } let mut a = [0u8; 32]; a.copy_from_slice(bytes); @@ -137,7 +141,7 @@ impl RistrettoSecretKey { /// Get the multiplicative inverse of a nonzero secret key /// If zero is passed, returns `None`; annoying, but a useful guardrail pub fn invert(&self) -> Option { - if self.0 == Scalar::zero() { + if self.0 == Scalar::ZERO { None } else { Some(RistrettoSecretKey(self.0.invert())) @@ -268,8 +272,9 @@ impl borsh::BorshSerialize for RistrettoPublicKey { #[cfg(feature = "borsh")] impl borsh::BorshDeserialize for RistrettoPublicKey { - fn deserialize(buf: &mut &[u8]) -> io::Result { - let bytes: Vec = borsh::BorshDeserialize::deserialize(buf)?; + fn deserialize_reader(reader: &mut R) -> Result + where R: io::Read { + let bytes: Vec = borsh::BorshDeserialize::deserialize_reader(reader)?; Self::from_bytes(bytes.as_slice()).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e.to_string())) } } @@ -293,7 +298,7 @@ impl RistrettoPublicKey { /// A verifiable group generator using a domain separated hasher pub fn new_generator(label: &'static str) -> Result { // This function requires 512 bytes of data, so let's be opinionated here and use blake2b - let hash = DomainSeparatedHasher::::new_with_label(label).finalize(); + let hash = DomainSeparatedHasher::, RistrettoGeneratorPoint>::new_with_label(label).finalize(); if hash.as_ref().len() < 64 { return Err(HashingError::DigestTooShort(64)); } @@ -363,7 +368,7 @@ impl PublicKey for RistrettoPublicKey { /// Generates a new Public key from the given secret key fn from_secret_key(k: &Self::K) -> RistrettoPublicKey { - let pk = &k.0 * &RISTRETTO_BASEPOINT_TABLE; + let pk = &k.0 * RISTRETTO_BASEPOINT_TABLE; RistrettoPublicKey::new_from_pk(pk) } @@ -378,7 +383,7 @@ impl PublicKey for RistrettoPublicKey { // Requires custom Hashable implementation for RistrettoPublicKey as CompressedRistretto doesnt implement this trait impl Hashable for RistrettoPublicKey { fn hash(&self) -> Vec { - Blake2b::digest(self.as_bytes()).to_vec() + Blake2b::::digest(self.as_bytes()).to_vec() } } @@ -463,7 +468,7 @@ impl Eq for RistrettoPublicKey {} impl PartialOrd for RistrettoPublicKey { fn partial_cmp(&self, other: &RistrettoPublicKey) -> Option { - self.compressed().as_bytes().partial_cmp(other.compressed().as_bytes()) + Some(self.cmp(other)) } } @@ -484,14 +489,16 @@ impl ByteArray for RistrettoPublicKey { where Self: Sized { // Check the length here, because The Ristretto constructor panics rather than returning an error if bytes.len() != 32 { - return Err(ByteArrayError::IncorrectLength); + return Err(ByteArrayError::IncorrectLength {}); } - let compressed = CompressedRistretto::from_slice(bytes); + let compressed = CompressedRistretto::from_slice(bytes).map_err(|_| ByteArrayError::ConversionError { + reason: "Invalid Public key".to_string(), + })?; match RistrettoPublicKey::new_from_compressed(compressed) { Some(p) => Ok(p), - None => Err(ByteArrayError::ConversionError( - "Invalid compressed Ristretto point".to_string(), - )), + None => Err(ByteArrayError::ConversionError { + reason: "Invalid compressed Ristretto point".to_string(), + }), } } @@ -595,7 +602,7 @@ mod test { use tari_utilities::{message_format::MessageFormat, ByteArray}; use super::*; - use crate::{hash::blake2::Blake256, keys::PublicKey, ristretto::test_common::get_keypair}; + use crate::{keys::PublicKey, ristretto::test_common::get_keypair}; fn assert_completely_equal(k1: &RistrettoPublicKey, k2: &RistrettoPublicKey) { assert_eq!(k1, k2); @@ -948,7 +955,7 @@ mod test { #[test] fn kdf_key_too_short() { - let err = RistrettoKdf::generate::(b"this_key_is_too_short", b"data", "test").err(); + let err = RistrettoKdf::generate::>(b"this_key_is_too_short", b"data", "test").err(); assert!(matches!(err, Some(HashingError::InputTooShort))); } @@ -956,8 +963,8 @@ mod test { fn kdf_test() { let key = RistrettoSecretKey::from_hex("b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c").unwrap(); - let derived1 = RistrettoKdf::generate::(key.as_bytes(), b"derived1", "test").unwrap(); - let derived2 = RistrettoKdf::generate::(key.as_bytes(), b"derived2", "test").unwrap(); + let derived1 = RistrettoKdf::generate::>(key.as_bytes(), b"derived1", "test").unwrap(); + let derived2 = RistrettoKdf::generate::>(key.as_bytes(), b"derived2", "test").unwrap(); assert_eq!( derived1.to_hex(), "e8df6fa40344c1fde721e9a35d46daadb48dc66f7901a9795ebb0374474ea601" diff --git a/src/ristretto/ristretto_sig.rs b/src/ristretto/ristretto_sig.rs index b36f9865..245c949c 100644 --- a/src/ristretto/ristretto_sig.rs +++ b/src/ristretto/ristretto_sig.rs @@ -41,7 +41,6 @@ use crate::{ /// # use tari_crypto::ristretto::*; /// # use tari_crypto::keys::*; /// # use tari_crypto::signatures::SchnorrSignature; -/// # use tari_crypto::hash::blake2::Blake256; /// # use digest::Digest; /// /// fn get_keypair() -> (RistrettoSecretKey, RistrettoPublicKey) { @@ -66,7 +65,6 @@ use crate::{ /// # use tari_crypto::ristretto::*; /// # use tari_crypto::keys::*; /// # use tari_crypto::signatures::SchnorrSignature; -/// # use tari_crypto::hash::blake2::Blake256; /// # use tari_utilities::hex::*; /// # use tari_utilities::ByteArray; /// # use digest::Digest; @@ -95,7 +93,6 @@ pub type RistrettoSchnorr = SchnorrSignature = SchnorrSignature::new() + .chain_update(P.as_bytes()) + .chain_update(R.as_bytes()) + .chain_update(b"Small Gods") .finalize(); let e_key = RistrettoSecretKey::from_bytes(&e).unwrap(); let s = &r + &e_key * &k; @@ -166,7 +163,7 @@ mod test { // Doesn't work for invalid credentials assert!(!sig.verify_challenge(&R, &e)); // Doesn't work for different challenge - let wrong_challenge = Blake256::digest(b"Guards! Guards!"); + let wrong_challenge = Blake2b::::digest(b"Guards! Guards!"); assert!(!sig.verify_challenge(&P, &wrong_challenge)); } @@ -182,12 +179,12 @@ mod test { let (k2, P2) = RistrettoPublicKey::random_keypair(&mut rng); let (r2, R2) = RistrettoPublicKey::random_keypair(&mut rng); // Each of them creates the Challenge = H(R1 || R2 || P1 || P2 || m) - let e = Blake256::new() - .chain(R1.as_bytes()) - .chain(R2.as_bytes()) - .chain(P1.as_bytes()) - .chain(P2.as_bytes()) - .chain(b"Moving Pictures") + let e = Blake2b::::new() + .chain_update(R1.as_bytes()) + .chain_update(R2.as_bytes()) + .chain_update(P1.as_bytes()) + .chain_update(P2.as_bytes()) + .chain_update(b"Moving Pictures") .finalize(); // Calculate Alice's signature let s1 = RistrettoSchnorr::sign_raw(&k1, r1, &e).unwrap(); @@ -219,13 +216,13 @@ mod test { let R = RistrettoPublicKey::from_hex("fa14cb581ce5717248444721242e6b195a482d503a853dea4acb513074d8d803").unwrap(); let msg = "Moving Pictures"; - let hash = SchnorrSignature::<_, _, SchnorrSigChallenge>::construct_domain_separated_challenge::<_, Blake256>( + let hash = SchnorrSignature::<_, _, SchnorrSigChallenge>::construct_domain_separated_challenge::<_, Blake2b>( &R, &P, msg, ); - let naiive = Blake256::new() - .chain(R.as_bytes()) - .chain(P.as_bytes()) - .chain(msg) + let naiive = Blake2b::::new() + .chain_update(R.as_bytes()) + .chain_update(P.as_bytes()) + .chain_update(msg) .finalize() .to_vec(); assert_ne!(hash.as_ref(), naiive.as_bytes()); diff --git a/src/ristretto/utils.rs b/src/ristretto/utils.rs index d38bbbab..7ac8cf58 100644 --- a/src/ristretto/utils.rs +++ b/src/ristretto/utils.rs @@ -40,8 +40,8 @@ pub fn sign( let mut rng = rand::thread_rng(); let (nonce, public_nonce) = RistrettoPublicKey::random_keypair(&mut rng); let message = D::new() - .chain(public_nonce.as_bytes()) - .chain(message) + .chain_update(public_nonce.as_bytes()) + .chain_update(message) .finalize() .to_vec(); let e = RistrettoSecretKey::from_bytes(&message).map_err(|_| SchnorrSignatureError::InvalidChallenge)?; diff --git a/src/signatures/commitment_signature.rs b/src/signatures/commitment_signature.rs index 487afae4..ed8d2e93 100644 --- a/src/signatures/commitment_signature.rs +++ b/src/signatures/commitment_signature.rs @@ -174,7 +174,7 @@ where /// From a canonical byte representation, retrieves a commitment signature pub fn from_bytes(buf: &[u8]) -> Result { if buf.len() != P::KEY_LEN + 2 * K::key_length() { - return Err(ByteArrayError::IncorrectLength); + return Err(ByteArrayError::IncorrectLength {}); } let public_nonce = HomomorphicCommitment::from_public_key(&P::from_bytes(&buf[0..P::KEY_LEN])?); let u = K::from_bytes(&buf[P::KEY_LEN..P::KEY_LEN + K::key_length()])?; diff --git a/src/signatures/schnorr.rs b/src/signatures/schnorr.rs index d929d657..5047e413 100644 --- a/src/signatures/schnorr.rs +++ b/src/signatures/schnorr.rs @@ -12,13 +12,13 @@ use std::{ ops::{Add, Mul}, }; -use digest::Digest; +use blake2::Blake2b; +use digest::{consts::U32, Digest}; use serde::{Deserialize, Serialize}; use tari_utilities::ByteArray; use thiserror::Error; use crate::{ - hash::blake2::Blake256, hash_domain, hashing::{DomainSeparatedHash, DomainSeparatedHasher, DomainSeparation}, keys::{PublicKey, SecretKey}, @@ -151,7 +151,8 @@ where { let public_nonce = P::from_secret_key(&nonce); let public_key = P::from_secret_key(secret); - let challenge = Self::construct_domain_separated_challenge::<_, Blake256>(&public_nonce, &public_key, message); + let challenge = + Self::construct_domain_separated_challenge::<_, Blake2b>(&public_nonce, &public_key, message); Self::sign_raw(secret, nonce, challenge.as_ref()) } @@ -189,7 +190,7 @@ where B: AsRef<[u8]>, { let challenge = - Self::construct_domain_separated_challenge::<_, Blake256>(&self.public_nonce, public_key, message); + Self::construct_domain_separated_challenge::<_, Blake2b>(&self.public_nonce, public_key, message); self.verify_challenge(public_key, challenge.as_ref()) } diff --git a/src/wasm/key_utils.rs b/src/wasm/key_utils.rs index 9c7de1d1..c1d4f17b 100644 --- a/src/wasm/key_utils.rs +++ b/src/wasm/key_utils.rs @@ -6,14 +6,14 @@ //! using a function from this module. You should use a [crate::wasm::keyring::KeyRing] instead. But sometimes, these //! functions are handy. -use blake2::Digest; +use blake2::{Blake2b, Digest}; +use digest::consts::U32; use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; use tari_utilities::hex::{from_hex, Hex}; use wasm_bindgen::prelude::*; use crate::{ - hash::blake2::Blake256, keys::{PublicKey, SecretKey}, ristretto::{ pedersen::{commitment_factory::PedersenCommitmentFactory, PedersenCommitment}, @@ -181,7 +181,7 @@ pub(super) fn sign_with_key( None => RistrettoPublicKey::random_keypair(&mut OsRng), }; let P = RistrettoPublicKey::from_secret_key(k); - let e = RistrettoSchnorr::construct_domain_separated_challenge::<_, Blake256>(&R, &P, msg); + let e = RistrettoSchnorr::construct_domain_separated_challenge::<_, Blake2b>(&R, &P, msg); let sig = match RistrettoSchnorr::sign_raw(k, r, e.as_ref()) { Ok(s) => s, Err(e) => { @@ -318,7 +318,7 @@ pub(crate) fn sign_comsig_message_with_key( nonce_2: Option<&RistrettoSecretKey>, result: &mut ComSignResult, ) { - let e = Blake256::digest(msg.as_bytes()); + let e = Blake2b::::digest(msg.as_bytes()); sign_comsig_with_key(private_key_a, private_key_x, e.as_slice(), nonce_1, nonce_2, result); } @@ -399,7 +399,7 @@ pub fn check_comsig_signature( }; let sig = RistrettoComSig::new(R, u, v); - let msg = Blake256::digest(msg.as_bytes()); + let msg = Blake2b::::digest(msg.as_bytes()); result.result = sig.verify_challenge(&public_commitment, msg.as_slice(), &factory); serde_wasm_bindgen::to_value(&result).unwrap() } @@ -511,7 +511,7 @@ pub(crate) fn sign_comandpubsig_message_with_key( nonce_y: Option<&RistrettoSecretKey>, result: &mut ComAndPubSignResult, ) { - let e = Blake256::digest(msg.as_bytes()); + let e = Blake2b::::digest(msg.as_bytes()); sign_comandpubsig_with_key( private_key_a, private_key_x, @@ -643,7 +643,7 @@ pub fn check_comandpubsig_signature( }; let sig = RistrettoComAndPubSig::new(ephemeral_commitment, ephemeral_pubkey, u_a, u_x, u_y); - let msg = Blake256::digest(msg.as_bytes()); + let msg = Blake2b::::digest(msg.as_bytes()); result.result = sig.verify_challenge(&commitment, &pubkey, msg.as_slice(), &factory, &mut OsRng); serde_wasm_bindgen::to_value(&result).unwrap() } @@ -727,8 +727,8 @@ mod test { const SAMPLE_CHALLENGE: &str = "Cormac was completely aware that he was being manipulated, but how he could not see."; - fn hash>(preimage: T) -> Output { - Blake256::digest(preimage.as_ref()) + fn hash>(preimage: T) -> Output> { + Blake2b::::digest(preimage.as_ref()) } fn hash_hex>(preimage: T) -> String {