ascon_hash/
lib.rs

1// Copyright 2022-2023 Sebastian Ramacher
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4#![no_std]
5#![cfg_attr(docsrs, feature(doc_auto_cfg))]
6#![doc = include_str!("../README.md")]
7#![doc(
8    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
9    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
10)]
11#![warn(missing_docs)]
12
13//! ## Usage (Hashing)
14//!
15//! ```
16//! use ascon_hash::{AsconHash, Digest}; // Or `AsconAHash`
17//!
18//! let mut hasher = AsconHash::new();
19//! hasher.update(b"some bytes");
20//! let digest = hasher.finalize();
21//! assert_eq!(&digest[..], b"\xb7\x42\xca\x75\xe5\x70\x38\x75\x70\x59\xcc\xcc\x68\x74\x71\x4f\x9d\xbd\x7f\xc5\x92\x4a\x7d\xf4\xe3\x16\x59\x4f\xd1\x42\x6c\xa8");
22//! ```
23//!
24//! ## Usage (XOF)
25//!
26//! ```
27//! use ascon_hash::{AsconXof, ExtendableOutput, Update, XofReader};
28//!
29//! let mut xof = AsconXof::default();
30//! xof.update(b"some bytes");
31//! let mut reader = xof.finalize_xof();
32//! let mut dst = [0u8; 5];
33//! reader.read(&mut dst);
34//! assert_eq!(&dst, b"\xc2\x19\x72\xfd\xe9");
35//! ```
36
37use core::marker::PhantomData;
38
39use ascon::{pad, State};
40pub use digest::{self, Digest, ExtendableOutput, Reset, Update, XofReader};
41use digest::{
42    block_buffer::Eager,
43    consts::{U32, U8},
44    core_api::{
45        AlgorithmName, Block, Buffer, BufferKindUser, CoreWrapper, ExtendableOutputCore,
46        FixedOutputCore, UpdateCore, XofReaderCore, XofReaderCoreWrapper,
47    },
48    crypto_common::BlockSizeUser,
49    HashMarker, Output, OutputSizeUser,
50};
51
52/// Parameters for Ascon hash instances.
53trait HashParameters {
54    /// Number of rounds for the permutation.
55    const ROUNDS: usize;
56    /// Part of the IV.
57    const IV0: u64;
58    /// Part of the IV.
59    const IV1: u64;
60    /// Part of the IV.
61    const IV2: u64;
62    /// Part of the IV.
63    const IV3: u64;
64    /// Part of the IV.
65    const IV4: u64;
66}
67
68/// Parameters for AsconA hash.
69#[derive(Clone, Debug)]
70struct Parameters;
71
72impl HashParameters for Parameters {
73    const ROUNDS: usize = 12;
74    const IV0: u64 = 0xee9398aadb67f03d;
75    const IV1: u64 = 0x8bb21831c60f1002;
76    const IV2: u64 = 0xb48a92db98d5da62;
77    const IV3: u64 = 0x43189921b8f8e3e8;
78    const IV4: u64 = 0x348fa5c9d525e140;
79}
80
81/// Parameters for AsconA hash.
82#[derive(Clone, Debug)]
83struct ParametersA;
84
85impl HashParameters for ParametersA {
86    const ROUNDS: usize = 8;
87    const IV0: u64 = 0x01470194fc6528a6;
88    const IV1: u64 = 0x738ec38ac0adffa7;
89    const IV2: u64 = 0x2ec8e3296c76384c;
90    const IV3: u64 = 0xd6f6a54d7f52377d;
91    const IV4: u64 = 0xa13c42a223be8d87;
92}
93
94#[derive(Clone, Debug)]
95struct ParametersXof;
96
97impl HashParameters for ParametersXof {
98    const ROUNDS: usize = 12;
99    const IV0: u64 = 0xb57e273b814cd416;
100    const IV1: u64 = 0x2b51042562ae2420;
101    const IV2: u64 = 0x66a3a7768ddf2218;
102    const IV3: u64 = 0x5aad0a7a8153650c;
103    const IV4: u64 = 0x4f3e0e32539493b6;
104}
105
106#[derive(Clone, Debug)]
107struct ParametersAXof;
108
109impl HashParameters for ParametersAXof {
110    const ROUNDS: usize = 8;
111    const IV0: u64 = 0x44906568b77b9832;
112    const IV1: u64 = 0xcd8d6cae53455532;
113    const IV2: u64 = 0xf7b5212756422129;
114    const IV3: u64 = 0x246885e1de0d225b;
115    const IV4: u64 = 0xa8cb5ce33449973f;
116}
117
118#[derive(Clone, Debug)]
119struct HashCore<P: HashParameters> {
120    state: State,
121    phantom: PhantomData<P>,
122}
123
124impl<P: HashParameters> HashCore<P> {
125    fn absorb_block(&mut self, block: &[u8; 8]) {
126        self.state[0] ^= u64::from_be_bytes(*block);
127        self.permute_state();
128    }
129
130    fn absorb_last_block(&mut self, block: &[u8]) {
131        debug_assert!(block.len() < 8);
132
133        let len = block.len();
134        if len > 0 {
135            let mut tmp = [0u8; 8];
136            tmp[0..len].copy_from_slice(block);
137            self.state[0] ^= u64::from_be_bytes(tmp);
138        }
139        self.state[0] ^= pad(len);
140        self.state.permute_12();
141    }
142
143    // for fixed-sized output
144    fn squeeze(&mut self, mut block: &mut [u8]) {
145        debug_assert_eq!(block.len() % 8, 0);
146
147        while block.len() > 8 {
148            block[..8].copy_from_slice(&u64::to_be_bytes(self.state[0]));
149            self.permute_state();
150            block = &mut block[8..];
151        }
152        block[..8].copy_from_slice(&u64::to_be_bytes(self.state[0]));
153    }
154
155    // for XOF output
156    fn squeeze_block(&mut self) -> [u8; 8] {
157        let ret = u64::to_be_bytes(self.state[0]);
158        self.permute_state();
159        ret
160    }
161
162    #[inline(always)]
163    fn permute_state(&mut self) {
164        if P::ROUNDS == 12 {
165            self.state.permute_12();
166        } else if P::ROUNDS == 8 {
167            self.state.permute_8();
168        } else if P::ROUNDS == 6 {
169            self.state.permute_6();
170        }
171    }
172}
173
174impl<P: HashParameters> Default for HashCore<P> {
175    fn default() -> Self {
176        Self {
177            state: State::new(P::IV0, P::IV1, P::IV2, P::IV3, P::IV4),
178            phantom: PhantomData,
179        }
180    }
181}
182
183/// Ascon hash implementation
184#[derive(Clone, Debug, Default)]
185pub struct AsconCore {
186    state: HashCore<Parameters>,
187}
188
189impl HashMarker for AsconCore {}
190
191impl BlockSizeUser for AsconCore {
192    type BlockSize = U8;
193}
194
195impl BufferKindUser for AsconCore {
196    type BufferKind = Eager;
197}
198
199impl OutputSizeUser for AsconCore {
200    type OutputSize = U32;
201}
202
203impl UpdateCore for AsconCore {
204    fn update_blocks(&mut self, blocks: &[Block<Self>]) {
205        for block in blocks {
206            self.state.absorb_block(block.as_ref());
207        }
208    }
209}
210
211impl FixedOutputCore for AsconCore {
212    fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
213        debug_assert!(buffer.get_pos() < 8);
214        self.state
215            .absorb_last_block(&buffer.get_data()[..buffer.get_pos()]);
216        self.state.squeeze(out);
217    }
218}
219
220impl Reset for AsconCore {
221    fn reset(&mut self) {
222        *self = Default::default();
223    }
224}
225
226impl AlgorithmName for AsconCore {
227    fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
228        f.write_str("AsconHash")
229    }
230}
231
232/// Ascon hash implementation
233#[derive(Clone, Debug, Default)]
234pub struct AsconACore {
235    state: HashCore<ParametersA>,
236}
237
238impl HashMarker for AsconACore {}
239
240impl BlockSizeUser for AsconACore {
241    type BlockSize = U8;
242}
243
244impl BufferKindUser for AsconACore {
245    type BufferKind = Eager;
246}
247
248impl OutputSizeUser for AsconACore {
249    type OutputSize = U32;
250}
251
252impl UpdateCore for AsconACore {
253    fn update_blocks(&mut self, blocks: &[Block<Self>]) {
254        for block in blocks {
255            self.state.absorb_block(block.as_ref());
256        }
257    }
258}
259
260impl FixedOutputCore for AsconACore {
261    fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
262        debug_assert!(buffer.get_pos() < 8);
263        self.state
264            .absorb_last_block(&buffer.get_data()[..buffer.get_pos()]);
265        self.state.squeeze(out);
266    }
267}
268
269impl Reset for AsconACore {
270    fn reset(&mut self) {
271        *self = Default::default();
272    }
273}
274
275impl AlgorithmName for AsconACore {
276    fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
277        f.write_str("AsconAHash")
278    }
279}
280
281/// Ascon XOF
282#[derive(Clone, Debug, Default)]
283pub struct AsconXofCore {
284    state: HashCore<ParametersXof>,
285}
286
287impl HashMarker for AsconXofCore {}
288
289impl BlockSizeUser for AsconXofCore {
290    type BlockSize = U8;
291}
292
293impl BufferKindUser for AsconXofCore {
294    type BufferKind = Eager;
295}
296
297impl UpdateCore for AsconXofCore {
298    fn update_blocks(&mut self, blocks: &[Block<Self>]) {
299        for block in blocks {
300            self.state.absorb_block(block.as_ref());
301        }
302    }
303}
304
305/// Reader for XOF output
306#[derive(Clone, Debug)]
307pub struct AsconXofReaderCore {
308    hasher: HashCore<ParametersXof>,
309}
310
311impl BlockSizeUser for AsconXofReaderCore {
312    type BlockSize = U8;
313}
314
315impl XofReaderCore for AsconXofReaderCore {
316    fn read_block(&mut self) -> Block<Self> {
317        self.hasher.squeeze_block().into()
318    }
319}
320
321impl ExtendableOutputCore for AsconXofCore {
322    type ReaderCore = AsconXofReaderCore;
323
324    fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
325        debug_assert!(buffer.get_pos() < 8);
326        self.state
327            .absorb_last_block(&buffer.get_data()[..buffer.get_pos()]);
328        Self::ReaderCore {
329            hasher: self.state.clone(),
330        }
331    }
332}
333
334impl Reset for AsconXofCore {
335    fn reset(&mut self) {
336        *self = Default::default();
337    }
338}
339
340impl AlgorithmName for AsconXofCore {
341    fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
342        f.write_str("AsconXOF")
343    }
344}
345
346/// AsconA XOF
347#[derive(Clone, Debug, Default)]
348pub struct AsconAXofCore {
349    state: HashCore<ParametersAXof>,
350}
351
352impl HashMarker for AsconAXofCore {}
353
354impl BlockSizeUser for AsconAXofCore {
355    type BlockSize = U8;
356}
357
358impl BufferKindUser for AsconAXofCore {
359    type BufferKind = Eager;
360}
361
362impl UpdateCore for AsconAXofCore {
363    fn update_blocks(&mut self, blocks: &[Block<Self>]) {
364        for block in blocks {
365            self.state.absorb_block(block.as_ref());
366        }
367    }
368}
369
370/// Reader for XOF output
371#[derive(Clone, Debug)]
372pub struct AsconAXofReaderCore {
373    hasher: HashCore<ParametersAXof>,
374}
375
376impl BlockSizeUser for AsconAXofReaderCore {
377    type BlockSize = U8;
378}
379
380impl XofReaderCore for AsconAXofReaderCore {
381    fn read_block(&mut self) -> Block<Self> {
382        self.hasher.squeeze_block().into()
383    }
384}
385
386impl ExtendableOutputCore for AsconAXofCore {
387    type ReaderCore = AsconAXofReaderCore;
388
389    fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore {
390        debug_assert!(buffer.get_pos() < 8);
391        self.state
392            .absorb_last_block(&buffer.get_data()[..buffer.get_pos()]);
393        Self::ReaderCore {
394            hasher: self.state.clone(),
395        }
396    }
397}
398
399impl Reset for AsconAXofCore {
400    fn reset(&mut self) {
401        *self = Default::default();
402    }
403}
404
405impl AlgorithmName for AsconAXofCore {
406    fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
407        f.write_str("AsconAXOF")
408    }
409}
410
411/// Ascon hash
412///
413/// ```
414/// use ascon_hash::{AsconHash, Digest};
415///
416/// let mut hasher = AsconHash::new();
417/// hasher.update(b"some bytes");
418/// let digest = hasher.finalize();
419/// assert_eq!(&digest[..], b"\xb7\x42\xca\x75\xe5\x70\x38\x75\x70\x59\xcc\xcc\x68\x74\x71\x4f\x9d\xbd\x7f\xc5\x92\x4a\x7d\xf4\xe3\x16\x59\x4f\xd1\x42\x6c\xa8");
420/// ```
421pub type AsconHash = CoreWrapper<AsconCore>;
422/// AsconA hash
423///
424/// ```
425/// use ascon_hash::{AsconAHash, Digest};
426///
427/// let mut hasher = AsconAHash::new();
428/// hasher.update(b"some bytes");
429/// let digest = hasher.finalize();
430/// assert_eq!(&digest[..], b"\x1d\x1a\xc8\x74\x4a\x4a\x05\x81\x33\x7d\x5a\xf2\x78\xc2\x55\x88\xe1\xa3\xdd\x2d\x86\x73\x07\x64\x26\x53\xdc\xa4\x45\xf5\x5c\x2a");
431/// ```
432pub type AsconAHash = CoreWrapper<AsconACore>;
433/// AsconXof
434///
435/// ```
436/// use ascon_hash::{AsconXof, ExtendableOutput, Update, XofReader};
437///
438/// let mut xof = AsconXof::default();
439/// xof.update(b"some bytes");
440/// let mut reader = xof.finalize_xof();
441/// let mut dst = [0u8; 5];
442/// reader.read(&mut dst);
443/// assert_eq!(&dst, b"\xc2\x19\x72\xfd\xe9");
444/// ```
445pub type AsconXof = CoreWrapper<AsconXofCore>;
446/// Reader for AsconXof output
447pub type AsconAXofReader = XofReaderCoreWrapper<AsconAXofReaderCore>;
448/// AsconAXof
449///
450/// ```
451/// use ascon_hash::{AsconAXof, ExtendableOutput, Update, XofReader};
452///
453/// let mut xof = AsconAXof::default();
454/// xof.update(b"some bytes");
455/// let mut reader = xof.finalize_xof();
456/// let mut dst = [0u8; 5];
457/// reader.read(&mut dst);
458/// assert_eq!(&dst, b"\xb8\xd6\xbd\xf0\xa7");
459/// ```
460pub type AsconAXof = CoreWrapper<AsconAXofCore>;
461/// Reader for AsconAXof output
462pub type AsconXofReader = XofReaderCoreWrapper<AsconAXofReaderCore>;