]>
Commit | Line | Data |
---|---|---|
9135bf4d MCC |
1 | =========================== |
2 | SipHash - a short input PRF | |
3 | =========================== | |
4 | ||
5 | :Author: Written by Jason A. Donenfeld <jason@zx2c4.com> | |
2c956a60 JD |
6 | |
7 | SipHash is a cryptographically secure PRF -- a keyed hash function -- that | |
8 | performs very well for short inputs, hence the name. It was designed by | |
9 | cryptographers Daniel J. Bernstein and Jean-Philippe Aumasson. It is intended | |
10 | as a replacement for some uses of: `jhash`, `md5_transform`, `sha_transform`, | |
11 | and so forth. | |
12 | ||
13 | SipHash takes a secret key filled with randomly generated numbers and either | |
14 | an input buffer or several input integers. It spits out an integer that is | |
15 | indistinguishable from random. You may then use that integer as part of secure | |
16 | sequence numbers, secure cookies, or mask it off for use in a hash table. | |
17 | ||
9135bf4d MCC |
18 | Generating a key |
19 | ================ | |
2c956a60 JD |
20 | |
21 | Keys should always be generated from a cryptographically secure source of | |
9135bf4d | 22 | random numbers, either using get_random_bytes or get_random_once:: |
2c956a60 | 23 | |
9135bf4d MCC |
24 | siphash_key_t key; |
25 | get_random_bytes(&key, sizeof(key)); | |
2c956a60 JD |
26 | |
27 | If you're not deriving your key from here, you're doing it wrong. | |
28 | ||
9135bf4d MCC |
29 | Using the functions |
30 | =================== | |
2c956a60 JD |
31 | |
32 | There are two variants of the function, one that takes a list of integers, and | |
9135bf4d | 33 | one that takes a buffer:: |
2c956a60 | 34 | |
9135bf4d | 35 | u64 siphash(const void *data, size_t len, const siphash_key_t *key); |
2c956a60 | 36 | |
9135bf4d | 37 | And:: |
2c956a60 | 38 | |
9135bf4d MCC |
39 | u64 siphash_1u64(u64, const siphash_key_t *key); |
40 | u64 siphash_2u64(u64, u64, const siphash_key_t *key); | |
41 | u64 siphash_3u64(u64, u64, u64, const siphash_key_t *key); | |
42 | u64 siphash_4u64(u64, u64, u64, u64, const siphash_key_t *key); | |
43 | u64 siphash_1u32(u32, const siphash_key_t *key); | |
44 | u64 siphash_2u32(u32, u32, const siphash_key_t *key); | |
45 | u64 siphash_3u32(u32, u32, u32, const siphash_key_t *key); | |
46 | u64 siphash_4u32(u32, u32, u32, u32, const siphash_key_t *key); | |
2c956a60 JD |
47 | |
48 | If you pass the generic siphash function something of a constant length, it | |
49 | will constant fold at compile-time and automatically choose one of the | |
50 | optimized functions. | |
51 | ||
9135bf4d | 52 | Hashtable key function usage:: |
2c956a60 | 53 | |
9135bf4d MCC |
54 | struct some_hashtable { |
55 | DECLARE_HASHTABLE(hashtable, 8); | |
56 | siphash_key_t key; | |
57 | }; | |
2c956a60 | 58 | |
9135bf4d MCC |
59 | void init_hashtable(struct some_hashtable *table) |
60 | { | |
61 | get_random_bytes(&table->key, sizeof(table->key)); | |
62 | } | |
2c956a60 | 63 | |
9135bf4d MCC |
64 | static inline hlist_head *some_hashtable_bucket(struct some_hashtable *table, struct interesting_input *input) |
65 | { | |
66 | return &table->hashtable[siphash(input, sizeof(*input), &table->key) & (HASH_SIZE(table->hashtable) - 1)]; | |
67 | } | |
2c956a60 JD |
68 | |
69 | You may then iterate like usual over the returned hash bucket. | |
70 | ||
9135bf4d MCC |
71 | Security |
72 | ======== | |
2c956a60 JD |
73 | |
74 | SipHash has a very high security margin, with its 128-bit key. So long as the | |
75 | key is kept secret, it is impossible for an attacker to guess the outputs of | |
76 | the function, even if being able to observe many outputs, since 2^128 outputs | |
77 | is significant. | |
78 | ||
79 | Linux implements the "2-4" variant of SipHash. | |
80 | ||
9135bf4d MCC |
81 | Struct-passing Pitfalls |
82 | ======================= | |
2c956a60 JD |
83 | |
84 | Often times the XuY functions will not be large enough, and instead you'll | |
85 | want to pass a pre-filled struct to siphash. When doing this, it's important | |
86 | to always ensure the struct has no padding holes. The easiest way to do this | |
87 | is to simply arrange the members of the struct in descending order of size, | |
88 | and to use offsetendof() instead of sizeof() for getting the size. For | |
89 | performance reasons, if possible, it's probably a good thing to align the | |
9135bf4d MCC |
90 | struct to the right boundary. Here's an example:: |
91 | ||
92 | const struct { | |
93 | struct in6_addr saddr; | |
94 | u32 counter; | |
95 | u16 dport; | |
96 | } __aligned(SIPHASH_ALIGNMENT) combined = { | |
97 | .saddr = *(struct in6_addr *)saddr, | |
98 | .counter = counter, | |
99 | .dport = dport | |
100 | }; | |
101 | u64 h = siphash(&combined, offsetofend(typeof(combined), dport), &secret); | |
102 | ||
103 | Resources | |
104 | ========= | |
2c956a60 JD |
105 | |
106 | Read the SipHash paper if you're interested in learning more: | |
107 | https://131002.net/siphash/siphash.pdf | |
1ae2324f | 108 | |
9135bf4d | 109 | ------------------------------------------------------------------------------- |
1ae2324f | 110 | |
9135bf4d | 111 | =============================================== |
1ae2324f | 112 | HalfSipHash - SipHash's insecure younger cousin |
9135bf4d MCC |
113 | =============================================== |
114 | ||
115 | :Author: Written by Jason A. Donenfeld <jason@zx2c4.com> | |
1ae2324f JD |
116 | |
117 | On the off-chance that SipHash is not fast enough for your needs, you might be | |
118 | able to justify using HalfSipHash, a terrifying but potentially useful | |
119 | possibility. HalfSipHash cuts SipHash's rounds down from "2-4" to "1-3" and, | |
120 | even scarier, uses an easily brute-forcable 64-bit key (with a 32-bit output) | |
121 | instead of SipHash's 128-bit key. However, this may appeal to some | |
122 | high-performance `jhash` users. | |
123 | ||
124 | Danger! | |
125 | ||
126 | Do not ever use HalfSipHash except for as a hashtable key function, and only | |
127 | then when you can be absolutely certain that the outputs will never be | |
128 | transmitted out of the kernel. This is only remotely useful over `jhash` as a | |
129 | means of mitigating hashtable flooding denial of service attacks. | |
130 | ||
9135bf4d MCC |
131 | Generating a key |
132 | ================ | |
1ae2324f JD |
133 | |
134 | Keys should always be generated from a cryptographically secure source of | |
135 | random numbers, either using get_random_bytes or get_random_once: | |
136 | ||
137 | hsiphash_key_t key; | |
138 | get_random_bytes(&key, sizeof(key)); | |
139 | ||
140 | If you're not deriving your key from here, you're doing it wrong. | |
141 | ||
9135bf4d MCC |
142 | Using the functions |
143 | =================== | |
1ae2324f JD |
144 | |
145 | There are two variants of the function, one that takes a list of integers, and | |
9135bf4d | 146 | one that takes a buffer:: |
1ae2324f | 147 | |
9135bf4d | 148 | u32 hsiphash(const void *data, size_t len, const hsiphash_key_t *key); |
1ae2324f | 149 | |
9135bf4d | 150 | And:: |
1ae2324f | 151 | |
9135bf4d MCC |
152 | u32 hsiphash_1u32(u32, const hsiphash_key_t *key); |
153 | u32 hsiphash_2u32(u32, u32, const hsiphash_key_t *key); | |
154 | u32 hsiphash_3u32(u32, u32, u32, const hsiphash_key_t *key); | |
155 | u32 hsiphash_4u32(u32, u32, u32, u32, const hsiphash_key_t *key); | |
1ae2324f JD |
156 | |
157 | If you pass the generic hsiphash function something of a constant length, it | |
158 | will constant fold at compile-time and automatically choose one of the | |
159 | optimized functions. | |
160 | ||
9135bf4d MCC |
161 | Hashtable key function usage |
162 | ============================ | |
163 | ||
164 | :: | |
1ae2324f | 165 | |
9135bf4d MCC |
166 | struct some_hashtable { |
167 | DECLARE_HASHTABLE(hashtable, 8); | |
168 | hsiphash_key_t key; | |
169 | }; | |
1ae2324f | 170 | |
9135bf4d MCC |
171 | void init_hashtable(struct some_hashtable *table) |
172 | { | |
173 | get_random_bytes(&table->key, sizeof(table->key)); | |
174 | } | |
1ae2324f | 175 | |
9135bf4d MCC |
176 | static inline hlist_head *some_hashtable_bucket(struct some_hashtable *table, struct interesting_input *input) |
177 | { | |
178 | return &table->hashtable[hsiphash(input, sizeof(*input), &table->key) & (HASH_SIZE(table->hashtable) - 1)]; | |
179 | } | |
1ae2324f JD |
180 | |
181 | You may then iterate like usual over the returned hash bucket. | |
182 | ||
9135bf4d MCC |
183 | Performance |
184 | =========== | |
1ae2324f JD |
185 | |
186 | HalfSipHash is roughly 3 times slower than JenkinsHash. For many replacements, | |
187 | this will not be a problem, as the hashtable lookup isn't the bottleneck. And | |
188 | in general, this is probably a good sacrifice to make for the security and DoS | |
189 | resistance of HalfSipHash. |