Sorteio verificável

Não precisa confiar. Dá para conferir.

Em muitas rifas você só tem a palavra de quem sorteia. Aqui, o resultado é calculado de um jeito que nem nós conseguimos escolher ou prever, e qualquer pessoa pode refazer a conta depois, no próprio navegador.

Confira uma rifa agora

Como funciona, em 4 momentos

  1. 1Na criação: o segredo é trancadoGeramos um número secreto (a seed) e publicamos só o hash SHA-256 dele, o "compromisso". Ele aparece na página da rifa antes de qualquer venda. Mudar a seed depois mudaria o hash, e todo mundo veria.
  2. 2No fim das vendas: a lista é congeladaPublicamos o hash da lista de cotas vendidas (número e apelido de cada uma). Ninguém consegue comprar depois disso.
  3. 3Um número público do futuroEscolhemos uma rodada do drand que só vai sair ~30 segundos depois do fim das vendas. O drand é um serviço público de números aleatórios mantido por universidades e empresas (League of Entropy). Ninguém sabe o valor antes.
  4. 4O sorteio e a revelaçãoCom o valor do drand, a fórmula abaixo calcula os ganhadores e pagamos os prêmios. Na hora revelamos a seed para qualquer pessoa conferir.
Por que ninguém consegue trapacear? Nós não podemos trocar a seed (o hash foi publicado antes) e não sabemos o valor do drand quando as vendas fecham. Um jogador também não, porque não conhece a seed. Só depois de tudo travado o resultado passa a existir.

A fórmula

Para cada prêmio k (0 = 1º lugar) e tentativa t = 0, 1, 2…

h = HMAC-SHA256(chave = seed, mensagem = "drand|hashDaLista|k|t") x = primeiros 4 bytes de h, como número (0 a 4.294.967.295) se x >= floor(2^32 / n) * n → descarta e tenta t+1 (evita viés) cota = cotasVendidas[x mod n] (lista em ordem crescente) se a cota já ganhou um prêmio → tenta t+1

n = quantidade de cotas vendidas. O descarte garante que todas as cotas tenham exatamente a mesma chance.

Quer conferir fora do site?

Todos os dados de uma rifa (seed, compromisso, rodada e valor do drand e a lista completa de cotas) ficam públicos em rifinha.fun/api/rifas/NÚMERO/verificacao. Este código em Python faz a mesma conta:

import hashlib, hmac def confere(seed, compromisso): return hashlib.sha256(seed.encode()).hexdigest() == compromisso def ganhadores(seed, drand, cotas, premios): # cotas = [(numero, "apelido"), ...] exatamente como na página da rifa lista = "|".join(f"{n}:{a}" for n, a in sorted(cotas)) hash_lista = hashlib.sha256(lista.encode()).hexdigest() vendidas = sorted(n for n, _ in cotas) n = len(vendidas) limite = (2**32 // n) * n # evita viés resultado = [] for k in range(premios): # k = 0 é o 1º lugar t = 0 while True: msg = f"{drand}|{hash_lista}|{k}|{t}".encode() h = hmac.new(seed.encode(), msg, hashlib.sha256).digest() x = int.from_bytes(h[:4], "big") t += 1 if x >= limite: continue cota = vendidas[x % n] if cota in resultado: continue resultado.append(cota) break return resultado

O valor do drand de qualquer rodada pode ser consultado direto na fonte pública, em api.drand.sh (rede quicknet). A versão do algoritmo é a "v1"; se um dia mudar, a versão aparece nos dados da rifa.

Como funciona o siteVer rifas abertas