winter_crypto/hash/sha/
mod.rs

1// Copyright (c) Facebook, Inc. and its affiliates.
2//
3// This source code is licensed under the MIT license found in the
4// LICENSE file in the root directory of this source tree.
5
6use core::marker::PhantomData;
7
8use math::{FieldElement, StarkField};
9use sha3::Digest;
10use utils::ByteWriter;
11
12use super::{ByteDigest, ElementHasher, Hasher};
13
14// SHA3 WITH 256-BIT OUTPUT
15// ================================================================================================
16
17/// Implementation of the [Hasher](super::Hasher) trait for SHA3 hash function with 256-bit
18/// output.
19pub struct Sha3_256<B: StarkField>(PhantomData<B>);
20
21impl<B: StarkField> Hasher for Sha3_256<B> {
22    type Digest = ByteDigest<32>;
23
24    const COLLISION_RESISTANCE: u32 = 128;
25
26    fn hash(bytes: &[u8]) -> Self::Digest {
27        ByteDigest(sha3::Sha3_256::digest(bytes).into())
28    }
29
30    fn merge(values: &[Self::Digest; 2]) -> Self::Digest {
31        ByteDigest(sha3::Sha3_256::digest(ByteDigest::digests_as_bytes(values)).into())
32    }
33
34    fn merge_many(values: &[Self::Digest]) -> Self::Digest {
35        ByteDigest(sha3::Sha3_256::digest(ByteDigest::digests_as_bytes(values)).into())
36    }
37
38    fn merge_with_int(seed: Self::Digest, value: u64) -> Self::Digest {
39        let mut data = [0; 40];
40        data[..32].copy_from_slice(&seed.0);
41        data[32..].copy_from_slice(&value.to_le_bytes());
42        ByteDigest(sha3::Sha3_256::digest(data).into())
43    }
44}
45
46impl<B: StarkField> ElementHasher for Sha3_256<B> {
47    type BaseField = B;
48
49    fn hash_elements<E: FieldElement<BaseField = Self::BaseField>>(elements: &[E]) -> Self::Digest {
50        if B::IS_CANONICAL {
51            // when element's internal and canonical representations are the same, we can hash
52            // element bytes directly
53            let bytes = E::elements_as_bytes(elements);
54            ByteDigest(sha3::Sha3_256::digest(bytes).into())
55        } else {
56            // when elements' internal and canonical representations differ, we need to serialize
57            // them before hashing
58            let mut hasher = ShaHasher::new();
59            hasher.write_many(elements);
60            ByteDigest(hasher.finalize())
61        }
62    }
63}
64
65// SHA HASHER
66// ================================================================================================
67
68/// Wrapper around SHA3 hasher to implement [ByteWriter] trait for it.
69struct ShaHasher(sha3::Sha3_256);
70
71impl ShaHasher {
72    pub fn new() -> Self {
73        Self(sha3::Sha3_256::new())
74    }
75
76    pub fn finalize(self) -> [u8; 32] {
77        self.0.finalize().into()
78    }
79}
80
81impl ByteWriter for ShaHasher {
82    fn write_u8(&mut self, value: u8) {
83        self.0.update([value]);
84    }
85
86    fn write_bytes(&mut self, values: &[u8]) {
87        self.0.update(values);
88    }
89}