dryoc/classic/
crypto_shorthash.rs

1//! # Short-input hashing
2//!
3//! This module implements libsodium's short input hashing, based on
4//! SipHash-2-4.
5//!
6//! You may want to use short input hashing when:
7//!
8//! * you need to construct hash tables in a fashion that is collision resistant
9//!   (i.e., it's hard for other parties to guess when there may be a hash key
10//!   collision, which could lead to DoS or timing attacks)
11//! * you want to construct probabilistic data structures, such as bloom filters
12//! * you want to perform basic integrity checks on data
13//! * you have relatively short inputs
14//!
15//! The key used with this function should be treated as a secret. If used for
16//! constructing hash tables, it's recommended the table size be a prime number
17//! to ensure all bits from the output are used.
18//!
19//! For details, refer to [libsodium docs](https://libsodium.gitbook.io/doc/hashing/short-input_hashing).
20//!
21//! ## Classic API example
22//!
23//! ```
24//! use dryoc::classic::crypto_shorthash::*;
25//! use dryoc::rng::copy_randombytes;
26//!
27//! // Generate a random key
28//! let key = crypto_shorthash_keygen();
29//!
30//! // Generate some random input data
31//! let mut input = vec![0u8; 69];
32//! copy_randombytes(&mut input);
33//!
34//! // Compute the hash, put result into `output`
35//! let mut output = Hash::default();
36//! crypto_shorthash(&mut output, &input, &key);
37//! ```
38use crate::constants::{CRYPTO_SHORTHASH_BYTES, CRYPTO_SHORTHASH_KEYBYTES};
39use crate::rng::copy_randombytes;
40use crate::siphash24::siphash24;
41
42/// Hash type alias for short input hashing.
43pub type Hash = [u8; CRYPTO_SHORTHASH_BYTES];
44/// Key type alias for short input hashing.
45pub type Key = [u8; CRYPTO_SHORTHASH_KEYBYTES];
46
47/// Generates a random key for short input hashing.
48pub fn crypto_shorthash_keygen() -> Key {
49    let mut key = Key::default();
50    copy_randombytes(&mut key);
51    key
52}
53
54/// Computes a short input hash for `input` and `key`, placing the result into
55/// `output`, using SipHash-2-4.
56pub fn crypto_shorthash(output: &mut Hash, input: &[u8], key: &Key) {
57    siphash24(output, input, key)
58}
59
60#[cfg(test)]
61mod tests {
62    use rand::TryRngCore;
63
64    use super::*;
65
66    #[test]
67    fn test_shorthash() {
68        use rand_core::OsRng;
69        use sodiumoxide::crypto::shorthash;
70
71        for _ in 0..20 {
72            let key = crypto_shorthash_keygen();
73            let mut input = vec![0u8; (OsRng.try_next_u32().unwrap() % 69) as usize];
74            copy_randombytes(&mut input);
75            let mut output = Hash::default();
76
77            crypto_shorthash(&mut output, &input, &key);
78
79            let so_output = shorthash::shorthash(
80                &input,
81                &shorthash::Key::from_slice(&key).expect("so key failed"),
82            );
83
84            assert_eq!(output, so_output.0);
85        }
86    }
87}