I'm looking to run a small raffle but i'd like people to be able to verify that the number chosen was fair. I know some sites use a "Provably Fair" system to achieve this where user input is combined with a secret string which is then hashed to determine the winner. Once the secret string is released, participants can verify using the hash that the correct winner was chosen.
From a sha512 hash a "random" number from 0-n (n varies in length but is 255 at most) should be generated to determine the winner. This is what I thought up:
Creating an array of n length and inserting pairs of characters that can appear in a sha hash. If n was 255 for example, the array would have: array('aa','ab','ac'...'fd','fe','ff'...'97','98','99')
. Basically it'd have every combination of two characters using a-f and 0-9.
It'd then look at the first two characters of the hash and use array_search to see if that pair exists in the array. If it does, it's index is the number picked, otherwise it moves over to the next pair of characters and searches those. In the rare scenario it doesn't find a match it'll continually hash itself and use the new hash returned to continue the search.
$values = array('a','b','c','d','e','f','0','1','2','3','4','5','6','7','8','9');
$numbers = array();
$ENTRANTS = 100;
$rand = md5(uniqid(rand(), true));
$hash = hash('sha512',$rand);
$values_index = 0;
$current = $values[$values_index];
$options = 0;
while ($options < $ENTRANTS){
$remaining = ($ENTRANTS - $options > 15)? 16: $ENTRANTS-$options;
for ($n=0; $n < $remaining ;$n++){
array_push($numbers, $current . $values[$n]);
$options++;
}
$values_index++;
$current = $values[$values_index];
}
$outcomes = array();
$winning = null;
$i = 0;
while (empty($winning)){
while ($i+1 < 64 && empty($winning)){
$combo = $hash[$i] . $hash[$i+1];
$number = array_search($combo,$numbers);
if ($number !== false){
$winning = $number;
}
$i++;
}
if (!empty($winning)){
echo "<pre>" . print_r($numbers,true) . "</pre>";
echo $hash . "<br>" . $winning;
}
else {
echo "re-hashing" . "<br>";
$hash = hash("sha512",$hash);
$i = 0;
}
}
This is working when tested but I'm unsure if it is effectively generating a random number. Are the characters in a sha512 hash for the most part evenly and unpredictably distributed? If you can see any issues with this or have any advice on how it could be improved please let me know!