SipHash

#include <Windows.h>

SIZE_T StringLengthW(_In_ LPCWSTR String)
{
	LPCWSTR String2;

	for (String2 = String; *String2; ++String2);

	return (String2 - String);
}

UINT64 RotateToLeft64(UINT64 x, UINT64 Rotate)
{
	return (x << Rotate) | (x >> (64 - Rotate));
}

PVOID CopyMemoryEx(_Inout_ PVOID Destination, _In_ CONST PVOID Source, _In_ SIZE_T Length)
{
	PBYTE D = (PBYTE)Destination;
	PBYTE S = (PBYTE)Source;

	while (Length--)
		*D++ = *S++;

	return Destination;
}

VOID ImplSipRound(PUINT64 InternalState0, PUINT64 InternalState1, PUINT64 InternalState2, PUINT64 InternalState3)
{
	*InternalState0 += *InternalState1;
	*InternalState1 = RotateToLeft64(*InternalState1, 13);
	*InternalState1 ^= *InternalState0;
	*InternalState0 = RotateToLeft64(*InternalState0, 32);

	*InternalState2 += *InternalState3;
	*InternalState3 = RotateToLeft64(*InternalState3, 16);
	*InternalState3 ^= *InternalState2;

	*InternalState0 += *InternalState3;
	*InternalState3 = RotateToLeft64(*InternalState3, 21);
	*InternalState3 ^= *InternalState0;

	*InternalState2 += *InternalState1;
	*InternalState1 = RotateToLeft64(*InternalState1, 17);
	*InternalState1 ^= *InternalState2;
	*InternalState2 = RotateToLeft64(*InternalState2, 32);
}

UINT64 HashStringSipHashW(PBYTE Key, PVOID String, SIZE_T Length)
{
	PBYTE Pointer = (PBYTE)String;
	PBYTE InputEnd = Pointer + (Length & ~(SIZE_T)7);

	UINT64 KeyBase = 0;
	UINT64 KeyBaseOffset = 0;
	UINT64 Block = 0;

	CopyMemoryEx(&KeyBase, Key, 8);
	CopyMemoryEx(&KeyBaseOffset, Key + 8, 8);

	UINT64 InternalState0 = 0x736f6d6570736575ULL ^ KeyBase;
	UINT64 InternalState1 = 0x646f72616e646f6dULL ^ KeyBaseOffset;
	UINT64 InternalState2 = 0x6c7967656e657261ULL ^ KeyBase;
	UINT64 InternalState3 = 0x7465646279746573ULL ^ KeyBaseOffset;

	for (; Pointer != InputEnd; Pointer += 8)
	{
		UINT64 MixObject = 0;

		CopyMemoryEx(&MixObject, Pointer, 8);

		InternalState3 ^= MixObject;
		ImplSipRound(&InternalState0, &InternalState1, &InternalState2, &InternalState3);
		ImplSipRound(&InternalState0, &InternalState1, &InternalState2, &InternalState3);
		InternalState0 ^= MixObject;
	}

	Block = (UINT64)Length << 56;
	switch (Length & 7) 
	{
		case 7: Block |= (UINT64)Pointer[6] << 48;
		case 6: Block |= (UINT64)Pointer[5] << 40;
		case 5: Block |= (UINT64)Pointer[4] << 32;
		case 4: Block |= (UINT64)Pointer[3] << 24;
		case 3: Block |= (UINT64)Pointer[2] << 16;
		case 2: Block |= (UINT64)Pointer[1] << 8;
		case 1: Block |= (UINT64)Pointer[0];
		default: break;
	}

	InternalState3 ^= Block;
	ImplSipRound(&InternalState0, &InternalState1, &InternalState2, &InternalState3);
	ImplSipRound(&InternalState0, &InternalState1, &InternalState2, &InternalState3);
	InternalState0 ^= Block;

	InternalState2 ^= 0xff;
	ImplSipRound(&InternalState0, &InternalState1, &InternalState2, &InternalState3);
	ImplSipRound(&InternalState0, &InternalState1, &InternalState2, &InternalState3);
	ImplSipRound(&InternalState0, &InternalState1, &InternalState2, &InternalState3);
	ImplSipRound(&InternalState0, &InternalState1, &InternalState2, &InternalState3);

	return (InternalState0 & InternalState1) ^ (InternalState2 ^ InternalState3);
}

INT main(VOID)
{
	WCHAR StringHashExample[] = L"Hash This String";
	BYTE Key[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
	UINT64 Hash = 0;

  Hash = HashStringSipHashW(Key, StringHashExample, (StringLengthW(StringHashExample) * sizeof(WCHAR)));

	return ERROR_SUCCESS;
}

Last updated