Skip to content

Instantly share code, notes, and snippets.

@0x1F9F1
Created July 29, 2023 17:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0x1F9F1/a22774f0d77584787d91101de5aba57e to your computer and use it in GitHub Desktop.
Save 0x1F9F1/a22774f0d77584787d91101de5aba57e to your computer and use it in GitHub Desktop.
#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