- Server should save a random bytestring
PS
(regenerated after each full match) for each player.PS
should be visible on game UI. - Server should publish a global 1024-bit (128 bytes) random bytestring
GS
(changed every X minutes). Current and nextGS
should be visible on game UI. - When a match starts, save timestamp
T1
. - When a round starts, save timestamp
T2
, and generate a random bytestringR
. Then, generate random seed for this round by calculating SHA512 hash of concatenation of following elements (||
denotes concatenation):
- T1
- T2
- R
- HMAC-SHA512(GS, T1 || T2 || R)
- HMAC-SHA512(PS, T1 || T2 || R) for each player
- Use RFC7539 ChaCha20 as random number generator. Key, nonce and block count are sliced from the hash generated in step #4. Generated bitstream should be XORed with
GS
to produce output. - Use Fisher–Yates algorithm to shuffle the tiles.
- All random bytestrings should be at least 32 bytes long, and preferably generated from
/dev/urandom
orRDRAND
. - All timestamps should be at least in millisecond precision
- All seed materials should be saved in game record for verification
T1
,T2
andR
should be kept on server-side and NOT revealed to players until the match is completed
- Random number generator with deterministic seed allows players to verify that tiles are shuffled using this algorithm
GS
andPS
ensure that server can't use a pre-generated tile list for a specific gameT1
,T2
andR
introduce randomness into the algorithm, and ensure player can't compute tile list for games in progress- XORing with
GS
is for increasing number of possible permutions to 1024bit