2323
2424#include " tscore/Hash.h"
2525#include < cstdint>
26+ #include < cstring>
2627
2728/*
28- Siphash is a Hash Message Authentication Code and can take a key.
29+ SipHash is a Hash Message Authentication Code and can take a key.
2930
3031 If you don't care about MAC use the void constructor and it will use
3132 a zero key for you.
32- */
3333
34- struct ATSHash64Sip24 : ATSHash64 {
35- ATSHash64Sip24 ();
36- ATSHash64Sip24 (const unsigned char key[16 ]);
37- ATSHash64Sip24 (std::uint64_t key0, std::uint64_t key1);
38- void update (const void *data, std::size_t len) override ;
39- void final () override ;
40- std::uint64_t get () const override ;
41- void clear () override ;
34+ Template parameters:
35+ - c_rounds: number of compression rounds per message block
36+ - d_rounds: number of finalization rounds
37+ */
38+
39+ #define SIP_BLOCK_SIZE 8
40+
41+ #define ROTL64 (a, b ) (((a) << (b)) | ((a) >> (64 - b)))
42+
43+ #define U8TO64_LE (p ) *(const std::uint64_t *)(p)
44+
45+ #define SIPCOMPRESS (x0, x1, x2, x3 ) \
46+ x0 += x1; \
47+ x2 += x3; \
48+ x1 = ROTL64(x1, 13 ); \
49+ x3 = ROTL64(x3, 16 ); \
50+ x1 ^= x0; \
51+ x3 ^= x2; \
52+ x0 = ROTL64(x0, 32 ); \
53+ x2 += x1; \
54+ x0 += x3; \
55+ x1 = ROTL64(x1, 17 ); \
56+ x3 = ROTL64(x3, 21 ); \
57+ x1 ^= x2; \
58+ x3 ^= x0; \
59+ x2 = ROTL64(x2, 32 );
60+
61+ template <int c_rounds, int d_rounds> struct ATSHashSip : ATSHash64 {
62+ ATSHashSip () { this ->clear (); }
63+
64+ ATSHashSip (const unsigned char key[16 ]) : k0(U8TO64_LE(key)), k1(U8TO64_LE(key + sizeof (k0))) { this ->clear (); }
65+
66+ ATSHashSip (std::uint64_t key0, std::uint64_t key1) : k0(key0), k1(key1) { this ->clear (); }
67+
68+ void
69+ update (const void *data, std::size_t len) override
70+ {
71+ std::size_t i, blocks;
72+ unsigned char *m;
73+ std::uint64_t mi;
74+ std::uint8_t block_off = 0 ;
75+
76+ if (!finalized) {
77+ m = (unsigned char *)data;
78+ total_len += len;
79+
80+ if (len + block_buffer_len < SIP_BLOCK_SIZE) {
81+ std::memcpy (block_buffer + block_buffer_len, m, len);
82+ block_buffer_len += len;
83+ } else {
84+ if (block_buffer_len > 0 ) {
85+ block_off = SIP_BLOCK_SIZE - block_buffer_len;
86+ std::memcpy (block_buffer + block_buffer_len, m, block_off);
87+
88+ mi = U8TO64_LE (block_buffer);
89+ v3 ^= mi;
90+ for (int r = 0 ; r < c_rounds; r++) {
91+ SIPCOMPRESS (v0, v1, v2, v3);
92+ }
93+ v0 ^= mi;
94+ }
95+
96+ for (i = block_off, blocks = ((len - block_off) & ~(SIP_BLOCK_SIZE - 1 )); i < blocks; i += SIP_BLOCK_SIZE) {
97+ mi = U8TO64_LE (m + i);
98+ v3 ^= mi;
99+ for (int r = 0 ; r < c_rounds; r++) {
100+ SIPCOMPRESS (v0, v1, v2, v3);
101+ }
102+ v0 ^= mi;
103+ }
104+
105+ block_buffer_len = (len - block_off) & (SIP_BLOCK_SIZE - 1 );
106+ std::memcpy (block_buffer, m + block_off + blocks, block_buffer_len);
107+ }
108+ }
109+ }
110+
111+ void
112+ final () override
113+ {
114+ std::uint64_t last7;
115+ int i;
116+
117+ if (!finalized) {
118+ last7 = static_cast <std::uint64_t >(total_len & 0xff ) << 56 ;
119+
120+ for (i = block_buffer_len - 1 ; i >= 0 ; i--) {
121+ last7 |= static_cast <std::uint64_t >(block_buffer[i]) << (i * 8 );
122+ }
123+
124+ v3 ^= last7;
125+ for (int r = 0 ; r < c_rounds; r++) {
126+ SIPCOMPRESS (v0, v1, v2, v3);
127+ }
128+ v0 ^= last7;
129+ v2 ^= 0xff ;
130+ for (int r = 0 ; r < d_rounds; r++) {
131+ SIPCOMPRESS (v0, v1, v2, v3);
132+ }
133+ hfinal = v0 ^ v1 ^ v2 ^ v3;
134+ finalized = true ;
135+ }
136+ }
137+
138+ std::uint64_t
139+ get () const override
140+ {
141+ if (finalized) {
142+ return hfinal;
143+ } else {
144+ return 0 ;
145+ }
146+ }
147+
148+ void
149+ clear () override
150+ {
151+ v0 = k0 ^ 0x736f6d6570736575ull ;
152+ v1 = k1 ^ 0x646f72616e646f6dull ;
153+ v2 = k0 ^ 0x6c7967656e657261ull ;
154+ v3 = k1 ^ 0x7465646279746573ull ;
155+ finalized = false ;
156+ total_len = 0 ;
157+ block_buffer_len = 0 ;
158+ }
42159
43160private:
44161 unsigned char block_buffer[8 ] = {0 };
@@ -53,3 +170,7 @@ struct ATSHash64Sip24 : ATSHash64 {
53170 std::size_t total_len = 0 ;
54171 bool finalized = false ;
55172};
173+
174+ // Standard SipHash variants
175+ using ATSHash64Sip24 = ATSHashSip<2 , 4 >;
176+ using ATSHash64Sip13 = ATSHashSip<1 , 3 >;
0 commit comments