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}