Created
October 8, 2021 05:45
-
-
Save methane/5bb59a0563a025994e49fac509b49bf9 to your computer and use it in GitHub Desktop.
create known hashes for siphash13
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// create known hash in test_hash | |
#include <cstdint> | |
#include <iostream> | |
#include <stdio.h> | |
#include <stddef.h> | |
#include <string.h> | |
// copied from initconfig.c | |
typedef union { | |
/* ensure 24 bytes */ | |
unsigned char uc[24]; | |
/* two uint64 for SipHash24 */ | |
struct { | |
uint64_t k0; | |
uint64_t k1; | |
} siphash; | |
} hashseed_t; | |
static void | |
lcg_urandom(unsigned int x0, unsigned char *buffer, size_t size) | |
{ | |
size_t index; | |
unsigned int x; | |
x = x0; | |
for (index=0; index < size; index++) { | |
x *= 214013; | |
x += 2531011; | |
/* modulo 2 ^ (8 * sizeof(int)) */ | |
buffer[index] = (x >> 16) & 0xff; | |
} | |
} | |
// copied from https://tociyuki.hatenablog.jp/entry/20170310/1489133310 | |
uint64_t siphash13 (uint8_t const key[16], uint8_t const *s, std::size_t const len); | |
static inline void | |
sipround (uint64_t& v0, uint64_t& v1, uint64_t& v2, uint64_t& v3) | |
{ | |
v0 += v1; | |
v1 = (v1 << 13) | (v1 >> 51); | |
v1 ^= v0; | |
v0 = (v0 << 32) | (v0 >> 32); | |
v2 += v3; | |
v3 = (v3 << 16) | (v3 >> 48); | |
v3 ^= v2; | |
v0 += v3; | |
v3 = (v3 << 21) | (v3 >> 43); | |
v3 ^= v0; | |
v2 += v1; | |
v1 = (v1 << 17) | (v1 >> 47); | |
v1 ^= v2; | |
v2 = (v2 << 32) | (v2 >> 32); | |
} | |
static inline uint64_t | |
u8to64_le(uint8_t const *s) | |
{ | |
return (uint64_t)(s[0]) | ((uint64_t)(s[1]) << 8) | |
| ((uint64_t)(s[2]) << 16) | ((uint64_t)(s[3]) << 24) | |
| ((uint64_t)(s[4]) << 32) | ((uint64_t)(s[5]) << 40) | |
| ((uint64_t)(s[6]) << 48) | ((uint64_t)(s[7]) << 56); | |
} | |
uint64_t | |
siphash13 (uint64_t k0, uint64_t k1, uint8_t const *s, std::size_t const len) | |
{ | |
uint64_t m; | |
uint64_t v0 = UINT64_C(0x736f6d6570736575); | |
uint64_t v1 = UINT64_C(0x646f72616e646f6d); | |
uint64_t v2 = UINT64_C(0x6c7967656e657261); | |
uint64_t v3 = UINT64_C(0x7465646279746573); | |
v3 ^= k1; | |
v2 ^= k0; | |
v1 ^= k1; | |
v0 ^= k0; | |
std::size_t n = len; | |
for (; n >= 8; s += 8, n -= 8) { | |
m = u8to64_le (s); | |
v3 ^= m; | |
sipround (v0, v1, v2, v3); | |
#ifdef SIPHASH24 | |
sipround (v0, v1, v2, v3); | |
#endif | |
v0 ^= m; | |
} | |
uint64_t b = ((uint64_t) len) << 56; | |
switch (n) { | |
case 7: b ^= ((uint64_t)s[6]) << 48; | |
case 6: b ^= ((uint64_t)s[5]) << 40; | |
case 5: b ^= ((uint64_t)s[4]) << 32; | |
case 4: b ^= ((uint64_t)s[3]) << 24; | |
case 3: b ^= ((uint64_t)s[2]) << 16; | |
case 2: b ^= ((uint64_t)s[1]) << 8; | |
case 1: b ^= ((uint64_t)s[0]); | |
} | |
v3 ^= b; | |
sipround (v0, v1, v2, v3); | |
#ifdef SIPHASH24 | |
sipround (v0, v1, v2, v3); | |
#endif | |
v0 ^= b; | |
v2 ^= UINT64_C(0xff); | |
sipround (v0, v1, v2, v3); | |
sipround (v0, v1, v2, v3); | |
sipround (v0, v1, v2, v3); | |
#ifdef SIPHASH24 | |
sipround (v0, v1, v2, v3); | |
#endif | |
b = v0 ^ v1 ^ v2 ^ v3; | |
return b; | |
} | |
// end | |
void report(int seed, uint64_t k0, uint64_t k1, const char *name, const char *little, const char *big, size_t len) | |
{ | |
uint64_t hl = siphash13(k0, k1, (const uint8_t*)little, len); | |
uint64_t hb = siphash13(k0, k1, (const uint8_t*)big, len); | |
printf("# seed %d, '%s'\n", seed, name); | |
printf("[%d, %ld, %d, %ld],\n", (int32_t)hl, (int64_t)hl, (int32_t)hb, (int64_t)hb); | |
} | |
int main() | |
{ | |
uint64_t h; | |
int seed; | |
const char *s; | |
size_t len; | |
const char *s1 = "abc"; | |
const char *s2 = "abcdefghijk"; | |
const char *name = "äú∑ℇ"; | |
const char *s3 = "\xe4\x00\xfa\x00\x11\"\x07!"; | |
const char *s4 = "\x00\xe4\x00\xfa\"\x11!\x07"; | |
// PYTHONHASHSEED=42 | |
hashseed_t seed42; | |
lcg_urandom(42, seed42.uc, 16); | |
uint64_t k0 = seed42.siphash.k0; | |
uint64_t k1 = seed42.siphash.k1; | |
report(0, 0, 0, s1, s1, s1, 3); | |
report(42, k0, k1, s1, s1, s1, 3); | |
report(42, k0, k1, s2, s2, s2, strlen(s2)); | |
report(0, 0, 0, name, s3, s4, 8); | |
report(42, k0, k1, name, s3, s4, 8); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment