9
|
1 |
<?php |
|
2 |
|
|
3 |
if (class_exists('ParagonIE_Sodium_Core32_SipHash', false)) { |
|
4 |
return; |
|
5 |
} |
|
6 |
|
|
7 |
/** |
|
8 |
* Class ParagonIE_SodiumCompat_Core32_SipHash |
|
9 |
* |
|
10 |
* Only uses 32-bit arithmetic, while the original SipHash used 64-bit integers |
|
11 |
*/ |
|
12 |
class ParagonIE_Sodium_Core32_SipHash extends ParagonIE_Sodium_Core32_Util |
|
13 |
{ |
|
14 |
/** |
|
15 |
* @internal You should not use this directly from another application |
|
16 |
* |
|
17 |
* @param array<int, ParagonIE_Sodium_Core32_Int64> $v |
|
18 |
* @return array<int, ParagonIE_Sodium_Core32_Int64> |
|
19 |
*/ |
|
20 |
public static function sipRound(array $v) |
|
21 |
{ |
|
22 |
# v0 += v1; |
|
23 |
$v[0] = $v[0]->addInt64($v[1]); |
|
24 |
|
|
25 |
# v1 = ROTL(v1, 13); |
|
26 |
$v[1] = $v[1]->rotateLeft(13); |
|
27 |
|
|
28 |
# v1 ^= v0; |
|
29 |
$v[1] = $v[1]->xorInt64($v[0]); |
|
30 |
|
|
31 |
# v0=ROTL(v0,32); |
|
32 |
$v[0] = $v[0]->rotateLeft(32); |
|
33 |
|
|
34 |
# v2 += v3; |
|
35 |
$v[2] = $v[2]->addInt64($v[3]); |
|
36 |
|
|
37 |
# v3=ROTL(v3,16); |
|
38 |
$v[3] = $v[3]->rotateLeft(16); |
|
39 |
|
|
40 |
# v3 ^= v2; |
|
41 |
$v[3] = $v[3]->xorInt64($v[2]); |
|
42 |
|
|
43 |
# v0 += v3; |
|
44 |
$v[0] = $v[0]->addInt64($v[3]); |
|
45 |
|
|
46 |
# v3=ROTL(v3,21); |
|
47 |
$v[3] = $v[3]->rotateLeft(21); |
|
48 |
|
|
49 |
# v3 ^= v0; |
|
50 |
$v[3] = $v[3]->xorInt64($v[0]); |
|
51 |
|
|
52 |
# v2 += v1; |
|
53 |
$v[2] = $v[2]->addInt64($v[1]); |
|
54 |
|
|
55 |
# v1=ROTL(v1,17); |
|
56 |
$v[1] = $v[1]->rotateLeft(17); |
|
57 |
|
|
58 |
# v1 ^= v2; |
|
59 |
$v[1] = $v[1]->xorInt64($v[2]); |
|
60 |
|
|
61 |
# v2=ROTL(v2,32) |
|
62 |
$v[2] = $v[2]->rotateLeft(32); |
|
63 |
|
|
64 |
return $v; |
|
65 |
} |
|
66 |
|
|
67 |
/** |
|
68 |
* @internal You should not use this directly from another application |
|
69 |
* |
|
70 |
* @param string $in |
|
71 |
* @param string $key |
|
72 |
* @return string |
|
73 |
* @throws SodiumException |
|
74 |
* @throws TypeError |
|
75 |
*/ |
|
76 |
public static function sipHash24($in, $key) |
|
77 |
{ |
|
78 |
$inlen = self::strlen($in); |
|
79 |
|
|
80 |
# /* "somepseudorandomlygeneratedbytes" */ |
|
81 |
# u64 v0 = 0x736f6d6570736575ULL; |
|
82 |
# u64 v1 = 0x646f72616e646f6dULL; |
|
83 |
# u64 v2 = 0x6c7967656e657261ULL; |
|
84 |
# u64 v3 = 0x7465646279746573ULL; |
|
85 |
$v = array( |
|
86 |
new ParagonIE_Sodium_Core32_Int64( |
|
87 |
array(0x736f, 0x6d65, 0x7073, 0x6575) |
|
88 |
), |
|
89 |
new ParagonIE_Sodium_Core32_Int64( |
|
90 |
array(0x646f, 0x7261, 0x6e64, 0x6f6d) |
|
91 |
), |
|
92 |
new ParagonIE_Sodium_Core32_Int64( |
|
93 |
array(0x6c79, 0x6765, 0x6e65, 0x7261) |
|
94 |
), |
|
95 |
new ParagonIE_Sodium_Core32_Int64( |
|
96 |
array(0x7465, 0x6462, 0x7974, 0x6573) |
|
97 |
) |
|
98 |
); |
|
99 |
|
|
100 |
# u64 k0 = LOAD64_LE( k ); |
|
101 |
# u64 k1 = LOAD64_LE( k + 8 ); |
|
102 |
$k = array( |
|
103 |
ParagonIE_Sodium_Core32_Int64::fromReverseString( |
|
104 |
self::substr($key, 0, 8) |
|
105 |
), |
|
106 |
ParagonIE_Sodium_Core32_Int64::fromReverseString( |
|
107 |
self::substr($key, 8, 8) |
|
108 |
) |
|
109 |
); |
|
110 |
|
|
111 |
# b = ( ( u64 )inlen ) << 56; |
|
112 |
$b = new ParagonIE_Sodium_Core32_Int64( |
|
113 |
array(($inlen << 8) & 0xffff, 0, 0, 0) |
|
114 |
); |
|
115 |
|
|
116 |
# v3 ^= k1; |
|
117 |
$v[3] = $v[3]->xorInt64($k[1]); |
|
118 |
# v2 ^= k0; |
|
119 |
$v[2] = $v[2]->xorInt64($k[0]); |
|
120 |
# v1 ^= k1; |
|
121 |
$v[1] = $v[1]->xorInt64($k[1]); |
|
122 |
# v0 ^= k0; |
|
123 |
$v[0] = $v[0]->xorInt64($k[0]); |
|
124 |
|
|
125 |
$left = $inlen; |
|
126 |
# for ( ; in != end; in += 8 ) |
|
127 |
while ($left >= 8) { |
|
128 |
# m = LOAD64_LE( in ); |
|
129 |
$m = ParagonIE_Sodium_Core32_Int64::fromReverseString( |
|
130 |
self::substr($in, 0, 8) |
|
131 |
); |
|
132 |
|
|
133 |
# v3 ^= m; |
|
134 |
$v[3] = $v[3]->xorInt64($m); |
|
135 |
|
|
136 |
# SIPROUND; |
|
137 |
# SIPROUND; |
|
138 |
$v = self::sipRound($v); |
|
139 |
$v = self::sipRound($v); |
|
140 |
|
|
141 |
# v0 ^= m; |
|
142 |
$v[0] = $v[0]->xorInt64($m); |
|
143 |
|
|
144 |
$in = self::substr($in, 8); |
|
145 |
$left -= 8; |
|
146 |
} |
|
147 |
|
|
148 |
# switch( left ) |
|
149 |
# { |
|
150 |
# case 7: b |= ( ( u64 )in[ 6] ) << 48; |
|
151 |
# case 6: b |= ( ( u64 )in[ 5] ) << 40; |
|
152 |
# case 5: b |= ( ( u64 )in[ 4] ) << 32; |
|
153 |
# case 4: b |= ( ( u64 )in[ 3] ) << 24; |
|
154 |
# case 3: b |= ( ( u64 )in[ 2] ) << 16; |
|
155 |
# case 2: b |= ( ( u64 )in[ 1] ) << 8; |
|
156 |
# case 1: b |= ( ( u64 )in[ 0] ); break; |
|
157 |
# case 0: break; |
|
158 |
# } |
|
159 |
switch ($left) { |
|
160 |
case 7: |
|
161 |
$b = $b->orInt64( |
|
162 |
ParagonIE_Sodium_Core32_Int64::fromInts( |
|
163 |
0, self::chrToInt($in[6]) << 16 |
|
164 |
) |
|
165 |
); |
|
166 |
case 6: |
|
167 |
$b = $b->orInt64( |
|
168 |
ParagonIE_Sodium_Core32_Int64::fromInts( |
|
169 |
0, self::chrToInt($in[5]) << 8 |
|
170 |
) |
|
171 |
); |
|
172 |
case 5: |
|
173 |
$b = $b->orInt64( |
|
174 |
ParagonIE_Sodium_Core32_Int64::fromInts( |
|
175 |
0, self::chrToInt($in[4]) |
|
176 |
) |
|
177 |
); |
|
178 |
case 4: |
|
179 |
$b = $b->orInt64( |
|
180 |
ParagonIE_Sodium_Core32_Int64::fromInts( |
|
181 |
self::chrToInt($in[3]) << 24, 0 |
|
182 |
) |
|
183 |
); |
|
184 |
case 3: |
|
185 |
$b = $b->orInt64( |
|
186 |
ParagonIE_Sodium_Core32_Int64::fromInts( |
|
187 |
self::chrToInt($in[2]) << 16, 0 |
|
188 |
) |
|
189 |
); |
|
190 |
case 2: |
|
191 |
$b = $b->orInt64( |
|
192 |
ParagonIE_Sodium_Core32_Int64::fromInts( |
|
193 |
self::chrToInt($in[1]) << 8, 0 |
|
194 |
) |
|
195 |
); |
|
196 |
case 1: |
|
197 |
$b = $b->orInt64( |
|
198 |
ParagonIE_Sodium_Core32_Int64::fromInts( |
|
199 |
self::chrToInt($in[0]), 0 |
|
200 |
) |
|
201 |
); |
|
202 |
case 0: |
|
203 |
break; |
|
204 |
} |
|
205 |
|
|
206 |
# v3 ^= b; |
|
207 |
$v[3] = $v[3]->xorInt64($b); |
|
208 |
|
|
209 |
# SIPROUND; |
|
210 |
# SIPROUND; |
|
211 |
$v = self::sipRound($v); |
|
212 |
$v = self::sipRound($v); |
|
213 |
|
|
214 |
# v0 ^= b; |
|
215 |
$v[0] = $v[0]->xorInt64($b); |
|
216 |
|
|
217 |
// Flip the lower 8 bits of v2 which is ($v[4], $v[5]) in our implementation |
|
218 |
# v2 ^= 0xff; |
|
219 |
$v[2]->limbs[3] ^= 0xff; |
|
220 |
|
|
221 |
# SIPROUND; |
|
222 |
# SIPROUND; |
|
223 |
# SIPROUND; |
|
224 |
# SIPROUND; |
|
225 |
$v = self::sipRound($v); |
|
226 |
$v = self::sipRound($v); |
|
227 |
$v = self::sipRound($v); |
|
228 |
$v = self::sipRound($v); |
|
229 |
|
|
230 |
# b = v0 ^ v1 ^ v2 ^ v3; |
|
231 |
# STORE64_LE( out, b ); |
|
232 |
return $v[0] |
|
233 |
->xorInt64($v[1]) |
|
234 |
->xorInt64($v[2]) |
|
235 |
->xorInt64($v[3]) |
|
236 |
->toReverseString(); |
|
237 |
} |
|
238 |
} |