From ff74d0d7ad4b311f473c1c50ae6d854294de3feb Mon Sep 17 00:00:00 2001 From: Lenny McLennington Date: Sat, 9 Dec 2023 14:15:51 +0000 Subject: [PATCH] Create offline mode accounts with consistent Uuids Uses basically what already exists in Qt, just modified so I can specify an arbitrary length byte array for the namespace. Not really sure if it needs to be the same as the way Minecraft generates it or if I could've just used Uuid::createUuidV3. It would've still been consistent either way, but whatever, this works. Signed-off-by: Lenny McLennington --- launcher/minecraft/auth/MinecraftAccount.cpp | 32 +++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/launcher/minecraft/auth/MinecraftAccount.cpp b/launcher/minecraft/auth/MinecraftAccount.cpp index 700c3c0f..36e2671a 100644 --- a/launcher/minecraft/auth/MinecraftAccount.cpp +++ b/launcher/minecraft/auth/MinecraftAccount.cpp @@ -54,6 +54,36 @@ #include "flows/Offline.h" #include "minecraft/auth/AccountData.h" +// Basically the same as https://github.com/qt/qtbase/blob/5.12/src/corelib/plugin/quuid.cpp#L152C1-L173C2, but unfortunately they don't allow +// us to specify a byte array for the namespace, we only get to specify a fixed length Uuid so I have to copy it and modify it ever so slightly. +static QUuid createUuidFromName(const QByteArray &ns, const QByteArray &baseData, QCryptographicHash::Algorithm algorithm, int version) +{ + QByteArray hashResult; + + // create a scope so later resize won't reallocate + { + QCryptographicHash hash(algorithm); + hash.addData(ns); + hash.addData(baseData); + hashResult = hash.result(); + } + hashResult.resize(16); // Sha1 will be too long + + QUuid result = QUuid::fromRfc4122(hashResult); + + result.data3 &= 0x0FFF; + result.data3 |= (version << 12); + result.data4[0] &= 0x3F; + result.data4[0] |= 0x80; + + return result; +} + +static QUuid createUuidV3(const QByteArray &ns, const QByteArray &baseData) +{ + return createUuidFromName(ns, baseData, QCryptographicHash::Md5, 3); +} + MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent) { data.internalId = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]")); } @@ -112,7 +142,7 @@ MinecraftAccountPtr MinecraftAccount::createOffline(const QString &username) account->data.yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]")); account->data.minecraftEntitlement.ownsMinecraft = true; account->data.minecraftEntitlement.canPlayMinecraft = true; - account->data.minecraftProfile.id = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]")); + account->data.minecraftProfile.id = createUuidV3("OfflinePlayer:", username.toUtf8()).toString().remove(QRegularExpression("[{}-]")); account->data.minecraftProfile.name = username; account->data.minecraftProfile.validity = Katabasis::Validity::Certain; return account;