forked from shirok/Gauche
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdwsiphash.c
91 lines (84 loc) · 2.83 KB
/
dwsiphash.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/* Public domain 2013 Sam Trenholme */
#include "dwsiphash.h"
#include "gauche/priv/dws_adapter.h"
#if SIZEOF_LONG > 4
/* Core sipHash round function, as per spec */
void DwSip_round(DwSH_WORD *v0, DwSH_WORD *v1, DwSH_WORD *v2, DwSH_WORD *v3) {
*v0 += *v1;
*v2 += *v3;
*v1 = (*v1 << DwSH_R1) | (*v1 >> DwSH_R1i);
*v3 = (*v3 << DwSH_R2) | (*v3 >> DwSH_R2i);
*v1 ^= *v0;
*v3 ^= *v2;
*v0 = (*v0 << DwSH_R3) | (*v0 >> DwSH_R3i);
*v2 += *v1;
*v0 += *v3;
*v1 = (*v1 << DwSH_R4) | (*v1 >> DwSH_R4i);
*v3 = (*v3 << DwSH_R5) | (*v3 >> DwSH_R5i);
*v1 ^= *v2;
*v3 ^= *v0;
*v2 = (*v2 << DwSH_R6) | (*v2 >> DwSH_R6i);
}
/* Key setup. Given two keys, set up the first state and final XOR constant */
void DwSip_ksetup(DwSH_WORD *k0, DwSH_WORD *k1, DwSH_WORD *v0, DwSH_WORD *v1,
DwSH_WORD *v2, DwSH_WORD *v3, DwSH_WORD *fx) {
*v0 = *k0 ^ DwSH_kc1;
*v1 = *k1 ^ DwSH_kc2;
*v2 = *k0 ^ DwSH_kc3;
*v3 = *k1 ^ DwSH_kc4;
*fx = DwSH_fx;
}
/* Convert part of a word in to a message block SipHash can understand */
DwSH_WORD DwSip_getword(uint32_t *offset, uint8_t *str, uint32_t len) {
uint32_t toffset = *offset;
int shift = 0;
DwSH_WORD out = 0;
do {
if(toffset >= len) {
out |= ((DwSH_WORD)len & 0xff) << (DwSH_BWIDTH - 8);
*offset = len + 1;
return out;
}
out |= (DwSH_WORD)*(str + toffset) << shift;
shift += 8;
toffset++;
} while(toffset < *offset + DwSH_OWIDTH);
*offset = toffset;
return out;
}
/* Calculate the hash for a given string */
DwSH_WORD DwSip_hash(uint8_t *str, uint32_t len, DwSH_WORD k1, DwSH_WORD k2) {
uint32_t offset = 0;
int a = 0;
DwSH_WORD v0 = 0, v1 = 0, v2 = 0, v3 = 0, fx = 0, m = 0;
DwSip_ksetup(&k1, &k2, &v0, &v1, &v2, &v3, &fx);
while(offset <= len) {
m = DwSip_getword(&offset, str, len);
v3 ^= m;
for(a = 0; a < DwSH_CROUNDS; a++) {
DwSip_round(&v0,&v1,&v2,&v3);
}
v0 ^= m;
}
v2 ^= fx;
for(a = 0; a < DwSH_FROUNDS; a++) {
DwSip_round(&v0,&v1,&v2,&v3);
}
return v0 ^ v1 ^ v2 ^ v3;
}
#ifdef MAIN
#include <stdio.h>
int main() {
uint8_t str[64];
uint32_t len = 15;
DwSH_WORD o = 0;
for(len = 0; len < 64; len++) {
str[len] = len;
o = DwSip_hash(str, len, 0x0706050403020100ULL,
0x0f0e0d0c0b0a0908ULL);
printf("%016llx\n",o);
}
return 0;
}
#endif /* MAIN */
#endif /* SIZEOF_LONG > 4 */