Elytra-Server / Elytra

A Cleanroom minecraft server API in kotlin
MIT License
51 stars 6 forks source link

Bidirectional UUID mapping for cracked accounts #46

Open WinX64 opened 4 years ago

WinX64 commented 4 years ago

Contextualization

Following issue #45, it is now more important than ever to raise awareness to future users of the API to save player-related data using unique ids, instead of player names.

Names are not only variable since premium accounts can change them, they're also no longer unique as well, since players with the same name (but different account type) can join the server simultaneously.

Problem

Linking data to the unique id is the safest option, and it can be easily queried by converting the unique id to the corresponding name.

For original accounts, this is easily done by consulting Mojang's API.

For pirated accounts, however, that feat is impossible. Unique ids for pirated accounts are generated from the hashed MD5 string OfflinePlayer:<name>, and so, are unidirectional functions, easily allowing the calculation of a unique id based on a name, but making the opposite impossible.

Suggestion

A new unique id mapping is suggested, allowing for bidirectional calculation. Below are two suggested implementations, each one having its advantages and disadvantages.

Implementation 1

Unique ids are composed of 128 bits, with 6 of them being reserved (4 for the version and 2 for the variant), resulting in 122 usable bits of data. By padding the user's name with null characters to the left, we can encode each of the 16 letters using the same amount of bits, or 7 (7.625 rounded down) per letter in this case. With 7 bits per letter, it is possible to represent every possible character in the ASCII table, accounting as well for every valid character ([0-9A-Za-z_]).

Implementation 2

There's a total of 63 possible options for each letter in a valid name (52 letters (uppercase and lowercase), 10 number and _), 64 if we consider null characters used for padding names shorter than 16 characters. By using this fact, each possible letter can be mapped to its index, and unique ids can be calculated incrementally.