/* * This code is part of the strategy game operational-space. * operational-space comes with ABSOLUTELY NO WARRANTY and is licensed under GPL-2.0. * Copyright (C) 2024 VegOwOtenks, Sleppo04 * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "siphash.h" struct SipHashConfig SipHash_DefaultConfig(void) { struct SipHashConfig config = { .key = {0, 0}, .c = 2, .d = 4, }; return config; } #ifndef ROTATE64 #define ROTATE64(b, n) ((b) << n | (b) >> (64 - n)) #endif void _siphash_initialize(bit128_t* key, uint64_t* words) { words[0] = key->first ^ 0x736f6d6570736575; words[1] = key->second ^ 0x646f72616e646f6d; words[2] = key->first ^ 0x6c7967656e657261; words[3] = key->second ^ 0x7465646279746573; /* I don't like it either, just look at https://cr.yp.to/siphash/siphash-20120727.pdf */ } void _siphash_round(uint64_t* words) { words[0] += words[1]; words[2] += words[3]; words[1] = ROTATE64(words[1], 13); words[3] = ROTATE64(words[3], 16); words[1] ^= words[0]; words[3] ^= words[2]; words[0] = ROTATE64(words[0], 32); words[2] += words[1]; words[0] += words[3]; words[1] = ROTATE64(words[1], 17); words[3] = ROTATE64(words[3], 21); words[1] ^= words[2]; words[3] ^= words[0]; words[2] = ROTATE64(words[2], 32); } uint64_t _siphash_finalize(uint64_t* words, int d) { uint64_t hashValue; words[2] ^= 0xff; while (d) { _siphash_round(words); d--; } // Das muss so. Echt jetzt. hashValue = words[0] ^ words[1] ^ words[2] ^ words[3]; return hashValue; } void _perform_rounds(int times, uint64_t* words) { for (int k = 0; k < times; k++) { // Perform round on this word _siphash_round(words); } } void _siphash_compress(int c, const char* value, unsigned int valueLength, uint64_t* words) { // c is a parameter for the amount of siphash_rounds to be done uint64_t* byteString = (uint64_t*) value; int wordcount = (valueLength + 1 ) / 8; uint64_t lastWord = 0; uint64_t current; for (int i = 0; i < wordcount - 1; i++) { // Minus one because the last word is somewhat special current = *byteString; words[3] ^= current; _perform_rounds(c, words); // Append last special byte words[0] ^= current; byteString += 1; // Move pointer to next 64 bits } // FF 00 AB CF 00 00 00 (valueLength % 256) int remainingBytes = valueLength % 8; memcpy(&lastWord, byteString, remainingBytes); uint64_t compareValue = valueLength % 256; compareValue <<= 56; // WTF is this thing? Don't touch, it works!!elf1! lastWord |= compareValue; //(unsigned char) (valueLength % 256); words[3] ^= lastWord; _perform_rounds(c, words); words[0] ^= lastWord; } uint64_t siphash(int c, int d, const char* key, unsigned int keyLength, bit128_t* hashkey) { /* C and D are parameters of siphash */ uint64_t words[] = {0, 0, 0, 0}; _siphash_initialize(hashkey, words); _siphash_compress(c, key, keyLength, words); uint64_t hashValue = _siphash_finalize(words, d); return hashValue; } uint64_t siphash2(const char* key, unsigned int keyLength, struct SipHashConfig* config) { return siphash(config->c, config->d, key, keyLength, &config->key); }