@@ -32,7 +32,7 @@ pure fn hash_bytes_keyed(buf: &[const u8], k0: u64, k1: u64) -> u64 {
32
32
33
33
#macro ( [ #rotl ( x, b) , ( x << b) | ( x >> ( 64 - b) ) ] ) ;
34
34
35
- #macro ( [ #compress ( ) , {
35
+ #macro ( [ #compress ( v0 , v1 , v2 , v3 ) , {
36
36
v0 += v1; v1 = #rotl ( v1, 13 ) ; v1 ^= v0; v0 = #rotl ( v0, 32 ) ;
37
37
v2 += v3; v3 = #rotl ( v3, 16 ) ; v3 ^= v2;
38
38
v0 += v3; v3 = #rotl ( v3, 21 ) ; v3 ^= v0;
@@ -47,8 +47,8 @@ pure fn hash_bytes_keyed(buf: &[const u8], k0: u64, k1: u64) -> u64 {
47
47
while i < end {
48
48
let m = #u8to64_le ( buf, i) ;
49
49
v3 ^= m;
50
- #compress ( ) ;
51
- #compress ( ) ;
50
+ #compress ( v0 , v1 , v2 , v3 ) ;
51
+ #compress ( v0 , v1 , v2 , v3 ) ;
52
52
v0 ^= m;
53
53
i += 8 ;
54
54
}
@@ -64,19 +64,182 @@ pure fn hash_bytes_keyed(buf: &[const u8], k0: u64, k1: u64) -> u64 {
64
64
if left > 6 { b |= buf[ i + 6 ] as u64 << 48 ; }
65
65
66
66
v3 ^= b;
67
- #compress ( ) ;
68
- #compress ( ) ;
67
+ #compress ( v0 , v1 , v2 , v3 ) ;
68
+ #compress ( v0 , v1 , v2 , v3 ) ;
69
69
v0 ^= b;
70
70
71
71
v2 ^= 0xff ;
72
- #compress ( ) ;
73
- #compress ( ) ;
74
- #compress ( ) ;
75
- #compress ( ) ;
72
+
73
+ #compress ( v0, v1, v2, v3) ;
74
+ #compress ( v0, v1, v2, v3) ;
75
+ #compress ( v0, v1, v2, v3) ;
76
+ #compress ( v0, v1, v2, v3) ;
76
77
77
78
ret v0 ^ v1 ^ v2 ^ v3;
78
79
}
79
80
81
+
82
+ iface streaming {
83
+ fn input( ~[ u8] ) ;
84
+ fn input_str ( ~str ) ;
85
+ fn result ( ) -> ~[ u8 ] ;
86
+ fn result_str ( ) -> ~str ;
87
+ fn reset ( ) ;
88
+ }
89
+
90
+ fn siphash ( key0 : u64 , key1 : u64 ) -> streaming {
91
+ type sipstate = {
92
+ k0 : u64 ,
93
+ k1 : u64 ,
94
+ mut length : uint , // how many bytes we've processed
95
+ mut v0 : u64 , // hash state
96
+ mut v1 : u64 ,
97
+ mut v2 : u64 ,
98
+ mut v3 : u64 ,
99
+ tail : ~[ mut u8] /8 , // unprocessed bytes
100
+ mut ntail : uint , // how many bytes in tail are valid
101
+ } ;
102
+
103
+ fn add_input ( st : sipstate , msg : ~[ u8 ] ) {
104
+ let length = vec:: len ( msg) ;
105
+ st. length += length;
106
+
107
+ let mut needed = 0 u;
108
+
109
+ if st. ntail != 0 {
110
+ needed = 8 - st. ntail ;
111
+
112
+ if length < needed {
113
+
114
+ let mut t = 0 ;
115
+ while t < length {
116
+ st. tail [ st. ntail +t] = msg[ t] ;
117
+ t += 1 ;
118
+ }
119
+ st. ntail += length;
120
+
121
+ ret;
122
+ }
123
+
124
+ let mut t = 0 ;
125
+ while t < needed {
126
+ st. tail [ st. ntail +t] = msg[ t] ;
127
+ t += 1 ;
128
+ }
129
+
130
+ let m = #u8to64_le ( st. tail , 0 ) ;
131
+
132
+ st. v3 ^= m;
133
+ #compress ( st. v0 , st. v1 , st. v2 , st. v3 ) ;
134
+ #compress ( st. v0 , st. v1 , st. v2 , st. v3 ) ;
135
+ st. v0 ^= m;
136
+
137
+ st. ntail = 0 ;
138
+ }
139
+
140
+ let len = length - needed;
141
+ let end = len & ( !0x7 ) ;
142
+ let left = len & 0x7 ;
143
+
144
+ let mut i = needed;
145
+ while i < end {
146
+ let mi = #u8to64_le ( msg, i) ;
147
+
148
+ st. v3 ^= mi;
149
+ #compress ( st. v0 , st. v1 , st. v2 , st. v3 ) ;
150
+ #compress ( st. v0 , st. v1 , st. v2 , st. v3 ) ;
151
+ st. v0 ^= mi;
152
+
153
+ i += 8 ;
154
+ }
155
+
156
+ let mut t = 0 u;
157
+ while t < left {
158
+ st. tail [ t] = msg[ i+t] ;
159
+ t += 1
160
+ }
161
+ st. ntail = left;
162
+ }
163
+
164
+ fn mk_result ( st : sipstate ) -> ~[ u8 ] {
165
+
166
+ let mut v0 = st. v0 ;
167
+ let mut v1 = st. v1 ;
168
+ let mut v2 = st. v2 ;
169
+ let mut v3 = st. v3 ;
170
+
171
+ let mut b : u64 = ( st. length as u64 & 0xff ) << 56 ;
172
+
173
+ if st. ntail > 0 { b |= st. tail [ 0 ] as u64 << 0 ; }
174
+ if st. ntail > 1 { b |= st. tail [ 1 ] as u64 << 8 ; }
175
+ if st. ntail > 2 { b |= st. tail [ 2 ] as u64 << 16 ; }
176
+ if st. ntail > 3 { b |= st. tail [ 3 ] as u64 << 24 ; }
177
+ if st. ntail > 4 { b |= st. tail [ 4 ] as u64 << 32 ; }
178
+ if st. ntail > 5 { b |= st. tail [ 5 ] as u64 << 40 ; }
179
+ if st. ntail > 6 { b |= st. tail [ 6 ] as u64 << 48 ; }
180
+
181
+ v3 ^= b;
182
+ #compress ( v0, v1, v2, v3) ;
183
+ #compress ( v0, v1, v2, v3) ;
184
+ v0 ^= b;
185
+
186
+ v2 ^= 0xff ;
187
+ #compress ( v0, v1, v2, v3) ;
188
+ #compress ( v0, v1, v2, v3) ;
189
+ #compress ( v0, v1, v2, v3) ;
190
+ #compress ( v0, v1, v2, v3) ;
191
+
192
+ let h = v0 ^ v1 ^ v2 ^ v3;
193
+
194
+ ret ~[
195
+ ( h >> 0 ) as u8 ,
196
+ ( h >> 8 ) as u8 ,
197
+ ( h >> 16 ) as u8 ,
198
+ ( h >> 24 ) as u8 ,
199
+ ( h >> 32 ) as u8 ,
200
+ ( h >> 40 ) as u8 ,
201
+ ( h >> 48 ) as u8 ,
202
+ ( h >> 56 ) as u8 ,
203
+ ] ;
204
+ }
205
+
206
+ impl of streaming for sipstate {
207
+ fn reset ( ) {
208
+ self . length = 0 ;
209
+ self . v0 = self . k0 ^ 0x736f6d6570736575 ;
210
+ self . v1 = self . k1 ^ 0x646f72616e646f6d ;
211
+ self . v2 = self . k0 ^ 0x6c7967656e657261 ;
212
+ self . v3 = self . k1 ^ 0x7465646279746573 ;
213
+ self . ntail = 0 ;
214
+ }
215
+ fn input ( msg : ~[ u8 ] ) { add_input ( self , msg) ; }
216
+ fn input_str ( msg : ~str ) { add_input ( self , str:: bytes ( msg) ) ; }
217
+ fn result ( ) -> ~[ u8 ] { ret mk_result ( self ) ; }
218
+ fn result_str ( ) -> ~str {
219
+ let r = mk_result ( self ) ;
220
+ let mut s = ~"";
221
+ for vec:: each( r) |b| { s += uint:: to_str ( b as uint , 16 u) ; }
222
+ ret s;
223
+ }
224
+ }
225
+
226
+ let st = {
227
+ k0 : key0,
228
+ k1 : key1,
229
+ mut length : 0 u,
230
+ mut v0 : 0u64 ,
231
+ mut v1 : 0u64 ,
232
+ mut v2 : 0u64 ,
233
+ mut v3 : 0u64 ,
234
+ tail : ~[ mut 0u8 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] /8 ,
235
+ mut ntail : 0 u,
236
+ } ;
237
+
238
+ let sh = st as streaming ;
239
+ sh. reset ( ) ;
240
+ ret sh;
241
+ }
242
+
80
243
#[ test]
81
244
fn test_siphash ( ) {
82
245
let vecs : [ [ u8 ] /8 ] /64 = [
@@ -150,14 +313,34 @@ fn test_siphash() {
150
313
let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08_u64 ;
151
314
let mut buf : ~[ u8 ] = ~[ ] ;
152
315
let mut t = 0 ;
316
+ let stream_inc = siphash ( k0, k1) ;
317
+ let stream_full = siphash ( k0, k1) ;
318
+
319
+ fn to_hex_str ( r : [ u8 ] /8 ) -> ~str {
320
+ let mut s = ~"";
321
+ for vec:: each( r) |b| { s += uint:: to_str ( b as uint , 16 u) ; }
322
+ ret s;
323
+ }
324
+
153
325
while t < 64 {
154
326
#debug ( "siphash test %?" , t) ;
155
327
let vec = #u8to64_le ( vecs[ t] , 0 ) ;
156
328
let out = hash_bytes_keyed ( buf, k0, k1) ;
157
329
#debug ( "got %?, expected %?" , out, vec) ;
158
330
assert vec == out;
331
+
332
+ stream_full. reset ( ) ;
333
+ stream_full. input ( buf) ;
334
+ let f = stream_full. result_str ( ) ;
335
+ let i = stream_inc. result_str ( ) ;
336
+ let v = to_hex_str ( vecs[ t] ) ;
337
+ #debug[ "%d: (%s) => inc=%s full=%s" , t, v, i, f] ;
338
+
339
+ assert f == i && f == v;
340
+
159
341
buf += ~[ t as u8 ] ;
342
+ stream_inc. input ( ~[ t as u8 ] ) ;
343
+
160
344
t += 1 ;
161
345
}
162
-
163
- }
346
+ }
0 commit comments