Esquema de assinatura
ML-DSA-87 explicado matematicamente
Como o ML-DSA-87 (FIPS 204) assina uma avaliação da McGesund — do Module-LWE ao rejection sampling, até à verificação no navegador.
Atualizado: 2026-09-07
1. Do que se trata aqui
Quando alguém submete uma avaliação na McGesund, acontece nos bastidores mais do que o texto deixa supor. Ao ser enviada, a avaliação é assinada digitalmente. Qualquer visitante pode mais tarde recalcular essa assinatura no seu próprio navegador — sem confiar em nós e sem nos perguntar nada.
Para clientes a partir do plano Pro, isso acontece, entre outros, com ML-DSA-87. Este artigo explica o que se passa matematicamente.
Uma nota prévia importante:
ML-DSA não é cifragem. O texto da avaliação continua legível publicamente — é esse justamente o sentido de uma avaliação. O ML-DSA não prova sigilo, mas sim origem e integridade.
O ML-DSA foi desenvolvido a partir do CRYSTALS-Dilithium e está normalizado como FIPS 204. O número 87 designa o nível de parâmetros. Há três:
- ML-DSA-44
- ML-DSA-65
- ML-DSA-87
O ML-DSA-87 é o mais alto e situa-se na categoria de segurança 5 do NIST.
2. O que é exatamente assinado?
Não é o texto da avaliação em si que entra na assinatura, mas um objeto de dados compacto que fixa o texto de forma inequívoca. Na McGesund, no essencial, tem este aspeto:
{
"v": 1,
"typ": "rev-comment",
"f": "<ID da empresa>",
"c": "<ID da avaliação>",
"h": "<SHA-256 do texto da avaliação>",
"rh": "<SHA-256 de todo o registo de submissão>",
"rv": 1,
"qh": "<SHA-256 do envelope QR, apenas em avaliações por QR>",
"iat": 1757203200
}
Este objeto é a nossa mensagem . Liga entre si seis afirmações:
- A que empresa pertence a avaliação (
f) - Que avaliação está em causa (
c) - Que texto estava por trás — sob a forma de hash (
h) - Que registo no seu conjunto foi submetido (
rh): texto, corações, estado de geolocalização e dados sobre o motivo, serializados canonicamente e reduzidos a hash — na versão de esquemarv - De que código QR provém a avaliação (
qh); sem QR o campo não existe - Quando foi assinada (
iat)
Se alguém alterar mais tarde um único caráter do texto da avaliação, o h deixa de encaixar — e o rh também não. Quem, em vez disso, mexer apenas nos corações deixa o h intacto, mas quebra o rh. Se alguém alterar um destes valores de hash, a assinatura deixa de encaixar. É precisamente esta cadeia que interessa.
3. O que a assinatura deve garantir
Um visitante que lê a avaliação deve poder verificar por si três coisas:
- A avaliação foi efetivamente emitida pela McGesund.
- O texto não foi alterado desde o envio.
- Ninguém pode inventar uma avaliação nova com aparência de válida.
Para isso existe um par de chaves:
- uma chave privada — encontra-se exclusivamente no serviço de assinatura
- uma chave pública — pode estar em poder de qualquer pessoa e é endereçada pelo ID da chave (
kid) no envelope
Assina-se com a chave privada. Verifica-se com a pública — e isso acontece no navegador do leitor, não no nosso servidor.
4. Porquê sequer um esquema pós-quântico?
Muitos dos esquemas de assinatura hoje habituais assentam na fatorização de números grandes ou em logaritmos discretos. Um computador quântico suficientemente potente poderia resolver exatamente estes problemas muito mais depressa com algoritmos já conhecidos.
Para uma avaliação, isso não é uma questão académica. Uma avaliação deve continuar verificável daqui a dez anos. Quem assina hoje, assina para todo o tempo de vida do registo.
Por isso, o ML-DSA usa outra base:
Mais precisamente: Module-LWE e Module-SIS.
5. O que é um reticulado?
Para já, apenas pontos no espaço. Tomemos dois vetores:
Todas as combinações com coeficientes inteiros
formam o reticulado. Por exemplo:
O decisivo:
Em dimensões pequenas, os problemas de reticulados são fáceis. Em dimensões muito altas, determinadas tarefas tornam-se extremamente difíceis.
6. Polinómios em vez de números isolados
O ML-DSA não calcula com vetores em 2D, mas com polinómios e vetores de polinómios.
Um polinómio como
pode escrever-se como lista de coeficientes:
Calcula-se num anel:
Isso significa duas coisas:
- : calcular módulo
- : uma regra adicional que fixa o comprimento dos polinómios
Para os três níveis do ML-DSA vale:
Um polinómio tem, portanto, 256 coeficientes, considerados módulo 8 380 417. O que muda entre os níveis não é nem , mas o tamanho das matrizes — mais sobre isso adiante.
A propósito: na prática, a multiplicação de polinómios neste anel corre através da NTT, a variante da teoria dos números da transformada rápida de Fourier. O ML-DSA está, portanto, longe de dispensar as ideias da FFT; elas estão apenas na aritmética em vez de estarem no princípio da assinatura.
7. O truque central: Module-LWE
A ideia de base é Module Learning With Errors:
Em que:
- — matriz pública de polinómios, aparentemente aleatória
- — vetores secretos pequenos
- — valor público
Um atacante conhece e , mas não . Para ele, a equação parece uma equação aleatória com ruído. Não deve conseguir extrair dela os pequenos segredos de forma eficiente.
8. Um exemplo numérico minúsculo
Tomamos de propósito uma variante ridiculamente pequena — números normais em vez de polinómios, dimensão 2 em vez de 256, e
Seja
Então:
Neste miniformato seria possível experimentar todas as possibilidades. No ML-DSA-87, é uma matriz de polinómios com 256 coeficientes cada — são mais de 14 000 incógnitas na estrutura do reticulado.
9. O par de chaves do serviço de assinatura
A chave privada contém, entre outras coisas, os pequenos vetores . No ML-DSA-87, os seus coeficientes provêm do intervalo
ou seja, de . Esta pequenez não é um pormenor, é o núcleo: só porque os segredos são pequenos é que surge sequer um problema de reticulados difícil.
A chave pública é, de forma simplificada,
é uma seed a partir da qual se reconstrói deterministicamente — a matriz não precisa, portanto, de ser transmitida. são os bits superiores de ; os bits inferiores ficam de fora, o que reduz consideravelmente a chave. Esta omissão é, mais adiante, a razão para os chamados hints.
Assim nasce a assimetria pretendida:
10. A avaliação transforma-se num número
O serviço de assinatura começa por reduzir a hash o objeto do payload da secção 2:
No nosso exemplo de brincar tomamos um mini-hash artificial. No sistema real, tem 512 bits e inclui adicionalmente a chave pública — o que impede que uma assinatura seja reinterpretada como pertencendo a outra chave.
11. Compromisso
O serviço de assinatura sorteia um vetor pequeno aleatório . No nosso exemplo:
Daí resulta um valor intermédio, o compromisso:
Isto ainda não é uma assinatura.
12. Da avaliação nasce um desafio
A mensagem e o compromisso são reduzidos a hash em conjunto:
No ML-DSA-87, é um polinómio com exatamente coeficientes de ; os restantes 196 são zero. Esta estrutura é intencional: mantém pequeno.
No nosso exemplo de brincar, pomos simplesmente
13. A assinatura propriamente dita
Com os nossos valores:
14. O passo que facilmente escapa: rejection sampling
Aqui está o ponto em que o ML-DSA se distingue de uma construção ingénua — e não é opcional.
contém o segredo . Se fosse simplesmente divulgado sempre, seria possível extrair estatisticamente a partir de um número suficiente de assinaturas. Num portal de avaliações com muitíssimas assinaturas por dia, isso não é um risco teórico.
Por isso, o serviço de assinatura verifica antes da emissão se revela demasiado e, em caso afirmativo, descarta a assinatura — recomeçando então do princípio com um novo aleatório. Chama-se a isto Fiat-Shamir with Aborts.
A condição é, no essencial:
Para o ML-DSA-87 vale e . A isso acresce um segundo limiar sobre os bits inferiores. Na prática, várias passagens são normais — assinar é, portanto, um processo iterativo e não um passo único.
Para a verificação é importante o seguinte: é exatamente este limiar que o navegador confere mais tarde. Uma assinatura com coeficientes demasiado grandes é rejeitada, mesmo que a equação feche.
15. Porque é que o navegador consegue verificar isto
O navegador do leitor conhece:
- a avaliação e, com ela,
- a chave pública
- a assinatura
Não conhece . A relação que, ainda assim, o faz avançar:
E, uma vez que
se verifica, o desconhecido pode ser substituído pelo valor público:
Esta é a equação central — e diz algo importante: o navegador não reconstrói exatamente, mas apenas a menos do pequeno termo .
16. O pequeno exemplo até ao fim
Tínhamos:
Façamos as contas:
O compromisso original era
A diferença é
Ou seja, exatamente o pequeno termo de erro previsto. O verificador não recebe , mas algo que fica perto de .
É precisamente por isso que o ML-DSA não compara os valores em si, mas os seus bits superiores. E é precisamente por isso que a assinatura contém adicionalmente um vetor de hints : indica de forma compacta em que posições o arredondamento saltou uma fronteira por causa do pequeno termo de erro. No ML-DSA-87 são permitidos no máximo desses indícios. Eles não revelam o segredo — apenas reparam o arredondamento.
No fim, o navegador recalcula o desafio. Se coincidir,
e se todas as normas estiverem dentro dos limiares, a assinatura é válida.
17. O que acontece se alguém alterar a avaliação?
Suponhamos que alguém com acesso à base de dados — incluindo alguém da nossa equipa — altera o texto da avaliação ou um dos corações. Então muda pelo menos um dos dois valores de hash no payload (h no caso do texto, rh no caso de qualquer campo do registo):
Com isso muda o desafio:
Mas a assinatura existente foi gerada para o desafio antigo. O navegador refaz as contas e conclui:
A frase decisiva é esta: podemos apagar uma avaliação, mas não podemos alterá-la sem que se note. Na McGesund, a mesma verificação corre ainda todas as noites do lado do servidor sobre o acervo — uma avaliação que não passe nessa verificação deixa de contar para a média da empresa.
18. Porque é que ninguém pode inventar uma assinatura?
Um atacante conhece e , mas não . Para construir uma assinatura válida, teria de encontrar um trio que
- satisfaça a equação de verificação e
- respeite os limiares de norma e
- corresponda ao desafio que resulta exatamente destes mesmos valores.
No essencial, isso conduz a um problema de reticulados difícil — em concreto, ao Module-SIS: encontrar soluções curtas de uma equação homogénea módulo . A condição de pequenez não é aqui um acessório, é o verdadeiro grau de dificuldade. Sem ela, uma solução seria trivial.
19. Porquê «module»?
A palavra descreve a estrutura situada entre vetores simples e reticulados gerais. Em vez de calcular com números isolados, o ML-DSA trabalha com vetores de polinómios:
e com matrizes formadas por eles:
A vantagem: obtém-se a alta dimensão de um reticulado, mas mantém-se uma representação compacta e eficientemente calculável. A segurança pode ser afinada através do tamanho da matriz, sem mudar de anel.
20. Porquê precisamente 87?
Os três níveis não se distinguem no anel, mas nas dimensões:
| Parâmetro | ML-DSA-44 | ML-DSA-65 | ML-DSA-87 |
|---|---|---|---|
| Tamanho da matriz | |||
| Intervalo do segredo | 2 | 4 | 2 |
| Peso do desafio | 39 | 49 | 60 |
| Chave pública | 1 312 B | 1 952 B | 2 592 B |
| Assinatura | 2 420 B | 3 309 B | 4 627 B |
| Categoria NIST | 2 | 3 | 5 |
Digno de nota: o ML-DSA-87 não é simplesmente «o ML-DSA-65, só que maior». O intervalo do segredo volta de 4 para 2; aqui a segurança vem da matriz maior, não de coeficientes maiores. Trata-se de uma escolha de parâmetros autónoma e normalizada.
O preço: 4 627 bytes por assinatura — por cada carimbo que é armazenado e entregue ao navegador no momento da verificação. Por isso, na McGesund, ao lado do ML-DSA-87 existe também o FALCON à escolha, que se basta com 1 280 bytes.
21. Fiat-Shamir: porque funciona sem interlocutor
Uma prova interativa decorreria assim:
- O serviço de assinatura envia um compromisso.
- O verificador envia um desafio aleatório.
- O serviço de assinatura responde.
- O verificador refaz as contas.
No caso de uma avaliação, esse diálogo não existe — o leitor chega meses mais tarde. A solução é a transformação de Fiat-Shamir: o desafio não é sorteado, mas obtido por hash a partir dos próprios dados:
Assim, um diálogo transforma-se num documento. O serviço de assinatura não pode escolher o desafio, porque para isso teria de controlar o hash.
22. Todo o processo
23. O que a McGesund faz concretamente com isto
Três níveis encaixam uns nos outros:
O envelope. Cada avaliação assinada leva uma assinatura Ed25519. Essa é a variante obrigatória — clássica, minúscula, verificável nativamente em qualquer navegador.
Os carimbos pós-quânticos. Adicionalmente, podem ser colocadas ao lado uma ou duas assinaturas resistentes a computadores quânticos. Quais, depende do plano:
| Plano | níveis de assinatura disponíveis |
|---|---|
| Basis | Ed25519, FN-DSA-512 |
| Klassik | Ed25519, FN-DSA-512, FN-DSA-1024 |
| Pro | Ed25519, FN-DSA-1024, ML-DSA-87 |
| Premium | Ed25519, FN-DSA-1024, ML-DSA-87, ambas em paralelo |
A variante paralela é deliberadamente redundante. Se uma das duas famílias matemáticas — reticulados NTRU no FALCON, reticulados de módulo no ML-DSA — vier a revelar-se mais fraca do que hoje se admite, a outra continua a sustentar.
A âncora temporal. A impressão digital da chave de assinatura é ancorada num bloco da Bitcoin através do OpenTimestamps. Com isso, não se demonstra apenas que a assinatura é autêntica, mas também que já existia num determinado momento — sem que ninguém tenha de acreditar no nosso carimbo temporal.
Tudo isto é verificado no navegador do leitor, através de um módulo WASM. Nós fornecemos os dados; as contas são refeitas no aparelho do visitante. Se amanhã saíssemos da rede, uma avaliação já descarregada continuaria verificável.
24. ML-DSA e FALCON lado a lado
| Propriedade | FALCON (FN-DSA) | ML-DSA |
|---|---|---|
| Tipo | assinatura digital | assinatura digital |
| Família de reticulados | NTRU | Module-LWE / Module-SIS |
| Anel | , | , |
| Mecanismo central | vetor curto por amostragem gaussiana | desafio-resposta com abortos |
| FFT / NTT | FFT de vírgula flutuante, crítica para a segurança | NTT, apenas aritmética |
| Tamanho da assinatura (nível mais alto) | 1 280 B | 4 627 B |
| Implementação | exigente (vírgula flutuante) | comparativamente direta |
| Normalização | prevista como FIPS 206 (FN-DSA), ainda não concluída | FIPS 204, concluída |
Em resumo: o ML-DSA é mais fácil de implementar e verificar corretamente, o FALCON fornece assinaturas bastante mais compactas. No código QR não está nenhuma das duas — ali fica apenas o envelope Ed25519. Por isso, o tamanho da assinatura conta no armazenamento e na entrega, e a robustez conta na implementação. É por isso que oferecemos ambas.
25. Uma frase para levar
Quem possui o vetor secreto assina em milissegundos. Quem não o possui teria de resolver um problema de reticulados em mais de 14 000 dimensões — mesmo com um computador quântico.
Para o leitor de uma avaliação, isso significa simplesmente: não tem de acreditar em nós. Pode verificar por si.