Metodologia: como um sorteio pode ser verificado por qualquer pessoa

Atualizado em

Resumo: um sorteio é verificável quando a lista é fixada antes de a aleatoriedade existir, o número aleatório vem de uma fonte pública e o cálculo é determinístico e aberto. Assim, qualquer pessoa refaz o sorteio depois e chega ao mesmo resultado.

Versão: o sorteio aplica este método (sorteio-v1) no seu navegador. O certificado acrescenta carimbos do tempo emitidos por autoridades independentes e a página pública de conferência.

Qual é o problema dos sorteios comuns?

Em um sorteador comum, o resultado sai de um número aleatório gerado no computador de quem opera a ferramenta. Você precisa acreditar que ninguém mexeu na lista, que o sorteio não foi repetido até sair o resultado desejado e que o algoritmo faz o que diz. Depois do evento, não há como conferir nada.

Uma planilha com a função de número aleatório tem o mesmo problema, e ainda um agravante: a função recalcula a cada alteração, então o resultado que estava na tela some.

Como funciona o método, passo a passo?

1. A lista é normalizada e recebe um hash

A lista é padronizada (codificação UTF-8, normalização Unicode, espaços aparados, linhas vazias removidas) e a ordem original é preservada. Depois se calcula o hash SHA-256 dela. O hash funciona como uma impressão digital: qualquer mudança, mesmo de uma letra, produz um hash completamente diferente. As regras do sorteio (quantos sorteados, suplentes, tratamento de repetidos) também recebem um hash.

2. A lista é fixada antes de o número existir (compromisso)

No sorteio com certificado, o registro tem dois momentos. Ao confirmar, os hashes da lista e das regras recebem um carimbo do tempo (padrão RFC 3161) de duas autoridades independentes: a “trava”. Quando a pessoa clica em “Realizar sorteio”, o sistema escolhe uma rodada futura da rede de aleatoriedade pública e registra um compromisso com os hashes da lista, das regras e dessa rodada, que também é carimbado. O segundo carimbo prova que a rodada foi escolhida antes de ser publicada; o primeiro prova desde quando a lista e as regras estavam fixadas.

3. O número aleatório vem de uma rede pública

O drand é uma rede distribuída, operada por várias organizações independentes, que publica a cada poucos segundos um número aleatório acompanhado de uma assinatura criptográfica. Como o número da rodada escolhida ainda não existia no momento do compromisso, nem o operador do sorteio nem quem forneceu a lista conseguem prevê-lo ou escolhê-lo.

4. O resultado sai de um cálculo determinístico

A semente do sorteio é derivada dos três ingredientes:

semente = SHA-256("sorteio-v1\n" + número_público + "\n" + hash_da_lista + "\n" + hash_das_regras)

Com essa semente, a lista é embaralhada pelo método de Fisher-Yates, usando amostragem por rejeição para evitar viés no sorteio de posições. Os sorteados são as primeiras posições; os suplentes, as seguintes. Como não há nenhuma escolha humana nem número gerado localmente, o cálculo é reproduzível.

5. Qualquer pessoa pode verificar

Um verificador independente, de código aberto, confere:

  1. se a lista informada corresponde ao hash registrado;
  2. se a assinatura do número da rodada é válida e a rodada é posterior ao carimbo do tempo;
  3. se os carimbos do tempo são válidos para a trava e para o compromisso;
  4. se o cálculo refeito produz o mesmo resultado.

Você pode fazer isso na página de verificação, que roda no seu navegador, ou pela linha de comando. O verificador também funciona sem consultar a nossa plataforma: a assinatura do drand é conferida com a chave pública da rede.

Qual é a especificação exata da versão sorteio-v1?

Para que qualquer pessoa implemente a verificação por conta própria, estes são os detalhes que definem o resultado:

  1. Lista: uma entrada por linha; cada item em Unicode NFC e sem espaços nas pontas; linhas vazias descartadas; a ordem original é preservada. Se a regra for "remover repetidos", fica só a primeira ocorrência de cada item (comparação sem diferenciar maiúsculas de minúsculas).
  2. Hash da lista: SHA-256 do texto JSON do array de itens (por exemplo ["Ana","Bruno"], sem espaços), codificado em UTF-8, em hexadecimal minúsculo.
  3. Hash das regras: SHA-256 do texto JSON do objeto {"algoritmo","modo","sorteados","suplentes","duplicados"}, nesta ordem de chaves, sem espaços.
  4. Número público: o campo randomness da rodada do drand (rede quicknet), que é o SHA-256 da assinatura da rodada. A assinatura (BLS12-381) é verificada contra a chave pública da rede.
  5. Semente: a fórmula acima, com os três valores em hexadecimal minúsculo e a codificação UTF-8.
  6. Fluxo pseudoaleatório: o bloco de índice i é SHA-256(semente ‖ i em 4 bytes big-endian); cada bloco rende oito inteiros de 32 bits (big-endian), consumidos em ordem.
  7. Inteiro em [0, n): amostragem por rejeição: descarta valores iguais ou maiores que ⌊2³² / n⌋ × n e usa o resto da divisão por n.
  8. Embaralhamento: Fisher-Yates com i de n−1 até 1, trocando a posição i com uma posição j sorteada em [0, i]. Sorteados são as primeiras posições; suplentes, as seguintes.

