From aedabb5632164bf29c8b3334945707ad3783d6fb Mon Sep 17 00:00:00 2001 From: Ap4sh Date: Sun, 28 Jun 2026 19:05:00 +0200 Subject: [PATCH] jh: implement SerializableState --- jh/CHANGELOG.md | 6 ++++++ jh/src/block_api.rs | 30 +++++++++++++++++++++++++- jh/src/lib.rs | 8 +++---- jh/tests/data/jh224_serialization.bin | Bin 0 -> 200 bytes jh/tests/data/jh256_serialization.bin | Bin 0 -> 200 bytes jh/tests/data/jh384_serialization.bin | Bin 0 -> 200 bytes jh/tests/data/jh512_serialization.bin | Bin 0 -> 200 bytes jh/tests/mod.rs | 7 +++++- 8 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 jh/tests/data/jh224_serialization.bin create mode 100644 jh/tests/data/jh256_serialization.bin create mode 100644 jh/tests/data/jh384_serialization.bin create mode 100644 jh/tests/data/jh512_serialization.bin diff --git a/jh/CHANGELOG.md b/jh/CHANGELOG.md index 29be5c236..5822252fa 100644 --- a/jh/CHANGELOG.md +++ b/jh/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.2.1 (UNRELEASED) +### Changed +- Implementation of the `SerializableState` trait ([#889]) + +[#889]: https://github.com/RustCrypto/hashes/pull/889 + ## 0.2.0 (2026-03-27) ### Added - `alloc` crate feature ([#678]) diff --git a/jh/src/block_api.rs b/jh/src/block_api.rs index 0c606d3dc..919565cfd 100644 --- a/jh/src/block_api.rs +++ b/jh/src/block_api.rs @@ -6,7 +6,8 @@ use digest::{ AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, Eager, OutputSizeUser, TruncSide, UpdateCore, VariableOutputCore, }, - typenum::{U64, Unsigned}, + common::hazmat::{DeserializeStateError, SerializableState, SerializedState}, + typenum::{U64, U128, U136, Unsigned}, }; use crate::consts; @@ -89,6 +90,33 @@ impl fmt::Debug for JhCore { } } +impl SerializableState for JhCore { + type SerializedStateSize = U136; + + #[inline] + fn serialize(&self) -> SerializedState { + let mut serialized_state = SerializedState::::default(); + let (state_dst, block_len_dst) = serialized_state.split_at_mut(128); + + state_dst.copy_from_slice(self.state.finalize()); + block_len_dst.copy_from_slice(&self.block_len.to_le_bytes()); + + serialized_state + } + + #[inline] + fn deserialize( + serialized_state: &SerializedState, + ) -> Result { + let (serialized_state, serialized_block_len) = serialized_state.split::(); + + Ok(Self { + state: Compressor::new(serialized_state.0), + block_len: u64::from_le_bytes(serialized_block_len.0), + }) + } +} + impl Drop for JhCore { fn drop(&mut self) { #[cfg(feature = "zeroize")] diff --git a/jh/src/lib.rs b/jh/src/lib.rs index 96e14aaf6..9f8af1dcb 100644 --- a/jh/src/lib.rs +++ b/jh/src/lib.rs @@ -22,20 +22,20 @@ use digest::{ digest::buffer_fixed!( /// JH-224 hasher. pub struct Jh224(CtOutWrapper); - impl: BaseFixedTraits AlgorithmName Default Clone HashMarker Reset FixedOutputReset; + impl: FixedHashTraits; ); digest::buffer_fixed!( /// JH-256 hasher. pub struct Jh256(CtOutWrapper); - impl: BaseFixedTraits AlgorithmName Default Clone HashMarker Reset FixedOutputReset; + impl: FixedHashTraits; ); digest::buffer_fixed!( /// JH-384 hasher. pub struct Jh384(CtOutWrapper); - impl: BaseFixedTraits AlgorithmName Default Clone HashMarker Reset FixedOutputReset; + impl: FixedHashTraits; ); digest::buffer_fixed!( /// JH-512 hasher. pub struct Jh512(CtOutWrapper); - impl: BaseFixedTraits AlgorithmName Default Clone HashMarker Reset FixedOutputReset; + impl: FixedHashTraits; ); diff --git a/jh/tests/data/jh224_serialization.bin b/jh/tests/data/jh224_serialization.bin new file mode 100644 index 0000000000000000000000000000000000000000..826a6e9f59bba47b3d6af968258b7e873f1979da GIT binary patch literal 200 zcmY#d)}gAltMAVoJAq|3>9gMVo^&|n$QrnvCGJMPi})qMnD`k_buX}g-t_S54lxhc zhAkz|rFZW8$;Ireg3sP8pJckcG&s5~XK8;n^C|f`>$jR|KRTUrzwU(C v`d42qzk3z)En8a_|M37{UFKfX_&t&(uhg>*|L}PH4`*b607hXbgG>ql*YZF0 literal 0 HcmV?d00001 diff --git a/jh/tests/data/jh256_serialization.bin b/jh/tests/data/jh256_serialization.bin new file mode 100644 index 0000000000000000000000000000000000000000..ee0bfd0ab2f8ea57e3a32caefc3cb2bca782157c GIT binary patch literal 200 zcmbO!|ME+6#o`zTKMOvAJsixr$8PxMtTjD#>434{soY=3Vi+z*E%;Mt{K#Pvw^FXs z|MiRycYa^z<6bxI@_k0%=wFQ2T%Ip^%g4FQKzq$9FV-FLs~I_aeB`4(p literal 0 HcmV?d00001 diff --git a/jh/tests/data/jh384_serialization.bin b/jh/tests/data/jh384_serialization.bin new file mode 100644 index 0000000000000000000000000000000000000000..7cd02c8b0b91bfa29e2bed1d664fe119a26dc672 GIT binary patch literal 200 zcmdnx!ShP&ov6|t%Y2X6ij5E4dl^L^8MOv}587awdN`i5j78^F&8zyZ)ra=n7QZ0V zdGS_QhxRFbiRTBZ@+KRl?|o7e+Wn=BuQud8hdjfrBOBMriFtB$2`86UtkdmliQW80 t&3c08#YW9mL!pT8Y@G|kBbuiL^s&u&A+SdzXVL9CMg|CA6oxX$qyU@mJ0So7 literal 0 HcmV?d00001 diff --git a/jh/tests/data/jh512_serialization.bin b/jh/tests/data/jh512_serialization.bin new file mode 100644 index 0000000000000000000000000000000000000000..f9b287ff4b654e87e23e1543e2021229aa6615ed GIT binary patch literal 200 zcmd;|loWI1>}LKhw;g7GZmxGbIU`MHR&cmr{i7rn?Zj>|ju$$=@4Zkod6jWDc7I8` zMCjLi@mL1kZk_!H^=9OIvR1q9sL}g=qBJ~0#_nmh>)yA^DqC%jo~<%WJI-6ClM*F; u_oUf@;D@e{q}IyLnQ7m9!LBgx`=ev-i)1&ne{X)Yo{<3p7=@t>GARJB)IL!F literal 0 HcmV?d00001 diff --git a/jh/tests/mod.rs b/jh/tests/mod.rs index c200b1729..1b7aeba40 100644 --- a/jh/tests/mod.rs +++ b/jh/tests/mod.rs @@ -1,4 +1,4 @@ -use digest::{dev::fixed_test, new_test}; +use digest::{dev::fixed_test, hash_serialization_test, new_test}; new_test!(jh224_long_kat, jh::Jh224, fixed_test); new_test!(jh256_long_kat, jh::Jh256, fixed_test); @@ -9,3 +9,8 @@ new_test!(jh224_short_kat, jh::Jh224, fixed_test); new_test!(jh256_short_kat, jh::Jh256, fixed_test); new_test!(jh384_short_kat, jh::Jh384, fixed_test); new_test!(jh512_short_kat, jh::Jh512, fixed_test); + +hash_serialization_test!(jh224_serialization, jh::Jh224); +hash_serialization_test!(jh256_serialization, jh::Jh256); +hash_serialization_test!(jh384_serialization, jh::Jh384); +hash_serialization_test!(jh512_serialization, jh::Jh512);