Skip to content

Commit 7896dab

Browse files
committed
ascon-hash256: refactor code and split XOF into separate crate
1 parent 979ced9 commit 7896dab

26 files changed

Lines changed: 708 additions & 8735 deletions

Cargo.lock

Lines changed: 9 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
resolver = "3"
33
members = [
44
"ascon-hash256",
5+
"ascon-xof128",
56
"bash-hash",
67
"belt-hash",
78
"blake2",

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ easily used for bare-metal or WebAssembly programming by disabling default crate
1717

1818
| Algorithm | Crate | Crates.io | Documentation | MSRV | [Security] |
1919
|-----------|-------|:---------:|:-------------:|:----:|:----------:|
20-
| [Ascon] hash | [`ascon‑hash256`] | [![crates.io](https://img.shields.io/crates/v/ascon-hash256.svg)](https://crates.io/crates/ascon-hash256) | [![Documentation](https://docs.rs/ascon-hash256/badge.svg)](https://docs.rs/ascon-hash256) | 1.85 | :green_heart: |
20+
| [Ascon-Hash256] | [`ascon-hash256`] | [![crates.io](https://img.shields.io/crates/v/ascon-hash256.svg)](https://crates.io/crates/ascon-hash256) | [![Documentation](https://docs.rs/ascon-hash256/badge.svg)](https://docs.rs/ascon-hash256) | 1.85 | :green_heart: |
21+
| [Ascon-XOF128] | [`ascon-xof128`] | [![crates.io](https://img.shields.io/crates/v/ascon-xof128.svg)](https://crates.io/crates/ascon-xof128) | [![Documentation](https://docs.rs/ascon-xof128/badge.svg)](https://docs.rs/ascon-xof128) | 1.85 | :green_heart: |
2122
| [Bash] hash | [`bash‑hash`] | [![crates.io](https://img.shields.io/crates/v/bash-hash.svg)](https://crates.io/crates/bash-hash) | [![Documentation](https://docs.rs/bash-hash/badge.svg)](https://docs.rs/bash-hash) | 1.85 | :green_heart: |
2223
| [BelT] hash | [`belt‑hash`] | [![crates.io](https://img.shields.io/crates/v/belt-hash.svg)](https://crates.io/crates/belt-hash) | [![Documentation](https://docs.rs/belt-hash/badge.svg)](https://docs.rs/belt-hash) | 1.85 | :green_heart: |
2324
| [BLAKE2] | [`blake2`] | [![crates.io](https://img.shields.io/crates/v/blake2.svg)](https://crates.io/crates/blake2) | [![Documentation](https://docs.rs/blake2/badge.svg)](https://docs.rs/blake2) | 1.85 | :green_heart: |
@@ -93,6 +94,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted
9394
[//]: # (crates)
9495

9596
[`ascon‑hash256`]: ./ascon-hash256
97+
[`ascon‑xof128`]: ./ascon-xof128
9698
[`bash‑hash`]: ./bash-hash
9799
[`belt‑hash`]: ./belt-hash
98100
[`blake2`]: ./blake2
@@ -138,7 +140,8 @@ Unless you explicitly state otherwise, any contribution intentionally submitted
138140

139141
[//]: # (algorithms)
140142

141-
[Ascon]: https://ascon.iaik.tugraz.at
143+
[Ascon-Hash256]: https://doi.org/10.6028/NIST.SP.800-232.ipd
144+
[Ascon-Xof128]: https://doi.org/10.6028/NIST.SP.800-232.ipd
142145
[Bash]: https://apmi.bsu.by/assets/files/std/bash-spec241.pdf
143146
[BelT]: https://ru.wikipedia.org/wiki/BelT
144147
[BLAKE2]: https://en.wikipedia.org/wiki/BLAKE_(hash_function)#BLAKE2

ascon-hash256/Cargo.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,16 @@ description = "Implementation of Ascon-Hash256 and Ascon-XOF256"
1414

1515
[dependencies]
1616
digest = "0.11"
17-
ascon = { version = "0.5.0-rc.0", default-features = false }
17+
ascon = { git = "https://github.com/RustCrypto/sponges" }
1818

1919
[dev-dependencies]
20-
spectral = { version = "0.6", default-features = false }
21-
hex = "0.4"
20+
digest = { version = "0.11", features = ["dev"] }
2221
hex-literal = "1"
2322

2423
[features]
2524
default = ["alloc"]
2625
alloc = ["digest/alloc"]
27-
zeroize = ["ascon/zeroize", "digest/zeroize"]
26+
zeroize = ["digest/zeroize"]
2827

2928
[package.metadata.docs.rs]
3029
all-features = true

ascon-hash256/LICENSE-MIT

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
Copyright (c) 2023-2026 The RustCrypto Project Developers
2-
Copyright (c) 2022-2023 Sebastian Ramacher <sebastian.ramacher@ait.ac.at>
1+
Copyright (c) 2026 The RustCrypto Project Developers
32

43
Permission is hereby granted, free of charge, to any
54
person obtaining a copy of this software and associated

ascon-hash256/README.md

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# RustCrypto: Ascon-Hash256 and Ascon-XOF128
1+
# RustCrypto: Ascon-Hash256
22

33
[![crate][crate-image]][crate-link]
44
[![Docs][docs-image]][docs-link]
@@ -7,17 +7,10 @@
77
![Rust Version][rustc-image]
88
[![Project Chat][chat-image]][chat-link]
99

10-
Pure Rust implementation of the lightweight cryptographic hash function [Ascon-Hash256][1] and the
11-
extendable output functions (XOF) Ascon-XOF128.
12-
13-
## Security Notes
14-
15-
No security audits of this crate have ever been performed.
16-
17-
USE AT YOUR OWN RISK!
10+
Pure Rust implementation of the [Ascon-Hash256] cryptographic hash function.
1811

1912
## Examples
20-
Fixed output size hashing:
13+
2114
```rust
2215
use ascon_hash256::{AsconHash256, Digest};
2316
use hex_literal::hex;
@@ -29,19 +22,6 @@ let hash = hasher.finalize();
2922
assert_eq!(hash, hex!("e909c2f6da9cb3028423265c8f23fc2d26bfc0f3db704683ef16b787a945ed68"));
3023
```
3124

32-
XOF hashing:
33-
```rust
34-
use ascon_hash256::{AsconXof128, ExtendableOutput, Update, XofReader};
35-
use hex_literal::hex;
36-
37-
let mut xof = AsconXof128::default();
38-
xof.update(b"some bytes");
39-
let mut reader = xof.finalize_xof();
40-
let mut dst = [0u8; 5];
41-
reader.read(&mut dst);
42-
assert_eq!(dst, hex!("8c7dd114a0"));
43-
```
44-
4525
See the [`digest`] crate docs for additional examples.
4626

4727
## License
@@ -74,5 +54,5 @@ dual licensed as above, without any additional terms or conditions.
7454

7555
[//]: # (general links)
7656

77-
[1]: https://doi.org/10.6028/NIST.SP.800-232.ipd
57+
[Ascon-Hash256]: https://doi.org/10.6028/NIST.SP.800-232.ipd
7858
[`digest`]: https://docs.rs/digest

ascon-hash256/src/block_api.rs

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

0 commit comments

Comments
 (0)