hashtree_rs/
lib.rs

1//! Hasthree rust bindings
2//!
3//! hashtree is a SHA256 library highly optimized for Merkle tree computations. It is based on
4//! Intel's implementation (intel-ipsec-mb) with a few modifications like hardcoding the scheduled
5//! words. This library exposes a single function that takes an input slice of bytes to be
6//! considered as chunks of 64 bytes each, and another slice where the digests of each chunk will
7//! be written consecutively
8//!
9
10/*
11MIT License
12
13Copyright (c) 2021-2024 Prysmatic Labs
14
15Permission is hereby granted, free of charge, to any person obtaining a copy
16of this software and associated documentation files (the "Software"), to deal
17in the Software without restriction, including without limitation the rights
18to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19copies of the Software, and to permit persons to whom the Software is
20furnished to do so, subject to the following conditions:
21
22The above copyright notice and this permission notice shall be included in all
23copies or substantial portions of the Software.
24
25THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31SOFTWARE.
32*/
33
34extern crate libc;
35use libc::c_int;
36use std::ptr;
37
38type HashFunction = extern "C" fn(*mut u8, *const u8, u64);
39
40extern "C" {
41    fn hashtree_init(override_: *const HashFunction) -> c_int;
42    fn hashtree_hash(output: *mut u8, input: *const u8, count: u64);
43}
44
45/// init is used to initialize the hashtree library. It automatically chooses the best
46/// implementation.
47pub fn init() -> i32 {
48    unsafe { hashtree_init(ptr::null()) }
49}
50
51/// hash takes a mutable slice where the digests will be stored (overwritten), a slice with the
52/// chunks to merkleize and the number of chunks to merkleize
53pub fn hash(out: &mut [u8], chunks: &[u8], count: usize) {
54    unsafe { hashtree_hash(out.as_mut_ptr(), chunks.as_ptr(), count as u64) }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn test_init() {
63        assert_eq!(init(), 1);
64    }
65
66    #[test]
67    fn test_hash() {
68        let chunks: [u8; 64] = [0xAB; 64];
69        let mut out = [0u8; 32];
70
71        hash(&mut out, &chunks, 1);
72
73        let expected_hash: [u8; 32] = [
74            0xec, 0x65, 0xc8, 0x79, 0x8e, 0xcf, 0x95, 0x90, 0x24, 0x13, 0xc4, 0x0f, 0x7b, 0x9e,
75            0x6d, 0x4b, 0x00, 0x68, 0x88, 0x5f, 0x5f, 0x32, 0x4a, 0xba, 0x1f, 0x9b, 0xa1, 0xc8,
76            0xe1, 0x4a, 0xea, 0x61,
77        ];
78
79        assert_eq!(
80            out, expected_hash,
81            "The generated hash did not match the expected hash."
82        );
83    }
84}