Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement SerializableState for hashes #385

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions fsb/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ use digest::{
AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore,
OutputSizeUser, Reset, UpdateCore,
},
crypto_common::{self, SerializableState},
typenum::Unsigned,
HashMarker, Output,
};
Expand Down
2 changes: 1 addition & 1 deletion fsb/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ macro_rules! fsb_impl {
) => {
use digest::consts::{$blocksize, $outputsize};

#[derive(Clone)]
#[derive(Clone, SerializableState)]
#[doc=$doc]
pub struct $state {
blocks_len: u64,
Expand Down
129 changes: 127 additions & 2 deletions fsb/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use digest::dev::{feed_rand_16mib, fixed_reset_test};
use digest::new_test;
use digest::{
dev::{feed_rand_16mib, fixed_reset_test},
hash_serialization_test, new_test,
};
use fsb::{Digest, Fsb160, Fsb224, Fsb256, Fsb384, Fsb512};
use hex_literal::hex;

Expand All @@ -9,6 +11,129 @@ new_test!(fsb256_main, "fsb256", Fsb256, fixed_reset_test);
new_test!(fsb384_main, "fsb384", Fsb384, fixed_reset_test);
new_test!(fsb512_main, "fsb512", Fsb512, fixed_reset_test);

#[rustfmt::skip]
hash_serialization_test!(
fsb160_serialization,
Fsb160,
hex!("
0100000000000000e269a086505e9493
fa92ed509f6cdce851dd58654160a8c8
a499a953a479c169d46c0576d8e7b262
341087f58eb3dc9d3002451f8f0d484c
bdc8b342afef13e54f2fce12e400eca0
a6bc0b8837f999c30113000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
0000000000
")
);
#[rustfmt::skip]
hash_serialization_test!(
fsb224_serialization,
Fsb224,
hex!("
0100000000000000bfba3bbd79050b44
28d239ec4eb25277b228898bd26c04cc
f11e052944e72b61aae3f1a0a6cdb862
d87fac21fefb1dc14074cfc45d899408
7dc70d1d5308b6b1f68f6eea5d886904
dfcab198e62f6c9767ae365fc648b1bb
7d00f65ff276373a7a1b4d80efdd7af5
fce3b0e93371172a0113000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000
")
);

#[rustfmt::skip]
hash_serialization_test!(
fsb256_serialization,
Fsb256,
hex!("
01000000000000006c4fef5401baa182
5e74fe2a150dd74655ba10d8fa2db4ee
3e6925de2cf4a83a5121e2ded528f926
13ec858045c1bdd15a11ce8bd4df1a3f
409dfc9d1025d333360f30a342f41701
8fcf0ff1c5dddb042a18453d707d2772
1e57fd182d93294589a1c3ef007e6bb3
b59f2a361094e21d6c72d213545a6612
a2adc547968a03e90113000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
000000000000000000
")
);

#[rustfmt::skip]
hash_serialization_test!(
fsb384_serialization,
Fsb384,
hex!("
010000000000000041825b73ae6b5cdc
91b8b70723dc1f9297fec62f09c17c75
a2326e3d7664efb5df1104db5c711016
d161187f3174ef77f5e0545c917d0137
5537d15cf90c838d2f5fd5a294c7012d
80a0f6a6240f90f9a6976812ec60fdd3
5bbc1a064287308e1d916cb4d59c02b1
9ab2d20e1b9b2acbe826c4d0022db322
e3314fe0cf232cdd75b61c653bf30569
ca76dd11bd032d03bc83a0e59964eb5d
d77a22d0a459de63ab5ff6ce1207a9da
ed690c36399f730643a1628e0f33650a
01130000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000
")
);

#[rustfmt::skip]
hash_serialization_test!(
fsb512_serialization,
Fsb512,
hex!("
01000000000000004feff733b532b076
7d0bbe8804f60ebcbbf33aa6796e608d
37e6e24dcf21663631312286c6efa794
b237f05df2838526cb5120291a53566b
b784ff32d2ea5464693cd68fc52a3737
5160c0a4f4b8dae806703a98720180c4
abaa2c195a6ede59ed68fc5caae61720
03ad9195d7ae774710d7a0c46772a721
6e553a39dbeac282fa2848e7038eec7c
78f7da35db4cf8ead35f2f140ec49203
f1d3afe24fe4100a9d0cc5fdb1e964ed
48fe786e2bfdabe470c148f65c67c21c
c6794b8e1eb90e6a39800334a2016e20
81f5a458fcd348d8778dc4090066f390
6b835a1283c975694e1dc38fef18dd35
d2d4f283d0bc1502db72a91871a23bc4
01130000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
000000000000000000000000
")
);

#[test]
fn fsb160_rand() {
let mut h = Fsb160::new();
Expand Down
51 changes: 50 additions & 1 deletion gost94/src/gost94_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ use digest::{
AlgorithmName, Block as TBlock, BlockSizeUser, Buffer, BufferKindUser, FixedOutputCore,
OutputSizeUser, Reset, UpdateCore,
},
typenum::{Unsigned, U32},
crypto_common::{DeserializeStateError, SerializableState, SerializedState},
generic_array::{
sequence::{Concat, Split},
GenericArray,
},
typenum::{Unsigned, U32, U96},
HashMarker, Output,
};

Expand Down Expand Up @@ -273,3 +278,47 @@ impl<P: Gost94Params> fmt::Debug for Gost94Core<P> {
f.write_str("Core { .. }")
}
}

impl<P: Gost94Params> SerializableState for Gost94Core<P> {
type SerializedStateSize = U96;

fn serialize(&self) -> SerializedState<Self> {
let serialized_h = GenericArray::<_, U32>::from(self.h);

let mut serialized_n = GenericArray::<_, U32>::default();
for (val, chunk) in self.n.iter().zip(serialized_n.chunks_exact_mut(8)) {
chunk.copy_from_slice(&val.to_le_bytes());
}

let mut serialized_sigma = GenericArray::<_, U32>::default();
for (val, chunk) in self.sigma.iter().zip(serialized_sigma.chunks_exact_mut(8)) {
chunk.copy_from_slice(&val.to_le_bytes());
}

serialized_h.concat(serialized_n).concat(serialized_sigma)
}

fn deserialize(
serialized_state: &SerializedState<Self>,
) -> Result<Self, DeserializeStateError> {
let (serialized_h, remaining_buffer) = Split::<_, U32>::split(serialized_state);

let (serialized_n, serialized_sigma) = Split::<_, U32>::split(remaining_buffer);
let mut n = [0; 4];
for (val, chunk) in n.iter_mut().zip(serialized_n.chunks_exact(8)) {
*val = u64::from_le_bytes(chunk.try_into().unwrap());
}

let mut sigma = [0; 4];
for (val, chunk) in sigma.iter_mut().zip(serialized_sigma.chunks_exact(8)) {
*val = u64::from_le_bytes(chunk.try_into().unwrap());
}

Ok(Self {
h: (*serialized_h).into(),
n,
sigma,
_m: core::marker::PhantomData,
})
}
}
69 changes: 67 additions & 2 deletions gost94/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use digest::dev::{feed_rand_16mib, fixed_reset_test};
use digest::new_test;
use gost94::{Digest, Gost94CryptoPro, Gost94Test, Gost94UA};
use digest::{hash_serialization_test, new_test};
use gost94::{Digest, Gost94CryptoPro, Gost94Test, Gost94UA, Gost94s2015};
use hex_literal::hex;

new_test!(gost94_test_main, "test", Gost94Test, fixed_reset_test);
Expand All @@ -11,6 +11,71 @@ new_test!(
fixed_reset_test
);

#[rustfmt::skip]
hash_serialization_test!(
gost94_crypto_pro_serialization,
Gost94CryptoPro,
hex!("
51aeb30f746350e15ef31472e3914b1b
4b9198e0272881ff2401cea8490e5ab2
00010000000000000000000000000000
00000000000000000000000000000000
13131313131313131313131313131313
13131313131313131313131313131313
01130000000000000000000000000000
00000000000000000000000000000000
00
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm... This redundant byte for eager hashes is certainly an eyesore. It could be worth to add serialize/deserialize methods to the block-buffer crate.

")
);
#[rustfmt::skip]
hash_serialization_test!(
gost94_test_serialization,
Gost94Test,
hex!("
81bba4e852b20165ac12b2151cd38b47
821cfd45ad739fb03018021a77750754
00010000000000000000000000000000
00000000000000000000000000000000
13131313131313131313131313131313
13131313131313131313131313131313
01130000000000000000000000000000
00000000000000000000000000000000
00
")
);
#[rustfmt::skip]
hash_serialization_test!(
gost94_ua_serialization,
Gost94UA,
hex!("
7755aa3d77c2026677adf176fd722741
742a184862f353ec99b1f7928ff0eaa4
00010000000000000000000000000000
00000000000000000000000000000000
13131313131313131313131313131313
13131313131313131313131313131313
01130000000000000000000000000000
00000000000000000000000000000000
00
")
);
#[rustfmt::skip]
hash_serialization_test!(
gost94_s_2015_serialization,
Gost94s2015,
hex!("
d29b34011a22a27037ea42d36a512910
913482fdc2349ab02ca1087a50745d5b
00010000000000000000000000000000
00000000000000000000000000000000
13131313131313131313131313131313
13131313131313131313131313131313
01130000000000000000000000000000
00000000000000000000000000000000
00
")
);

#[test]
fn gost94_test_rand() {
let mut h = Gost94Test::new();
Expand Down
67 changes: 65 additions & 2 deletions groestl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,20 @@

pub use digest::{self, Digest};

use core::fmt;
use core::{convert::TryInto, fmt};
use digest::{
block_buffer::Eager,
core_api::{
AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper,
CtVariableCoreWrapper, OutputSizeUser, RtVariableCoreWrapper, TruncSide, UpdateCore,
VariableOutputCore,
},
typenum::{Unsigned, U128, U28, U32, U48, U64},
crypto_common::{DeserializeStateError, SerializableState, SerializedState},
generic_array::{
sequence::{Concat, Split},
GenericArray,
},
typenum::{Unsigned, U128, U136, U28, U32, U48, U64, U72},
HashMarker, InvalidOutputSize, Output,
};

Expand Down Expand Up @@ -127,6 +132,35 @@ impl fmt::Debug for GroestlShortVarCore {
}
}

impl SerializableState for GroestlShortVarCore {
type SerializedStateSize = U72;

fn serialize(&self) -> SerializedState<Self> {
let mut serialized_state = GenericArray::<_, U64>::default();

for (val, chunk) in self.state.iter().zip(serialized_state.chunks_exact_mut(8)) {
chunk.copy_from_slice(&val.to_le_bytes());
}

serialized_state.concat(self.blocks_len.to_le_bytes().into())
}

fn deserialize(
serialized_state: &SerializedState<Self>,
) -> Result<Self, DeserializeStateError> {
let (serialized_state, serialized_block_len) = Split::<_, U64>::split(serialized_state);

let mut state = [0; compress512::COLS];
for (val, chunk) in state.iter_mut().zip(serialized_state.chunks_exact(8)) {
*val = u64::from_le_bytes(chunk.try_into().unwrap());
}

let blocks_len = u64::from_le_bytes((*serialized_block_len).into());

Ok(Self { state, blocks_len })
}
}

/// Short Groestl variant which allows to choose output size at runtime.
pub type GroestlShortVar = RtVariableCoreWrapper<GroestlShortVarCore>;
/// Core hasher state of the short Groestl variant generic over output size.
Expand Down Expand Up @@ -215,6 +249,35 @@ impl fmt::Debug for GroestlLongVarCore {
}
}

impl SerializableState for GroestlLongVarCore {
type SerializedStateSize = U136;

fn serialize(&self) -> SerializedState<Self> {
let mut serialized_state = GenericArray::<_, U128>::default();

for (val, chunk) in self.state.iter().zip(serialized_state.chunks_exact_mut(8)) {
chunk.copy_from_slice(&val.to_le_bytes());
}

serialized_state.concat(self.blocks_len.to_le_bytes().into())
}

fn deserialize(
serialized_state: &SerializedState<Self>,
) -> Result<Self, DeserializeStateError> {
let (serialized_state, serialized_blocks_len) = Split::<_, U128>::split(serialized_state);

let mut state = [0; compress1024::COLS];
for (val, chunk) in state.iter_mut().zip(serialized_state.chunks_exact(8)) {
*val = u64::from_le_bytes(chunk.try_into().unwrap());
}

let blocks_len = u64::from_le_bytes((*serialized_blocks_len).into());

Ok(Self { state, blocks_len })
}
}

/// Long Groestl variant which allows to choose output size at runtime.
pub type GroestlLongVar = RtVariableCoreWrapper<GroestlLongVarCore>;
/// Core hasher state of the long Groestl variant generic over output size.
Expand Down
Loading