Comment fonctionne un tirage — exemple concret

Suivez un tirage réel de bout en bout : 1 000 commentaires éligibles, 3 gagnants, 9 remplaçants. Sans jargon ni approximation.

Le scénario

Imaginez que le concours est terminé. Les commentaires ont été récupérés, les filtres du concours ont été appliqués, et 1 000 participations sont éligibles. Le prix récompense 3 gagnants avec 9 remplaçants, au cas où certains gagnants seraient injoignables. Voici la probabilité par participation — identique pour chacun des 1 000 commentaires éligibles, quelle que soit la date de publication ou la longueur du nom du commentateur.

Résultat Chance pour une participation
Tiré comme gagnant principal (positions 1–3) 3 sur 1 000 — 0,30 %
Tiré comme remplaçant (positions 4–12) 9 sur 1 000 — 0,90 %
Tiré dans n'importe quel emplacement gagnant 12 sur 1 000 — 1,20 %

Cela ne change pas si le concours a 444 commentaires ou 444 444. L'algorithme est identique. Seul le dénominateur change.

Étape 1 — Collecter et filtrer les participations

L'application récupère chaque commentaire sur la publication Facebook ou Instagram que vous avez connectée, puis applique les filtres du concours — doublons, mots bloqués, règles d'ancienneté du compte, selon la configuration. Ce qui reste constitue l'ensemble éligible. Dans notre scénario, ce sont 1 000 commentaires. Chacun possède une ligne en base de données avec un identifiant numérique unique ; ces 1 000 identifiants sont ceux sur lesquels repose le reste du tirage.

Étape 2 — Les trier dans un ordre canonique

Avant qu'il ne se passe quoi que ce soit d'aléatoire, l'application trie les 1 000 identifiants en ordre numérique strictement croissant — 17, 142, 203, 1058, 9941, … — et ignore l'ordre dans lequel ils sont arrivés. Pourquoi ? Parce que Facebook peut renvoyer les commentaires dans des ordres différents selon la pagination, l'heure de la journée ou des changements internes. Si le tirage utilisait l'ordre de Facebook, deux récupérations pourraient produire des gagnants différents à partir du même grain aléatoire. Trier d'abord fige l'entrée sur une liste canonique unique, de sorte que le grain seul détermine le résultat.

Étape 3 — Verrouiller la liste d'entrée avec un hash SHA-256

La liste triée est passée dans SHA-256 — une fonction de hachage cryptographique — produisant une empreinte de 64 caractères. L'empreinte, ainsi que la liste complète, est enregistrée dans l'enregistrement du concours. À partir de ce moment, toute personne inspectant le concours peut confirmer que la liste éligible n'a pas été modifiée : re-hacher la liste publiée, comparer avec l'empreinte enregistrée, et un seul identifiant modifié donnera un hash complètement différent. Il est impossible d'ajouter ou de supprimer discrètement un commentaire après cette étape sans que cela soit visible.

Étape 4 — Générer un grain aléatoire de 256 bits

L'application demande à la source aléatoire cryptographique du système d'exploitation (SecureRandom.hex(32)) 32 octets d'aléatoire imprévisible, et stocke le résultat sous forme d'une chaîne hexadécimale de 64 caractères — par exemple a3f1…ce. 256 bits signifie 2²⁵⁶ ≈ 10⁷⁷ grains possibles. Pour se donner une idée, l'univers observable contient environ 10⁸⁰ atomes. Personne — ni le créateur du concours, ni l'opérateur, ni un attaquant observant de l'extérieur — ne peut prédire ou deviner ce grain avant qu'il soit généré.

Étape 5 — Mélanger les 1 000 identifiants, puis prendre les 12 premiers

Le grain initialise un moteur de mélange déterministe, qui effectue ensuite un mélange de Fisher–Yates sur les 1 000 identifiants triés. Fisher–Yates est l'algorithme de mélange équitable standard — chacune des 1 000 participations a une chance égale de se retrouver à chaque position. Après le mélange, l'application prend les 12 premières participations. C'est toute l'étape de sélection : mélanger, extraire 12.

Étape 6 — Attribuer les positions

Les 12 participations sélectionnées sont parcourues dans l'ordre. Les trois premières deviennent les gagnants 1, 2 et 3, et les neuf suivantes deviennent les remplaçants 1 à 9. Les 988 participations éligibles restantes sont enregistrées comme non sélectionnées. Les commentaires filtrés précédemment sont marqués comme disqualifiés avec la raison spécifique pour laquelle ils n'étaient pas éligibles.

Étape 7 — Tout publier

Enfin, l'application enregistre cinq éléments de preuve dans l'enregistrement du concours — tous lisibles publiquement. Sans eux, le résultat serait une boîte noire. Avec eux, n'importe qui peut reproduire l'intégralité du tirage chez soi et confirmer que les gagnants publiés sont les seuls que le grain aurait pu produire.

Ce qui est publié à chaque tirage

Chacun de ces éléments est stocké dans le concours et exposé via les pages de vérification publiques. Ensemble, ils rendent le tirage entièrement reproductible — mêmes entrées, mêmes sorties, toujours.

  • Le grain aléatoire de 256 bits — la chaîne hexadécimale de 64 caractères de l'étape 4.
  • La liste triée des identifiants éligibles — les 1 000 identifiants de l'étape 2, dans l'ordre canonique.
  • L'empreinte SHA-256 des identifiants — le hash de 64 caractères de l'étape 3. Confirme que la liste publiée n'a pas été falsifiée.
  • La version de l'algorithme — actuellement v1. Fixe l'algorithme de sélection exact, de sorte que les améliorations futures ne modifient jamais rétroactivement les anciens résultats.
  • La version de Ruby — fixe l'environnement d'exécution du langage, car l'ordre exact du mélange en dépend.

Refaites le calcul vous-même — en cinq lignes

Si vous avez Ruby installé (il est fourni avec macOS et la plupart des distributions Linux), vous pouvez reproduire le tirage exact chez vous. Chaque concours publie son propre fichier eligible-ids.txt sur sa page de vérification (modèle d'URL : /results/<token>/verify) — le guide de vérification explique étape par étape comment le télécharger. Copiez le grain publié et collez ceci dans irb :

require "digest"
seed = "PASTE_THE_PUBLISHED_SEED_HERE"
ids  = File.read("eligible-ids.txt").split("\n").map(&:to_i).sort

# (1) Sanity check the input: must equal the published SHA-256.
Digest::SHA256.hexdigest(ids.join("\n"))

# (2) Re-run the shuffle. First 3 items are winners 1..3 (in order);
#     the next 9 items are reserves 1..9.
ids.shuffle(random: Random.new(seed.to_i(16))).first(12)

Les 12 identifiants ressortent dans l'ordre exact que le concours a publié. Trois gagnants, neuf remplaçants, bit pour bit identiques. C'est ce qui rend un tirage Pick a Winner vérifiable plutôt que simplement promis — les maths font le travail, pas la parole de l'opérateur.

Pourquoi il est difficile de truquer ce système

  • Le grain est impossible à deviner. 2²⁵⁶ possibilités, générées seulement après que la liste éligible est validée. Personne ne peut précalculer quels identifiants le grain favoriserait, car le grain n'existe pas avant le moment du tirage.
  • L'entrée est verrouillée. L'empreinte SHA-256 signifie que vous ne pouvez pas discrètement ajouter un commentaire d'un ami après avoir vu le grain — l'empreinte changerait et le tirage ne se reproduirait plus.
  • Le mélange est mécanique. Une fois que le grain et la liste triée existent, les gagnants sont déterminés. Aucune décision humaine ne s'interpose entre eux. Toute modification après coup apparaîtrait comme une discordance dès que quelqu'un referait le calcul.
  • Le reçu est public. Grain, liste, hash, version de l'algorithme, version de Ruby — les cinq sont publiés. Il n'existe aucune partie privée du tirage que l'opérateur pourrait modifier sans que tout le monde puisse le voir.