← voltar ao site · Relatório publicado como o revisor entregou, inclusive onde aponta erros da auditoria. As correções já foram aplicadas no site.

Revisão independente da auditoria do 2º turno (25/10/2026)

Revisor: agente independente, 26/10/2026. Código próprio em revisao/ (rber.py, bu_decode.py, cmp_all.py, mun_cmp.py, rdv_decode.py, crypto_test.py, forge_test.py, fraud_sim.py, cmp_bu1.py). Não apaguei nem alterei nada fora de revisao/. Fiz cerca de 75 requisições ao TSE, todas registradas nos scripts refetch.py, rdv_fetch.py e crypto_test.py.

Escala de gravidade usada aqui:

---

1. Decodificação do BU (presidente, 2º turno)

O que fiz. Escrevi um parser BER do zero (rber.py) que valida os comprimentos e rejeita comprimento indefinido. O decodificador (bu_decode.py) navega pela tag, não pela posição. Ele soma todos os ResultadoVotacao, exige que partido == código nos votos nominais e conta tipos de voto desconhecidos.

Em vez de rodar só 30 BUs, rodei os 499.178 BUs brutos do 2º turno.

Resultado.

Erros: nenhum no resultado.

Observação (baixa). bu_all.votes() é frágil: usa índices fixos (k[1], k[4], kids[2]), lê a primeira OCTET STRING com mais de 300 bytes e sobrescreveria out[...] se houvesse mais de um ResultadoVotacao. Com o formato de 2026 isso não causa erro, como a conferência completa acima mostra.

Observação (baixa). O BU tem dois campos de aptos (ex.: 308 e 307). O parser usa o primeiro.

2. Soma por município × tse/mun2

O que fiz. Somei a minha própria decodificação de todos os BUs por município (mun_cmp.py). Comparei com vap dos candidatos 13 e 22 e com vb, tvn e e.c de cada arquivo tse/mun2/*-6258.json.

Resultado.

Erro encontrado (BAIXA-MÉDIA): as 29 seções "sem BU" têm boletim publicado.

3. RDV × BU

Contagem de bu/rdv.jsonl.

Lógica do código (rdv_all.py / rdvp.py). Não é comparação de algo consigo mesmo.

Pontos fracos (baixa).

Reverificação independente. Baixei 12 RDVs aleatórios e decodifiquei com código próprio (rdv_decode.py). Nas 12, a contagem por tipo e número é igual à do BU. Os nulos são principalmente "00" e números de outros cargos.

Limite de interpretação (MÉDIA, de comunicação). RDV e BU são gerados pelo mesmo software, na mesma urna. A concordância prova consistência interna e ausência de alteração depois da urna. Ela não diz nada sobre um software de urna adulterado.

4. Assinaturas (crypto_check.py, ed521.py)

Revisão do código.

Execução. Rodei o verificador em 3 urnas, uma de cada emissor (AC UE2020 df-97012-0001-0662, AC UE2022 rr-03050-0003-0097, AC URNA mg-41076-0022-0061). As 3 passaram em tudo.

Testes de adulteração (crypto_test.py). Nos 3 emissores:

AlteraçãoResultado do verificador
1 byte no meio do BUbu=False
1 bit na assinaturaassinatura=False
1 bit no hash assinadolista=False e assinatura=False
1 bit na lista de hasheslista=False
BU trocado pelo de outra seçãobu=False

A verificação matemática é real: não passaria sempre.

Erro (MÉDIA): o controle declarado testa pouco. O "controle de adulteração" do código (67 de 67) só inverte 1 byte do BU. Isso testa a busca do hash na lista; não testa o caminho da assinatura. Os meus testes acima cobrem essa lacuna, e o resultado foi bom.

Erro (MÉDIA-ALTA): a afirmação "certificado emitido pelo TSE" é falsa no código, e a falsificação passa.

Outros pontos (baixa).

5. fraudbound.py, fluxo.py e aritmética nacional

Aritmética (confirmada)

1º turno. 53.879.538 + 56.104.503 + 9.316.747 + 5.975.047 = 125.275.835.

2º turno. 64.256.232 + 59.826.041 + 4.153.801 = 128.236.074. A diferença é 4.430.191; metade, arredondada, dá 2.215.096, que corresponde a 3,948% dos 56.104.503 votos de Flávio no 1º turno.

Identidade. Ganho de Lula (+10.376.694) + ganho de Flávio (+3.721.538) = 14.098.232. Esse valor é igual a demais (9.316.747) + queda de brancos e nulos (1.821.246) + aumento do comparecimento (+2.960.239).

Erro (ALTA): o "teto de fraude" de fraudbound.py só vale para um tipo de fraude

O site diz que "uma fraude assim exigiria +3,95%" e que "nada desse tamanho cabe nos dados". O coeficiente Flávio 1T → Lula 2T, num MQO sem intercepto, só sobe 3,95 pontos se a fraude tirar uma fração constante dos votos de Flávio em todas as urnas.

Injetei fraudes sintéticas nos dados reais e refiz o ajuste (fraud_sim.py; urnas pareadas: 496.266):

Fraude injetada (≈ suficiente para virar)Votos movidosCoef. Flávio1T → LulaVariação
Nenhuma (base)–−3,02%–
A) 3,95% dos votos de Flávio → Lula em toda urna2,35 mi+0,93%+3,95 pp (detectada)
B) 2,2 mi Flávio → Lula, proporcional ao voto de Lula2,21 mi−3,12%−0,10 pp (invisível)
C) 2,2 mi Flávio → Lula, só no Nordeste2,21 mi−2,17%+0,84 pp (abaixo do limiar)
D) 4,4 mi votos inventados para Lula a partir da abstenção4,43 mi−2,67%+0,35 pp (invisível)

Consequências:

Os testes 2 e 3 do site ("urnas puras" e Nordeste) limitam razoavelmente desvios de Flávio para Lula, mas não acréscimos. Não reproduzi o código desses dois testes.

Erro (MÉDIA): fluxo.py (mínimos quadrados limitados a [0,1])

Problemas de texto e amostra (baixa)

O que não consegui verificar