Skip to content

Commit d8ad927

Browse files
committed
add Ascon-CXOF128
1 parent 26395f5 commit d8ad927

8 files changed

Lines changed: 392 additions & 151 deletions

File tree

ascon-hash256/src/block_api.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ use digest::{
99
consts::{U8, U32, U40},
1010
};
1111

12+
const IV: u64 = 0x0000_0801_00CC_0002;
13+
1214
/// Initial state of Ascon-Hash256
13-
const IV: State = [
14-
0x9B1E_5494_E934_D681,
15-
0x4BC3_A01E_3337_51D2,
16-
0xAE65_396C_6B34_B81A,
17-
0x3C7F_D4A4_D56A_4DB3,
18-
0x1A5C_4649_06C5_976D,
19-
];
15+
const INIT_STATE: State = {
16+
let mut state = [IV, 0, 0, 0, 0];
17+
ascon::permute12(&mut state);
18+
state
19+
};
2020

2121
/// Ascon-Hash256 block-level hasher
2222
#[derive(Clone, Debug)]
@@ -27,7 +27,7 @@ pub struct AsconHash256Core {
2727
impl Default for AsconHash256Core {
2828
#[inline]
2929
fn default() -> Self {
30-
Self { state: IV }
30+
Self { state: INIT_STATE }
3131
}
3232
}
3333

@@ -77,7 +77,7 @@ impl FixedOutputCore for AsconHash256Core {
7777
impl Reset for AsconHash256Core {
7878
#[inline]
7979
fn reset(&mut self) {
80-
self.state = IV;
80+
self.state = INIT_STATE;
8181
}
8282
}
8383

ascon-xof128/src/block_api.rs

Lines changed: 12 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -1,140 +1,13 @@
1-
use ascon::State;
2-
use digest::{
3-
HashMarker, OutputSizeUser, Reset,
4-
block_api::{
5-
AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, Eager, ExtendableOutputCore,
6-
UpdateCore, XofReaderCore,
7-
},
8-
common::hazmat::{DeserializeStateError, SerializableState, SerializedState},
9-
consts::{U8, U32, U40},
10-
};
11-
12-
const IV: State = [
13-
0xDA82_CE76_8D94_47EB,
14-
0xCC7C_E6C7_5F1E_F969,
15-
0xE750_8FD7_8008_5631,
16-
0x0EE0_EA53_416B_58CC,
17-
0xE054_7524_DB6F_0BDE,
18-
];
19-
20-
/// Ascon-XOF128 block-level hasher
21-
#[derive(Clone, Debug)]
22-
pub struct AsconXof128Core {
23-
state: State,
24-
}
25-
26-
impl Default for AsconXof128Core {
27-
#[inline]
28-
fn default() -> Self {
29-
Self { state: IV }
30-
}
31-
}
32-
33-
impl HashMarker for AsconXof128Core {}
34-
35-
impl BlockSizeUser for AsconXof128Core {
36-
type BlockSize = U8;
37-
}
38-
39-
impl BufferKindUser for AsconXof128Core {
40-
type BufferKind = Eager;
41-
}
42-
43-
impl OutputSizeUser for AsconXof128Core {
44-
type OutputSize = U32;
45-
}
46-
47-
impl UpdateCore for AsconXof128Core {
48-
#[inline]
49-
fn update_blocks(&mut self, blocks: &[Block<Self>]) {
50-
for block in blocks {
51-
self.state[0] ^= u64::from_le_bytes(block.0);
52-
ascon::permute12(&mut self.state);
53-
}
54-
}
55-
}
56-
57-
impl ExtendableOutputCore for AsconXof128Core {
58-
type ReaderCore = AsconXofReaderCore;
59-
60-
fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
61-
let len = buffer.get_pos();
62-
let last_block = buffer.pad_with_zeros();
63-
let pad = 1u64 << (8 * len);
64-
self.state[0] ^= u64::from_le_bytes(last_block.0) ^ pad;
65-
66-
AsconXofReaderCore { state: self.state }
67-
}
68-
}
69-
70-
impl Reset for AsconXof128Core {
71-
#[inline]
72-
fn reset(&mut self) {
73-
self.state = IV;
74-
}
75-
}
76-
77-
impl AlgorithmName for AsconXof128Core {
78-
#[inline]
79-
fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
80-
f.write_str("Ascon-XOF128")
81-
}
82-
}
83-
84-
impl SerializableState for AsconXof128Core {
85-
type SerializedStateSize = U40;
86-
87-
#[inline]
88-
fn serialize(&self) -> SerializedState<Self> {
89-
let mut res = SerializedState::<Self>::default();
90-
let mut chunks = res.chunks_exact_mut(size_of::<u64>());
91-
for (src, dst) in self.state.iter().zip(&mut chunks) {
92-
dst.copy_from_slice(&src.to_le_bytes());
93-
}
94-
assert!(chunks.into_remainder().is_empty());
95-
res
96-
}
97-
98-
#[inline]
99-
fn deserialize(
100-
serialized_state: &SerializedState<Self>,
101-
) -> Result<Self, DeserializeStateError> {
102-
let state = core::array::from_fn(|i| {
103-
let n = size_of::<u64>();
104-
let chunk = &serialized_state[n * i..][..n];
105-
u64::from_le_bytes(chunk.try_into().expect("chunk has correct length"))
106-
});
107-
Ok(Self { state })
108-
}
109-
}
110-
111-
impl Drop for AsconXof128Core {
112-
#[inline]
113-
fn drop(&mut self) {
114-
#[cfg(feature = "zeroize")]
115-
{
116-
use digest::zeroize::Zeroize;
117-
self.state.zeroize()
118-
}
119-
}
120-
}
121-
122-
#[cfg(feature = "zeroize")]
123-
impl digest::zeroize::ZeroizeOnDrop for AsconXof128Core {}
124-
125-
/// Ascon-XOF128 block-level reader
126-
#[derive(Clone, Debug)]
127-
pub struct AsconXofReaderCore {
128-
state: State,
129-
}
130-
131-
impl BlockSizeUser for AsconXofReaderCore {
132-
type BlockSize = U8;
133-
}
134-
135-
impl XofReaderCore for AsconXofReaderCore {
136-
fn read_block(&mut self) -> Block<Self> {
137-
ascon::permute12(&mut self.state);
138-
self.state[0].to_le_bytes().into()
139-
}
1+
mod cxof;
2+
mod reader;
3+
mod xof;
4+
5+
pub use cxof::AsconCxof128Core;
6+
pub use reader::AsconXofReaderCore;
7+
pub use xof::AsconXof128Core;
8+
9+
const fn init_state(iv: u64) -> ascon::State {
10+
let mut state = [iv, 0, 0, 0, 0];
11+
ascon::permute12(&mut state);
12+
state
14013
}

ascon-xof128/src/block_api/cxof.rs

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
use ascon::State;
2+
use digest::{
3+
CustomizedInit, HashMarker, OutputSizeUser,
4+
block_api::{
5+
AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, Eager, ExtendableOutputCore,
6+
UpdateCore,
7+
},
8+
common::hazmat::{DeserializeStateError, SerializableState, SerializedState},
9+
consts::{U8, U32, U40},
10+
};
11+
12+
use super::{AsconXofReaderCore, init_state};
13+
14+
/// Maximum allowed length of customization strings in bits.
15+
const MAX_CUSTOM_LEN: usize = 2048;
16+
17+
const IV: u64 = 0x0000_0800_00CC_0004;
18+
const INIT_STATE: State = init_state(IV);
19+
20+
/// Ascon-CXOF128 block-level hasher
21+
#[derive(Clone, Debug)]
22+
pub struct AsconCxof128Core {
23+
state: State,
24+
}
25+
26+
impl Default for AsconCxof128Core {
27+
#[inline]
28+
fn default() -> Self {
29+
Self::new_customized(&[])
30+
}
31+
}
32+
33+
impl CustomizedInit for AsconCxof128Core {
34+
#[inline]
35+
fn new_customized(customization: &[u8]) -> Self {
36+
let bit_len = 8 * customization.len();
37+
assert!(bit_len < MAX_CUSTOM_LEN);
38+
let mut state = INIT_STATE;
39+
40+
state[0] ^= u64::try_from(bit_len).expect("bit_len is smaller than MAX_CUSTOM_LEN");
41+
42+
ascon::permute12(&mut state);
43+
44+
let mut blocks = customization.chunks_exact(size_of::<u64>());
45+
for block in &mut blocks {
46+
let block = block.try_into().expect("block has correct length");
47+
state[0] ^= u64::from_le_bytes(block);
48+
ascon::permute12(&mut state);
49+
}
50+
51+
let last_block = blocks.remainder();
52+
let len = last_block.len();
53+
54+
let mut buf = [0u8; 8];
55+
buf[..len].copy_from_slice(last_block);
56+
57+
let pad = 1u64 << (8 * len);
58+
state[0] ^= u64::from_le_bytes(buf) ^ pad;
59+
60+
ascon::permute12(&mut state);
61+
62+
Self { state }
63+
}
64+
}
65+
66+
impl HashMarker for AsconCxof128Core {}
67+
68+
impl BlockSizeUser for AsconCxof128Core {
69+
type BlockSize = U8;
70+
}
71+
72+
impl BufferKindUser for AsconCxof128Core {
73+
type BufferKind = Eager;
74+
}
75+
76+
impl OutputSizeUser for AsconCxof128Core {
77+
type OutputSize = U32;
78+
}
79+
80+
impl UpdateCore for AsconCxof128Core {
81+
#[inline]
82+
fn update_blocks(&mut self, blocks: &[Block<Self>]) {
83+
for block in blocks {
84+
self.state[0] ^= u64::from_le_bytes(block.0);
85+
ascon::permute12(&mut self.state);
86+
}
87+
}
88+
}
89+
90+
impl ExtendableOutputCore for AsconCxof128Core {
91+
type ReaderCore = AsconXofReaderCore;
92+
93+
fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
94+
let len = buffer.get_pos();
95+
let last_block = buffer.pad_with_zeros();
96+
let pad = 1u64 << (8 * len);
97+
self.state[0] ^= u64::from_le_bytes(last_block.0) ^ pad;
98+
99+
AsconXofReaderCore { state: self.state }
100+
}
101+
}
102+
103+
impl AlgorithmName for AsconCxof128Core {
104+
#[inline]
105+
fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
106+
f.write_str("Ascon-CXOF128")
107+
}
108+
}
109+
110+
impl SerializableState for AsconCxof128Core {
111+
type SerializedStateSize = U40;
112+
113+
#[inline]
114+
fn serialize(&self) -> SerializedState<Self> {
115+
let mut res = SerializedState::<Self>::default();
116+
let mut chunks = res.chunks_exact_mut(size_of::<u64>());
117+
for (src, dst) in self.state.iter().zip(&mut chunks) {
118+
dst.copy_from_slice(&src.to_le_bytes());
119+
}
120+
assert!(chunks.into_remainder().is_empty());
121+
res
122+
}
123+
124+
#[inline]
125+
fn deserialize(
126+
serialized_state: &SerializedState<Self>,
127+
) -> Result<Self, DeserializeStateError> {
128+
let state = core::array::from_fn(|i| {
129+
let n = size_of::<u64>();
130+
let chunk = &serialized_state[n * i..][..n];
131+
u64::from_le_bytes(chunk.try_into().expect("chunk has correct length"))
132+
});
133+
Ok(Self { state })
134+
}
135+
}
136+
137+
impl Drop for AsconCxof128Core {
138+
#[inline]
139+
fn drop(&mut self) {
140+
#[cfg(feature = "zeroize")]
141+
{
142+
use digest::zeroize::Zeroize;
143+
self.state.zeroize()
144+
}
145+
}
146+
}
147+
148+
#[cfg(feature = "zeroize")]
149+
impl digest::zeroize::ZeroizeOnDrop for AsconCxof128Core {}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use ascon::State;
2+
use digest::{
3+
block_api::{Block, BlockSizeUser, XofReaderCore},
4+
consts::U8,
5+
};
6+
7+
/// Ascon-XOF128 block-level reader
8+
#[derive(Clone, Debug)]
9+
pub struct AsconXofReaderCore {
10+
pub(super) state: State,
11+
}
12+
13+
impl BlockSizeUser for AsconXofReaderCore {
14+
type BlockSize = U8;
15+
}
16+
17+
impl XofReaderCore for AsconXofReaderCore {
18+
fn read_block(&mut self) -> Block<Self> {
19+
ascon::permute12(&mut self.state);
20+
self.state[0].to_le_bytes().into()
21+
}
22+
}

0 commit comments

Comments
 (0)