Created
July 29, 2023 17:53
-
-
Save 0x1F9F1/a22774f0d77584787d91101de5aba57e to your computer and use it in GitHub Desktop.
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
#include <stdint.h> | |
#include <stddef.h> | |
#include <stdio.h> | |
#include <string.h> | |
uint32_t joaat_loop(const uint8_t* key, size_t length, uint32_t hash) | |
{ | |
size_t i = 0; | |
while (i != length) { | |
hash += key[i++]; | |
hash += hash << 10; | |
hash ^= hash >> 6; | |
} | |
return hash; | |
} | |
uint32_t joaat_final(uint32_t hash) | |
{ | |
hash += hash << 3; | |
hash ^= hash >> 11; | |
hash += hash << 15; | |
return hash; | |
} | |
uint32_t joaat(const uint8_t* key, size_t length, uint32_t hash) | |
{ | |
return joaat_final(joaat_loop(key, length, hash)); | |
} | |
uint32_t inv_joaat_loop(const uint8_t* key, size_t length, uint32_t hash) | |
{ | |
size_t i = length; | |
while (i != 0) { | |
// invert hash ^= hash >> 6; | |
hash ^= (hash >> 6) ^ (hash >> 12) ^ (hash >> 18) ^ (hash >> 24) ^ (hash >> 30); | |
// invert hash += hash << 10; | |
hash *= 0xC00FFC01; | |
// invert hash += key[i++]; | |
hash -= key[--i]; | |
} | |
return hash; | |
} | |
uint32_t inv_joaat_final(uint32_t hash) | |
{ | |
// invert hash += hash << 15; | |
hash *= 0x3FFF8001; | |
// invert hash ^= hash >> 11; | |
hash ^= (hash >> 11) ^ (hash >> 22); | |
// invert hash += hash << 3; | |
hash *= 0x38E38E39; | |
return hash; | |
} | |
uint32_t inv_joaat(const uint8_t* key, size_t length, uint32_t hash) | |
{ | |
return inv_joaat_loop(key, length, inv_joaat_final(hash)); | |
} | |
int main() | |
{ | |
const char* key = "bazspamalpha6"; | |
size_t length = strlen(key); | |
uint32_t seed = 0x00000000; | |
// 0xC660C82F | |
uint32_t target_hash = joaat(key, length, seed); | |
printf("Hash: 0x%08X\n", target_hash); | |
// 0x00000000 | |
seed = inv_joaat(key, length, target_hash); | |
printf("Seed: 0x%08X\n", seed); | |
// 0x03CFAAD7 | |
target_hash = inv_joaat_final(target_hash); | |
printf("Hash: 0x%08X\n", target_hash); | |
const char* parts_0[3] = { "foo", "bar", "baz" }; | |
uint32_t hashes_0[3]; | |
printf("Part 0\n"); | |
for (size_t i = 0; i < 3; ++i) { | |
const char* part = parts_0[i]; | |
uint32_t hash = joaat_loop(part, strlen(part), seed); | |
printf("0x%08X\n", hash); | |
hashes_0[i] = hash; | |
} | |
const char* parts_1[3] = { "spam", "ham", "eggs" }; | |
uint32_t hashes_1[3 * 3]; | |
printf("Part 1\n"); | |
for (size_t i = 0; i < 3; ++i) { | |
const char* part = parts_1[i]; | |
for (size_t j = 0; j < 3; ++j) { | |
uint32_t hash = joaat_loop(part, strlen(part), hashes_0[j]); | |
printf("0x%08X\n", hash); | |
hashes_1[i * 3 + j] = hash; | |
} | |
} | |
printf("Part 3\n"); | |
const char* parts_3[10] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; | |
uint32_t hashes_3[10]; | |
for (size_t i = 0; i < 10; ++i) { | |
const char* part = parts_3[i]; | |
uint32_t hash = inv_joaat_loop(part, strlen(part), target_hash); | |
printf("0x%08X\n", hash); | |
hashes_3[i] = hash; | |
} | |
const char* parts_2[3] = { "alpha", "beta", "gamma" }; | |
uint32_t hashes_2[3 * 10]; | |
printf("Part 2\n"); | |
for (size_t i = 0; i < 3; ++i) { | |
const char* part = parts_2[i]; | |
for (size_t j = 0; j < 10; ++j) { | |
uint32_t hash = inv_joaat_loop(part, strlen(part), hashes_3[j]); | |
printf("0x%08X\n", hash); | |
hashes_2[i * 10 + j] = hash; | |
} | |
} | |
printf("Checking Matches\n"); | |
for (size_t i = 0; i < 9; ++i) { | |
uint32_t hash_1 = hashes_1[i]; | |
for (size_t j = 0; j < 30; ++j) { | |
uint32_t hash_2 = hashes_2[j]; | |
if (hash_1 == hash_2) { | |
printf("Match! %zu/%zu = 0x%08X\n", i, j, hash_1); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment