1 /* This is SipHash by Jean-Philippe Aumasson and Daniel J. Bernstein.
2 * The authors claim it is relatively secure compared to the alternatives
3 * and that performance wise it is a suitable hash for languages like Perl.
6 * https://www.131002.net/siphash/
8 * This implementation seems to perform slightly slower than one-at-a-time for
9 * short keys, but degrades slower for longer keys. Murmur Hash outperforms it
10 * regardless of keys size.
19 v0 += v1; v1=ROTL64(v1,13); v1 ^= v0; v0=ROTL64(v0,32); \
20 v2 += v3; v3=ROTL64(v3,16); v3 ^= v2; \
21 v0 += v3; v3=ROTL64(v3,21); v3 ^= v0; \
22 v2 += v1; v1=ROTL64(v1,17); v1 ^= v2; v2=ROTL64(v2,32); \
25 #define SIPHASH_SEED_STATE(key,v0,v1,v2,v3) \
27 v0 = v2 = U8TO64_LE(key + 0); \
28 v1 = v3 = U8TO64_LE(key + 8); \
29 /* "somepseudorandomlygeneratedbytes" */ \
30 v0 ^= UINT64_C(0x736f6d6570736575); \
31 v1 ^= UINT64_C(0x646f72616e646f6d); \
32 v2 ^= UINT64_C(0x6c7967656e657261); \
33 v3 ^= UINT64_C(0x7465646279746573); \
37 void S_perl_siphash_seed_state(const unsigned char * const seed_buf, unsigned char * state_buf) {
38 U64 *v= (U64*) state_buf;
39 SIPHASH_SEED_STATE(seed_buf, v[0],v[1],v[2],v[3]);
42 #define PERL_SIPHASH_FNC(FNC,SIP_ROUNDS,SIP_FINAL_ROUNDS) \
43 PERL_STATIC_INLINE U64 \
44 FNC ## _with_state_64 \
45 (const unsigned char * const state, const unsigned char *in, const STRLEN inlen) \
47 const int left = inlen & 7; \
48 const U8 *end = in + inlen - left; \
50 U64 b = ( ( U64 )(inlen) ) << 56; \
52 U64 v0 = U8TO64_LE(state); \
53 U64 v1 = U8TO64_LE(state+8); \
54 U64 v2 = U8TO64_LE(state+16); \
55 U64 v3 = U8TO64_LE(state+24); \
57 for ( ; in != end; in += 8 ) \
59 m = U8TO64_LE( in ); \
69 case 7: b |= ( ( U64 )in[ 6] ) << 48; /*FALLTHROUGH*/ \
70 case 6: b |= ( ( U64 )in[ 5] ) << 40; /*FALLTHROUGH*/ \
71 case 5: b |= ( ( U64 )in[ 4] ) << 32; /*FALLTHROUGH*/ \
72 case 4: b |= ( ( U64 )in[ 3] ) << 24; /*FALLTHROUGH*/ \
73 case 3: b |= ( ( U64 )in[ 2] ) << 16; /*FALLTHROUGH*/ \
74 case 2: b |= ( ( U64 )in[ 1] ) << 8; /*FALLTHROUGH*/ \
75 case 1: b |= ( ( U64 )in[ 0] ); break; \
89 b = v0 ^ v1 ^ v2 ^ v3; \
93 PERL_STATIC_INLINE U32 \
95 (const unsigned char * const state, const unsigned char *in, const STRLEN inlen) \
101 h.h64= FNC ## _with_state_64(state,in,inlen); \
102 return h.h32[0] ^ h.h32[1]; \
106 PERL_STATIC_INLINE U32 \
107 FNC (const unsigned char * const seed, const unsigned char *in, const STRLEN inlen) \
110 SIPHASH_SEED_STATE(seed,state[0],state[1],state[2],state[3]); \
111 return FNC ## _with_state((U8*)state,in,inlen); \
116 S_perl_hash_siphash_1_3
118 ,SIPROUND;SIPROUND;SIPROUND;
122 S_perl_hash_siphash_2_4
124 ,SIPROUND;SIPROUND;SIPROUND;SIPROUND;
127 #endif /* defined(CAN64BITHASH) */