8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- //! An implementation of SipHash 2-4 .
11
+ //! An implementation of SipHash.
12
12
13
13
use prelude:: v1:: * ;
14
14
15
+ use marker:: PhantomData ;
15
16
use ptr;
16
- use super :: Hasher ;
17
+
18
+ /// An implementation of SipHash 1-3.
19
+ ///
20
+ /// See: https://131002.net/siphash/
21
+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
22
+ #[ derive( Debug , Clone , Default ) ]
23
+ pub struct SipHasher13 {
24
+ hasher : Hasher < Sip13Rounds > ,
25
+ }
26
+
27
+ /// An implementation of SipHash 2-4.
28
+ ///
29
+ /// See: https://131002.net/siphash/
30
+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
31
+ #[ derive( Debug , Clone , Default ) ]
32
+ pub struct SipHasher24 {
33
+ hasher : Hasher < Sip24Rounds > ,
34
+ }
17
35
18
36
/// An implementation of SipHash 2-4.
19
37
///
@@ -30,22 +48,31 @@ use super::Hasher;
30
48
/// Although the SipHash algorithm is considered to be generally strong,
31
49
/// it is not intended for cryptographic purposes. As such, all
32
50
/// cryptographic uses of this implementation are _strongly discouraged_.
33
- #[ derive( Debug ) ]
34
51
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
35
- pub struct SipHasher {
52
+ #[ derive( Debug , Clone , Default ) ]
53
+ pub struct SipHasher ( SipHasher24 ) ;
54
+
55
+ #[ derive( Debug ) ]
56
+ struct Hasher < S : Sip > {
36
57
k0 : u64 ,
37
58
k1 : u64 ,
38
59
length : usize , // how many bytes we've processed
60
+ state : State , // hash State
61
+ tail : u64 , // unprocessed bytes le
62
+ ntail : usize , // how many bytes in tail are valid
63
+ _marker : PhantomData < S > ,
64
+ }
65
+
66
+ #[ derive( Debug , Clone , Copy ) ]
67
+ struct State {
39
68
// v0, v2 and v1, v3 show up in pairs in the algorithm,
40
69
// and simd implementations of SipHash will use vectors
41
70
// of v02 and v13. By placing them in this order in the struct,
42
71
// the compiler can pick up on just a few simd optimizations by itself.
43
- v0 : u64 , // hash state
72
+ v0 : u64 ,
44
73
v2 : u64 ,
45
74
v1 : u64 ,
46
75
v3 : u64 ,
47
- tail : u64 , // unprocessed bytes le
48
- ntail : usize , // how many bytes in tail are valid
49
76
}
50
77
51
78
// sadly, these macro definitions can't appear later,
@@ -93,6 +120,9 @@ macro_rules! rotl {
93
120
}
94
121
95
122
macro_rules! compress {
123
+ ( $state: expr) => ( {
124
+ compress!( $state. v0, $state. v1, $state. v2, $state. v3)
125
+ } ) ;
96
126
( $v0: expr, $v1: expr, $v2: expr, $v3: expr) =>
97
127
( {
98
128
$v0 = $v0. wrapping_add( $v1) ; $v1 = rotl!( $v1, 13 ) ; $v1 ^= $v0;
@@ -101,7 +131,7 @@ macro_rules! compress {
101
131
$v0 = $v0. wrapping_add( $v3) ; $v3 = rotl!( $v3, 21 ) ; $v3 ^= $v0;
102
132
$v2 = $v2. wrapping_add( $v1) ; $v1 = rotl!( $v1, 17 ) ; $v1 ^= $v2;
103
133
$v2 = rotl!( $v2, 32 ) ;
104
- } )
134
+ } ) ;
105
135
}
106
136
107
137
impl SipHasher {
@@ -116,16 +146,63 @@ impl SipHasher {
116
146
#[ inline]
117
147
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
118
148
pub fn new_with_keys ( key0 : u64 , key1 : u64 ) -> SipHasher {
119
- let mut state = SipHasher {
149
+ SipHasher ( SipHasher24 :: new_with_keys ( key0, key1) )
150
+ }
151
+ }
152
+
153
+
154
+ impl SipHasher13 {
155
+ /// Creates a new `SipHasher13` with the two initial keys set to 0.
156
+ #[ inline]
157
+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
158
+ pub fn new ( ) -> SipHasher13 {
159
+ SipHasher13 :: new_with_keys ( 0 , 0 )
160
+ }
161
+
162
+ /// Creates a `SipHasher13` that is keyed off the provided keys.
163
+ #[ inline]
164
+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
165
+ pub fn new_with_keys ( key0 : u64 , key1 : u64 ) -> SipHasher13 {
166
+ SipHasher13 {
167
+ hasher : Hasher :: new_with_keys ( key0, key1)
168
+ }
169
+ }
170
+ }
171
+
172
+ impl SipHasher24 {
173
+ /// Creates a new `SipHasher24` with the two initial keys set to 0.
174
+ #[ inline]
175
+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
176
+ pub fn new ( ) -> SipHasher24 {
177
+ SipHasher24 :: new_with_keys ( 0 , 0 )
178
+ }
179
+
180
+ /// Creates a `SipHasher24` that is keyed off the provided keys.
181
+ #[ inline]
182
+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
183
+ pub fn new_with_keys ( key0 : u64 , key1 : u64 ) -> SipHasher24 {
184
+ SipHasher24 {
185
+ hasher : Hasher :: new_with_keys ( key0, key1)
186
+ }
187
+ }
188
+ }
189
+
190
+ impl < S : Sip > Hasher < S > {
191
+ #[ inline]
192
+ fn new_with_keys ( key0 : u64 , key1 : u64 ) -> Hasher < S > {
193
+ let mut state = Hasher {
120
194
k0 : key0,
121
195
k1 : key1,
122
196
length : 0 ,
123
- v0 : 0 ,
124
- v1 : 0 ,
125
- v2 : 0 ,
126
- v3 : 0 ,
197
+ state : State {
198
+ v0 : 0 ,
199
+ v1 : 0 ,
200
+ v2 : 0 ,
201
+ v3 : 0 ,
202
+ } ,
127
203
tail : 0 ,
128
204
ntail : 0 ,
205
+ _marker : PhantomData ,
129
206
} ;
130
207
state. reset ( ) ;
131
208
state
@@ -134,16 +211,54 @@ impl SipHasher {
134
211
#[ inline]
135
212
fn reset ( & mut self ) {
136
213
self . length = 0 ;
137
- self . v0 = self . k0 ^ 0x736f6d6570736575 ;
138
- self . v1 = self . k1 ^ 0x646f72616e646f6d ;
139
- self . v2 = self . k0 ^ 0x6c7967656e657261 ;
140
- self . v3 = self . k1 ^ 0x7465646279746573 ;
214
+ self . state . v0 = self . k0 ^ 0x736f6d6570736575 ;
215
+ self . state . v1 = self . k1 ^ 0x646f72616e646f6d ;
216
+ self . state . v2 = self . k0 ^ 0x6c7967656e657261 ;
217
+ self . state . v3 = self . k1 ^ 0x7465646279746573 ;
141
218
self . ntail = 0 ;
142
219
}
143
220
}
144
221
145
222
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
146
- impl Hasher for SipHasher {
223
+ impl super :: Hasher for SipHasher {
224
+ #[ inline]
225
+ fn write ( & mut self , msg : & [ u8 ] ) {
226
+ self . 0 . write ( msg)
227
+ }
228
+
229
+ #[ inline]
230
+ fn finish ( & self ) -> u64 {
231
+ self . 0 . finish ( )
232
+ }
233
+ }
234
+
235
+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
236
+ impl super :: Hasher for SipHasher13 {
237
+ #[ inline]
238
+ fn write ( & mut self , msg : & [ u8 ] ) {
239
+ self . hasher . write ( msg)
240
+ }
241
+
242
+ #[ inline]
243
+ fn finish ( & self ) -> u64 {
244
+ self . hasher . finish ( )
245
+ }
246
+ }
247
+
248
+ #[ unstable( feature = "sip_hash_13" , issue = "29754" ) ]
249
+ impl super :: Hasher for SipHasher24 {
250
+ #[ inline]
251
+ fn write ( & mut self , msg : & [ u8 ] ) {
252
+ self . hasher . write ( msg)
253
+ }
254
+
255
+ #[ inline]
256
+ fn finish ( & self ) -> u64 {
257
+ self . hasher . finish ( )
258
+ }
259
+ }
260
+
261
+ impl < S : Sip > super :: Hasher for Hasher < S > {
147
262
#[ inline]
148
263
fn write ( & mut self , msg : & [ u8 ] ) {
149
264
let length = msg. len ( ) ;
@@ -161,10 +276,9 @@ impl Hasher for SipHasher {
161
276
162
277
let m = self . tail | u8to64_le ! ( msg, 0 , needed) << 8 * self . ntail ;
163
278
164
- self . v3 ^= m;
165
- compress ! ( self . v0, self . v1, self . v2, self . v3) ;
166
- compress ! ( self . v0, self . v1, self . v2, self . v3) ;
167
- self . v0 ^= m;
279
+ self . state . v3 ^= m;
280
+ S :: c_rounds ( & mut self . state ) ;
281
+ self . state . v0 ^= m;
168
282
169
283
self . ntail = 0 ;
170
284
}
@@ -177,10 +291,9 @@ impl Hasher for SipHasher {
177
291
while i < len - left {
178
292
let mi = unsafe { load_u64_le ( msg, i) } ;
179
293
180
- self . v3 ^= mi;
181
- compress ! ( self . v0, self . v1, self . v2, self . v3) ;
182
- compress ! ( self . v0, self . v1, self . v2, self . v3) ;
183
- self . v0 ^= mi;
294
+ self . state . v3 ^= mi;
295
+ S :: c_rounds ( & mut self . state ) ;
296
+ self . state . v0 ^= mi;
184
297
185
298
i += 8 ;
186
299
}
@@ -191,49 +304,81 @@ impl Hasher for SipHasher {
191
304
192
305
#[ inline]
193
306
fn finish ( & self ) -> u64 {
194
- let mut v0 = self . v0 ;
195
- let mut v1 = self . v1 ;
196
- let mut v2 = self . v2 ;
197
- let mut v3 = self . v3 ;
307
+ let mut state = self . state ;
198
308
199
309
let b: u64 = ( ( self . length as u64 & 0xff ) << 56 ) | self . tail ;
200
310
201
- v3 ^= b;
202
- compress ! ( v0, v1, v2, v3) ;
203
- compress ! ( v0, v1, v2, v3) ;
204
- v0 ^= b;
311
+ state. v3 ^= b;
312
+ S :: c_rounds ( & mut state) ;
313
+ state. v0 ^= b;
205
314
206
- v2 ^= 0xff ;
207
- compress ! ( v0, v1, v2, v3) ;
208
- compress ! ( v0, v1, v2, v3) ;
209
- compress ! ( v0, v1, v2, v3) ;
210
- compress ! ( v0, v1, v2, v3) ;
315
+ state. v2 ^= 0xff ;
316
+ S :: d_rounds ( & mut state) ;
211
317
212
- v0 ^ v1 ^ v2 ^ v3
318
+ state . v0 ^ state . v1 ^ state . v2 ^ state . v3
213
319
}
214
320
}
215
321
216
- #[ stable( feature = "rust1" , since = "1.0.0" ) ]
217
- impl Clone for SipHasher {
322
+ impl < S : Sip > Clone for Hasher < S > {
218
323
#[ inline]
219
- fn clone ( & self ) -> SipHasher {
220
- SipHasher {
324
+ fn clone ( & self ) -> Hasher < S > {
325
+ Hasher {
221
326
k0 : self . k0 ,
222
327
k1 : self . k1 ,
223
328
length : self . length ,
224
- v0 : self . v0 ,
225
- v1 : self . v1 ,
226
- v2 : self . v2 ,
227
- v3 : self . v3 ,
329
+ state : self . state ,
228
330
tail : self . tail ,
229
331
ntail : self . ntail ,
332
+ _marker : self . _marker ,
230
333
}
231
334
}
232
335
}
233
336
234
- #[ stable( feature = "rust1" , since = "1.0.0" ) ]
235
- impl Default for SipHasher {
236
- fn default ( ) -> SipHasher {
237
- SipHasher :: new ( )
337
+ impl < S : Sip > Default for Hasher < S > {
338
+ #[ inline]
339
+ fn default ( ) -> Hasher < S > {
340
+ Hasher :: new_with_keys ( 0 , 0 )
341
+ }
342
+ }
343
+
344
+ #[ doc( hidden) ]
345
+ trait Sip {
346
+ fn c_rounds ( & mut State ) ;
347
+ fn d_rounds ( & mut State ) ;
348
+ }
349
+
350
+ #[ derive( Debug , Clone , Default ) ]
351
+ struct Sip13Rounds ;
352
+
353
+ impl Sip for Sip13Rounds {
354
+ #[ inline]
355
+ fn c_rounds ( state : & mut State ) {
356
+ compress ! ( state) ;
357
+ }
358
+
359
+ #[ inline]
360
+ fn d_rounds ( state : & mut State ) {
361
+ compress ! ( state) ;
362
+ compress ! ( state) ;
363
+ compress ! ( state) ;
364
+ }
365
+ }
366
+
367
+ #[ derive( Debug , Clone , Default ) ]
368
+ struct Sip24Rounds ;
369
+
370
+ impl Sip for Sip24Rounds {
371
+ #[ inline]
372
+ fn c_rounds ( state : & mut State ) {
373
+ compress ! ( state) ;
374
+ compress ! ( state) ;
375
+ }
376
+
377
+ #[ inline]
378
+ fn d_rounds ( state : & mut State ) {
379
+ compress ! ( state) ;
380
+ compress ! ( state) ;
381
+ compress ! ( state) ;
382
+ compress ! ( state) ;
238
383
}
239
384
}
0 commit comments