v / vlib / x / crypto / ascon / hash.v
130 lines · 117 sloc · 3.66 KB · a10c59704b4fd795accd3542aed10e131d050ec4
Raw
1// Copyright ©2025 blackshirt.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4//
5// This file implement hashing routines based on Ascon-Hash256 schema defined in NIST SP 800-232 standard,
6// Ascon-Hash256 hashing produces 256-bits output.
7module ascon
8
9// block_size is the size (rate) of Ascon-Hash256, Ascon-XOF128 and Ascon-CXOF128 operates on.
10const block_size = 8
11
12// hash256_size is the length of the Ascon-Hash256 checksum output, in bytes
13const hash256_size = 32
14
15// hash256_initial_state is a precomputed value for Ascon-Hash256 state.
16//
17// The 320-bit internal state of Ascon-Hash256 is initialized with the
18// concatenation of the 64-bit 𝐼𝑉 = 0x0000080100cc0002 and 256 zeroes, followed
19// by the 𝐴𝑠𝑐𝑜𝑛-𝑝[12] permutation as S ← 𝐴𝑠𝑐𝑜𝑛-𝑝[12](𝐼𝑉 ∥0256).
20//
21// s.e0 = 0x0000080100cc0002
22// s.e1 = 0
23// s.e2 = 0
24// s.e3 = 0
25// s.e4 = 0
26// ascon_pnr(mut s, 12)
27//
28// Above step can be replaced with precomputed value to reduce runtime computations.
29// See the detail on the NIST SP 800-232 standard on Sec A.3. Precomputation
30// 𝑆0 ← 0x9b1e5494e934d681
31// 𝑆1 ← 0x4bc3a01e333751d2
32// 𝑆2 ← 0xae65396c6b34b81a
33// 𝑆3 ← 0x3c7fd4a4d56a4db3
34// 𝑆4 ← 0x1a5c464906c5976d
35//
36const hash256_initial_state = State{
37 e0: u64(0x9b1e5494e934d681)
38 e1: 0x4bc3a01e333751d2
39 e2: 0xae65396c6b34b81a
40 e3: 0x3c7fd4a4d56a4db3
41 e4: 0x1a5c464906c5976d
42}
43
44// sum256 creates an Ascon-Hash256 checksum for bytes on msg and produces a 256-bit hash.
45pub fn sum256(msg_ []u8) []u8 {
46 // This is single-shot function, so, no need to use Hash256 opaque that process
47 // message in streaming way. To reduce this overhead, use raw processing instead.
48 //
49 // Initialize state
50 mut s := hash256_initial_state
51 return ascon_generic_hash(mut s, msg_, hash256_size)
52}
53
54// Hash256 is an opaque provides an implementation of Ascon-Hash256 from NIST.SP.800-232 standard.
55// Its implements `hash.Hash` interface.
56@[noinit]
57pub struct Hash256 {
58 Digest
59}
60
61// new_hash256 creates a new Ascon-Hash256 instance.
62pub fn new_hash256() &Hash256 {
63 return &Hash256{
64 Digest: Digest{
65 State: hash256_initial_state
66 }
67 }
68}
69
70// size returns an underlying size of Hash256 checksum, ie, 32-bytes
71pub fn (h &Hash256) size() int {
72 return hash256_size
73}
74
75// block_size returns an underlying Hash256 block size operates on, ie, 8-bytes
76pub fn (h &Hash256) block_size() int {
77 return block_size
78}
79
80// reset resets and reinit internal Hash256 state into default initialized state.
81pub fn (mut h Hash256) reset() {
82 h.Digest.State = hash256_initial_state
83 unsafe { h.Digest.buf.reset() }
84 h.Digest.length = 0
85 h.Digest.done = false
86}
87
88// free releases out the resources taken by the `h`. Dont use x after .free call.
89@[unsafe]
90pub fn (mut h Hash256) free() {
91 $if prealloc {
92 return
93 }
94 unsafe {
95 h.Digest.buf.free()
96 }
97 // Mark it as unusable
98 h.Digest.done = true
99}
100
101// write writes out the content of message and updates internal Hash256 state.
102pub fn (mut h Hash256) write(msg []u8) !int {
103 if h.Digest.done {
104 panic('Digest: writing after done ')
105 }
106 return h.absorb(msg)
107}
108
109// clone returns the clone of the current Hash256
110fn (h &Hash256) clone() &Hash256 {
111 digest := Digest{
112 State: h.Digest.State
113 buf: h.Digest.buf.clone()
114 length: h.Digest.length
115 done: h.Digest.done
116 }
117 return &Hash256{digest}
118}
119
120// sum returns an Ascon-Hash256 checksum of the bytes in data.
121pub fn (mut h Hash256) sum(data []u8) []u8 {
122 // working on the clone of the h, so we can keep writing
123 mut h0 := h.clone()
124 _ := h0.write(data) or { panic(err) }
125 h0.Digest.finish()
126 mut dst := []u8{len: hash256_size}
127 _ := h0.Digest.squeeze(mut dst)
128 h0.reset()
129 return dst
130}
131