In an effort to make benchmarking cheating and tamper-proof, I have come up with a simple idea. By using existing technology and a few cryptography principles, it is possible to make score falsification hard.
One of the key elements here is NTP. It is a network protocol that allows a client device to sync its internal clock with that of a server, with decent precision (normally <1s).
The second element is the KDF, or key derivation function. Put simply, it is used to derive a secret key from a user-provided password which will be used for encryption/decryption when using a symmetric key cipher (such as AES). Secret keys are normally 128 or 256 bits long, meaning there are up to 2^128 or 2^256 keys, thus hard to predict.
scrypt is a memory-hard KDF, meaning that in contrast with normal KDFs, it requires a given amount of memory (which can be a lot depending on some parameters). Also, the higher the memory cost, the longer the derivation time.
Here is the notation for the next part:
R - random value
S - salt (also random value but not secret)
K <- secret key
RNG - random number generator, param: output size in bytes
KDF - key derivation function, params: password, salt
T <- Unix epoch
NTP <- network time protocol, param: server to sync with
The benchmark would work as follows:
1) Server: R <- RNG(32)
2) Server: S <- RNG(32)
3) Server: K <- KDF(R, S)
4) Client: T <- NTP(server)
5) Server -> R+S -> Client
6) Client: K <- KDF(R, S)
7) Client -> K -> Server
8) Server: check if K matches
That's the basic principle of the benchmark. Now it certainly needs some tweaks here and there but overall it should work as is.
One of the things that can be implemented to prevent the client to predict the computation time is to send random computation parameters and to measure the client's internal clock right after the computation is done. If the difference is >100ms, the score is considered null.
What do you guys think ?