This rng cheating can be prevented. Have everyone generate a random number in any way they want. Send that number out along with their inputs. xor all the numbers together. Then deterministically stretch the result into however much randomness is needed.
This approach alone is not enough. A cheating bot could wait until they received the input+number from all other players, then choose their own number as needed to obtain the desired "random" result.
A workaround is to have all parties pre-commit to their numbers by first sending a hash of the number. Each party will reveal their number only after receiving the hashes of everybody else. This adds another round-trip, which is bad for latency.
As a compromise, one could have clients pre-generate a whole sequence of numbers, pre-commit to that sequence by publishing its hash, and then reveal the sequence one number at a time. Then it is possible to detect tampering with the randomness at the end of a game.
However, even with this modification, another source of cheating in a peer-to-peer networked game may be that one party might want to adjust their input after having received the inputs of everybody else. This can again be mitigated with the same commit-before-publish scheme, except that now the loss of latency cannot be prevented.
(Obviously, all of these cheats can be eliminated when you have a trusted server, but in that case you can just let that server generate the randomness...)
The reason behind needing a salt normally is password reuse / poor entropy. But you don't have either problem with this situation.
Just have each peer generate a random number of sufficient length.
So, roughly. When you need more random numbers:
1) Have every client generate a random number of sufficient length and publish a cyyptographic hash of it.
2) Wait for everyone to ack that they have every hash
3) Everyone publishes the random numbers.
3) Every client verifies that everyone's random numbers match the hashes, and computes the final random value as the xor of everyone's random numbers.
As long as the random numbers generated by the clients are long enough / actually randomish, this should work.
AFAIK, this is secure. A client cannot delay until after they know other peoples random numbers, as it'll stall at step 2. A client cannot find someone else's random number from their hash, as inverting the cryptographic hash of a random number of sufficient length is infeasible.
About the only concern with this is spoofed network communication. And that's detectable.
I can force a bit one by simply doing a preimage attack on that bit; I can calculate two messages (0 and 1) that both have the same hash. Because there's no salt, I can spend as much time as I want doing that, but when it comes time to show the numbers (3) I simply wait for everyone else to publish, xor their bits together, and choose which message I want to reveal.
> I can calculate two messages (0 and 1) that both have the same hash.
It's part of the definition of a (secure) cryptographic hash function that this is impossible. For a secure hash function, finding two messages with the same hash cannot be done faster than by birthday collisions, which means that for a 256 bit hash function you need to compute 2^128 hashes, for a 512 bit hash function you need to compute 2^256 hashes. Even 2^128 is a pretty big number.
So you're right: adding the salt prevents the attack of precomputing a collision using an insane amount of computing power. Then again, if that's what you're worried about then you also have to consider AES-128 as broken, which (today) puts you in a rather small minority. I suppose one can never be paranoid enough ;-)
Good point. Yes, if the range of random numbers chosen is small.
If the random numbers being exchanged are N bits long and the length of the hash is also N (say N = 256), then a salt should be unnecessary, right? Inverting an essentially random hash value should be impossible. But it's always possible that I'm missing something.