2026-04-04 01:14:32 -04:00
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "UUID.h"
|
|
|
|
|
#include "Random.h"
|
|
|
|
|
#include <cstring>
|
2026-04-04 20:49:05 -04:00
|
|
|
#include <vector>
|
2026-04-04 02:17:59 -04:00
|
|
|
static void sha1_block(uint32_t h[5], const uint8_t block[64])
|
|
|
|
|
{
|
|
|
|
|
uint32_t w[80];
|
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
|
|
|
w[i] = (block[i * 4] << 24) | (block[i * 4 + 1] << 16) | (block[i * 4 + 2] << 8) | block[i * 4 + 3];
|
|
|
|
|
for (int i = 16; i < 80; i++) {
|
|
|
|
|
uint32_t x = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16];
|
|
|
|
|
w[i] = (x << 1) | (x >> 31);
|
|
|
|
|
}
|
|
|
|
|
uint32_t a = h[0], b = h[1], c = h[2], d = h[3], e = h[4];
|
|
|
|
|
for (int i = 0; i < 80; i++) {
|
|
|
|
|
uint32_t f, k;
|
|
|
|
|
if (i < 20) { f = (b & c) | (~b & d); k = 0x5A827999; }
|
|
|
|
|
else if (i < 40) { f = b ^ c ^ d; k = 0x6ED9EBA1; }
|
|
|
|
|
else if (i < 60) { f = (b & c) | (b & d) | (c & d); k = 0x8F1BBCDC; }
|
|
|
|
|
else { f = b ^ c ^ d; k = 0xCA62C1D6; }
|
|
|
|
|
uint32_t tmp = ((a << 5) | (a >> 27)) + f + e + k + w[i];
|
|
|
|
|
e = d; d = c; c = (b << 30) | (b >> 2); b = a; a = tmp;
|
|
|
|
|
}
|
|
|
|
|
h[0] += a; h[1] += b; h[2] += c; h[3] += d; h[4] += e;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-04 01:14:32 -04:00
|
|
|
static void sha1(const uint8_t* data, size_t len, uint8_t out[20])
|
|
|
|
|
{
|
|
|
|
|
uint32_t h[5] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 };
|
|
|
|
|
uint64_t bitLen = len * 8;
|
2026-04-04 02:17:59 -04:00
|
|
|
|
2026-04-04 01:14:32 -04:00
|
|
|
size_t fullBlocks = len / 64;
|
2026-04-04 02:17:59 -04:00
|
|
|
for (size_t blk = 0; blk < fullBlocks; blk++)
|
|
|
|
|
sha1_block(h, data + blk * 64);
|
|
|
|
|
|
2026-04-04 01:14:32 -04:00
|
|
|
uint8_t tail[128] = {};
|
|
|
|
|
size_t rem = len - fullBlocks * 64;
|
|
|
|
|
if (rem) memcpy(tail, data + fullBlocks * 64, rem);
|
|
|
|
|
tail[rem] = 0x80;
|
|
|
|
|
size_t tailLen = (rem < 56) ? 64 : 128;
|
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
|
|
|
tail[tailLen - 1 - i] = (uint8_t)(bitLen >> (i * 8));
|
|
|
|
|
|
2026-04-04 02:17:59 -04:00
|
|
|
for (size_t off = 0; off < tailLen; off += 64)
|
|
|
|
|
sha1_block(h, tail + off);
|
2026-04-04 01:14:32 -04:00
|
|
|
|
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
|
|
|
out[i * 4] = (uint8_t)(h[i] >> 24);
|
|
|
|
|
out[i * 4 + 1] = (uint8_t)(h[i] >> 16);
|
|
|
|
|
out[i * 4 + 2] = (uint8_t)(h[i] >> 8);
|
|
|
|
|
out[i * 4 + 3] = (uint8_t)(h[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
static constexpr char HEX[] = "0123456789abcdef";
|
|
|
|
|
static constexpr uint8_t hexVal(char c)
|
|
|
|
|
{
|
|
|
|
|
if (c >= '0' && c <= '9') return c - '0';
|
|
|
|
|
if (c >= 'a' && c <= 'f') return 10 + c - 'a';
|
|
|
|
|
if (c >= 'A' && c <= 'F') return 10 + c - 'A';
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GameUUID::toBytes(uint8_t out[16]) const
|
|
|
|
|
{
|
|
|
|
|
for (int i = 7; i >= 0; i--) out[7 - i] = (uint8_t)(msb >> (i * 8));
|
|
|
|
|
for (int i = 7; i >= 0; i--) out[15 - i] = (uint8_t)(lsb >> (i * 8));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GameUUID GameUUID::fromBytes(const uint8_t b[16])
|
|
|
|
|
{
|
|
|
|
|
GameUUID u;
|
|
|
|
|
for (int i = 0; i < 8; i++) u.msb = (u.msb << 8) | b[i];
|
|
|
|
|
for (int i = 0; i < 8; i++) u.lsb = (u.lsb << 8) | b[8 + i];
|
|
|
|
|
return u;
|
|
|
|
|
}
|
|
|
|
|
std::string GameUUID::toString() const
|
|
|
|
|
{
|
|
|
|
|
uint8_t b[16];
|
|
|
|
|
toBytes(b);
|
|
|
|
|
char buf[37];
|
|
|
|
|
int p = 0;
|
|
|
|
|
for (int i = 0; i < 16; i++) {
|
|
|
|
|
if (i == 4 || i == 6 || i == 8 || i == 10) buf[p++] = '-';
|
|
|
|
|
buf[p++] = HEX[b[i] >> 4];
|
|
|
|
|
buf[p++] = HEX[b[i] & 0xf];
|
|
|
|
|
}
|
|
|
|
|
buf[p] = '\0';
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::wstring GameUUID::toWString() const
|
|
|
|
|
{
|
|
|
|
|
std::string s = toString();
|
|
|
|
|
return { s.begin(), s.end() };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GameUUID GameUUID::fromString(const std::string& s)
|
|
|
|
|
{
|
|
|
|
|
uint8_t b[16] = {};
|
|
|
|
|
int bi = 0;
|
|
|
|
|
for (size_t i = 0; i < s.size() && bi < 16; i++) {
|
|
|
|
|
if (s[i] == '-') continue;
|
|
|
|
|
if (i + 1 >= s.size()) break;
|
|
|
|
|
b[bi++] = (hexVal(s[i]) << 4) | hexVal(s[i + 1]);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
return fromBytes(b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GameUUID GameUUID::fromWString(const std::wstring& s)
|
|
|
|
|
{
|
|
|
|
|
return fromString({ s.begin(), s.end() });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GameUUID GameUUID::v4(uint64_t high, uint64_t low)
|
|
|
|
|
{
|
|
|
|
|
return { (high & ~0xF000ULL) | 0x4000ULL, (low & ~0xC000000000000000ULL) | 0x8000000000000000ULL };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GameUUID GameUUID::v5(const GameUUID& ns, const std::string& name)
|
|
|
|
|
{
|
2026-04-04 20:49:05 -04:00
|
|
|
std::vector<uint8_t> input(16 + name.size());
|
|
|
|
|
ns.toBytes(input.data());
|
|
|
|
|
memcpy(input.data() + 16, name.data(), name.size());
|
2026-04-04 01:14:32 -04:00
|
|
|
|
|
|
|
|
uint8_t hash[20];
|
2026-04-04 20:49:05 -04:00
|
|
|
sha1(input.data(), input.size(), hash);
|
2026-04-04 01:14:32 -04:00
|
|
|
GameUUID u = fromBytes(hash);
|
|
|
|
|
u.msb = (u.msb & ~0xF000ULL) | 0x5000ULL;
|
|
|
|
|
u.lsb = (u.lsb & ~0xC000000000000000ULL) | 0x8000000000000000ULL;
|
|
|
|
|
return u;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GameUUID GameUUID::fromXuid(uint64_t xuid)
|
|
|
|
|
{
|
|
|
|
|
return v5(MCCONSOLES_NAMESPACE_UUID, std::to_string(xuid));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GameUUID GameUUID::random()
|
|
|
|
|
{
|
|
|
|
|
Random r;
|
|
|
|
|
return v4(r.nextLong(), r.nextLong());
|
|
|
|
|
}
|