129 lines
3.7 KiB
C
129 lines
3.7 KiB
C
|
/*
|
||
|
* 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);
|
||
|
}
|