From 013b72791a1d08f2a69a25b264e802fe19c5d184 Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Tue, 4 Feb 2020 18:17:09 +0800 Subject: [PATCH] Add Blake2b256 and Blake2s128 (#1386) Signed-off-by: koushiro Co-authored-by: Pierre Krieger --- misc/multihash/src/hashes.rs | 4 +- misc/multihash/src/lib.rs | 81 ++++++++++++++++++++++++++++++++++-- misc/multihash/tests/lib.rs | 6 ++- 3 files changed, 83 insertions(+), 8 deletions(-) diff --git a/misc/multihash/src/hashes.rs b/misc/multihash/src/hashes.rs index 7833548abf0..bd7c431e248 100644 --- a/misc/multihash/src/hashes.rs +++ b/misc/multihash/src/hashes.rs @@ -29,11 +29,11 @@ pub enum Hash { Keccak512, /// BLAKE2b-512 (64-byte hash size) Blake2b512, - /// Encoding unsupported + /// BLAKE2b-256 (32-byte hash size) Blake2b256, /// BLAKE2s-256 (32-byte hash size) Blake2s256, - /// Encoding unsupported + /// BLAKE2s-128 (16-byte hash size) Blake2s128, } diff --git a/misc/multihash/src/lib.rs b/misc/multihash/src/lib.rs index ec7eaeab1df..fa9c29f5d0c 100644 --- a/misc/multihash/src/lib.rs +++ b/misc/multihash/src/lib.rs @@ -8,17 +8,18 @@ mod errors; mod hashes; +use std::{convert::TryFrom, fmt::Write}; + use bytes::{BufMut, Bytes, BytesMut}; use rand::RngCore; -use sha2::Digest; -use std::{convert::TryFrom, fmt::Write}; +use sha2::digest::{self, VariableOutput}; use unsigned_varint::{decode, encode}; pub use self::errors::{DecodeError, DecodeOwnedError, EncodeError}; pub use self::hashes::Hash; /// Helper function for encoding input into output using given `Digest` -fn digest_encode(input: &[u8], output: &mut [u8]) { +fn digest_encode(input: &[u8], output: &mut [u8]) { output.copy_from_slice(&D::digest(input)) } @@ -91,7 +92,9 @@ pub fn encode(hash: Hash, input: &[u8]) -> Result { Keccak384 => sha3::Keccak384, Keccak512 => sha3::Keccak512, Blake2b512 => blake2::Blake2b, + Blake2b256 => Blake2b256, Blake2s256 => blake2::Blake2s, + Blake2s128 => Blake2s128, }); Ok(Multihash { bytes: output.freeze(), @@ -115,6 +118,76 @@ fn encode_hash(hash: Hash) -> (usize, BytesMut) { (code.len() + 1, output) } +/// BLAKE2b-256 (32-byte hash size) +#[derive(Debug, Clone)] +struct Blake2b256(blake2::VarBlake2b); + +impl Default for Blake2b256 { + fn default() -> Self { + Blake2b256(blake2::VarBlake2b::new(32).unwrap()) + } +} + +impl digest::Input for Blake2b256 { + fn input>(&mut self, data: B) { + self.0.input(data) + } +} + +impl digest::FixedOutput for Blake2b256 { + type OutputSize = digest::generic_array::typenum::U32; + + fn fixed_result(self) -> digest::generic_array::GenericArray { + let mut out = digest::generic_array::GenericArray::default(); + self.0.variable_result(|slice| { + assert_eq!(slice.len(), 32); + out.copy_from_slice(slice) + }); + out + } +} + +impl digest::Reset for Blake2b256 { + fn reset(&mut self) { + self.0.reset() + } +} + +/// BLAKE2s-128 (16-byte hash size) +#[derive(Debug, Clone)] +struct Blake2s128(blake2::VarBlake2s); + +impl Default for Blake2s128 { + fn default() -> Self { + Blake2s128(blake2::VarBlake2s::new(16).unwrap()) + } +} + +impl digest::Input for Blake2s128 { + fn input>(&mut self, data: B) { + self.0.input(data) + } +} + +impl digest::FixedOutput for Blake2s128 { + type OutputSize = digest::generic_array::typenum::U16; + + fn fixed_result(self) -> digest::generic_array::GenericArray { + let mut out = digest::generic_array::GenericArray::default(); + self.0.variable_result(|slice| { + assert_eq!(slice.len(), 16); + out.copy_from_slice(slice) + }); + out + } +} + +impl digest::Reset for Blake2s128 { + fn reset(&mut self) { + self.0.reset() + } +} + /// Represents a valid multihash. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Multihash { bytes: Bytes } @@ -194,7 +267,7 @@ impl<'a> MultihashRef<'a> { /// Creates a `MultihashRef` from the given `input`. pub fn from_slice(input: &'a [u8]) -> Result { if input.is_empty() { - return Err(DecodeError::BadInputLength) + return Err(DecodeError::BadInputLength); } // Ensure `Hash::code` returns a `u16` so that our `decode::u16` here is correct. diff --git a/misc/multihash/tests/lib.rs b/misc/multihash/tests/lib.rs index 3eea04fb959..f82684325b0 100644 --- a/misc/multihash/tests/lib.rs +++ b/misc/multihash/tests/lib.rs @@ -1,5 +1,3 @@ - - use parity_multihash::*; /// Helper function to convert a hex-encoded byte array back into a bytearray @@ -41,7 +39,9 @@ fn multihash_encode() { Keccak384, b"hello world", "1C3065fc99339a2a40e99d3c40d695b22f278853ca0f925cde4254bcae5e22ece47e6441f91b6568425adc9d95b0072eb49f"; Keccak512, b"hello world", "1D403ee2b40047b8060f68c67242175660f4174d0af5c01d47168ec20ed619b0b7c42181f40aa1046f39e2ef9efc6910782a998e0013d172458957957fac9405b67d"; Blake2b512, b"hello world", "c0e40240021ced8799296ceca557832ab941a50b4a11f83478cf141f51f933f653ab9fbcc05a037cddbed06e309bf334942c4e58cdf1a46e237911ccd7fcf9787cbc7fd0"; + Blake2b256, b"hello world", "a0e40220256c83b297114d201b30179f3f0ef0cace9783622da5974326b436178aeef610"; Blake2s256, b"hello world", "e0e402209aec6806794561107e594b1f6a8a6b0c92a0cba9acf5e5e93cca06f781813b0b"; + Blake2s128, b"hello world", "d0e4021037deae0226c30da2ab424a7b8ee14e83"; } } @@ -74,7 +74,9 @@ fn assert_decode() { Keccak384, "1C3065fc99339a2a40e99d3c40d695b22f278853ca0f925cde4254bcae5e22ece47e6441f91b6568425adc9d95b0072eb49f"; Keccak512, "1D403ee2b40047b8060f68c67242175660f4174d0af5c01d47168ec20ed619b0b7c42181f40aa1046f39e2ef9efc6910782a998e0013d172458957957fac9405b67d"; Blake2b512, "c0e40240021ced8799296ceca557832ab941a50b4a11f83478cf141f51f933f653ab9fbcc05a037cddbed06e309bf334942c4e58cdf1a46e237911ccd7fcf9787cbc7fd0"; + Blake2b256, "a0e40220256c83b297114d201b30179f3f0ef0cace9783622da5974326b436178aeef610"; Blake2s256, "e0e402209aec6806794561107e594b1f6a8a6b0c92a0cba9acf5e5e93cca06f781813b0b"; + Blake2s128, "d0e4021037deae0226c30da2ab424a7b8ee14e83"; } }