Uma implementação de referência independente (em Python, apenas com a biblioteca padrão) é conferida automaticamente contra a implementação do site em testes, e produz exatamente os mesmos resultados.

O que esse método prova e o que ele não prova?

Prova

  • que a lista e as regras não foram alteradas depois do compromisso;
  • que o resultado vem de uma fonte aleatória que ninguém controla;
  • que o resultado pode ser refeito por terceiros;
  • quando o compromisso foi registrado.

Não prova

  • que a lista de entrada estava correta ou completa (um sorteio verificável sobre uma lista errada é fielmente errado);
  • que o sorteio cumpre exigências legais ou formais do caso (ata, ato público exigido por edital, estatuto ou convenção, autorização de ações promocionais);
  • quem assinou o documento: isso depende da assinatura que o responsável aplicar no PDF, por exemplo com o gov.br.

Perguntas frequentes sobre a metodologia

Por que travar a lista antes do sorteio?

Porque, se a lista pudesse mudar depois de o número aleatório ser conhecido, alguém poderia ajustá-la para favorecer um resultado. O hash e o carimbo do tempo provam que a lista já estava fixa quando o número foi gerado.

O que o carimbo do tempo prova?

Prova que um conjunto de dados (aqui, o compromisso com a lista) existia em determinado momento e não foi alterado depois. Ele não diz se a lista está correta, apenas quando ela foi fixada.

Dá para refazer o sorteio e chegar ao mesmo resultado?

Sim. O cálculo é determinístico: com a mesma lista, as mesmas regras, o mesmo número público e a mesma versão do algoritmo, o resultado é sempre o mesmo.

Glossário: termos usados nesta página

Definições curtas dos termos técnicos do método.

Sorteio verificável
Sorteio em que qualquer pessoa, depois do fato, consegue refazer o cálculo e chegar ao mesmo resultado, e comprovar que a lista foi fixada antes de a fonte de aleatoriedade existir.
Hash
Resultado de uma função que transforma qualquer conjunto de dados em um código curto de tamanho fixo. Funciona como uma impressão digital: mudar um único caractere dos dados muda completamente o hash.
SHA-256
Função de hash amplamente usada e considerada segura, que produz um código de 256 bits. É a usada pelo método do Sorteio Verificável.
Compromisso (commit)
Registro, feito antes de um evento, de dados que não poderão mais ser alterados. No sorteio, o compromisso reúne os hashes da lista e das regras e a rodada escolhida da rede de aleatoriedade.
Carimbo do tempo
Prova emitida por uma autoridade independente de que determinados dados existiam em um momento específico e não foram alterados desde então. O padrão técnico mais usado é o RFC 3161.
RFC 3161
Padrão da internet para serviços de carimbo do tempo. Uma autoridade de carimbo assina digitalmente o hash dos dados junto com a data e a hora.
drand
Rede pública e distribuída que publica números aleatórios verificáveis a cada poucos segundos, operada por várias organizações independentes. Cada número vem com uma assinatura que qualquer pessoa pode conferir.
Rodada
Cada número aleatório publicado pelo drand corresponde a uma rodada numerada. O sorteio usa uma rodada futura, que ainda não existia quando a lista foi fixada.
Semente (seed)
Valor inicial a partir do qual o algoritmo calcula o resultado de forma determinística. Mesma semente e mesma lista produzem sempre o mesmo resultado.
Embaralhamento de Fisher-Yates
Algoritmo clássico para embaralhar uma lista de modo que todas as ordens possíveis sejam igualmente prováveis, quando alimentado por números aleatórios sem viés.
Amostragem por rejeição
Técnica que descarta valores aleatórios que causariam viés ao converter um número grande em uma posição da lista (viés de módulo), garantindo que todas as posições tenham a mesma chance.
Verificador independente
Programa de código aberto que refaz o cálculo do sorteio e confere hashes, assinaturas e carimbos sem depender da plataforma que realizou o sorteio.
Ata
Documento que registra formalmente o que ocorreu em uma reunião ou assembleia. O certificado de um sorteio pode ser anexado à ata como prova de apoio, mas não a substitui.

Para aplicar o método em situações reais, veja os guias.