Pular para o conteúdo
ecdsa.com
C

libsodium

A libsodium, de Frank Denis, o fork portátil da NaCl: assinaturas Ed25519 com verificação estrita, X25519, criptografia autenticada e ML-KEM-768, além do KEM híbrido X-Wing — mas nenhum suporte a ECDSA.
Licença
ISC
Versão verificada
1.0.22 ·
Código-fonte
github.com/jedisct1/libsodium
Documentação
doc.libsodium.org/

Visão geral da compatibilidade

EdDSAPós-quântica

EdDSA
Ed25519Ed25519ph
Formatos de chave privada
seed-32expanded-64

A libsodium oferece um conjunto pequeno e opinativo de primitivas por trás de funções difíceis de usar errado; ela vem embutida no PHP, é usada por muitos bindings de linguagens e está integrada a aplicativos de mensagens. As assinaturas são apenas Ed25519: os cabeçalhos da 1.0.22 (verificados no pacote do Alpine 3.24.2) não declaram nenhuma função ECDSA, então qualquer coisa que use ES256 ou secp256k1 precisa de outra biblioteca.

A assinatura Ed25519 é determinística, como a RFC 8032 especifica — duas assinaturas da mesma mensagem foram idênticas —, e as funções crypto_sign_*_ph implementam o Ed25519ph, cujas assinaturas não são intercambiáveis com as do Ed25519 simples: no teste, o verificador simples rejeitou uma delas. A chave secreta tem 64 bytes, a semente de 32 bytes seguida da chave pública, enquanto a maioria das outras bibliotecas armazena só a semente; crypto_sign_ed25519_sk_to_seed e crypto_sign_seed_keypair convertem entre as duas formas, como mostra o exemplo.

A verificação é estrita onde outras implementações divergem. Uma assinatura com S substituído por S + L — o mesmo valor módulo a ordem do grupo, proibido pela RFC 8032 — foi rejeitada, assim como uma assinatura verificada com o ponto identidade, de ordem pequena, como chave pública. Bibliotecas que aceitam essas entradas divergem da libsodium em casos-limite, o que importa para sistemas de consenso, que precisam concordar sobre a validade. crypto_sign_verify_detached não recebe o comprimento da assinatura e lê exatamente 64 bytes; por isso, verifique o comprimento antes de chamá-la.

Na 1.0.22, o suporte pós-quântico se limita ao encapsulamento de chave: crypto_kem_mlkem768_* (chaves públicas de 1184 bytes, textos cifrados de 1088 bytes) e o híbrido X-Wing (crypto_kem_xwing_*, 1216 e 1120 bytes), que também é o que as funções genéricas crypto_kem_* usam por padrão. Não há ML-DSA nem outra assinatura pós-quântica. As chaves são sempre bytes brutos — chaves públicas e sementes de 32 bytes —, sem suporte a PEM, DER nem JWK. Compare os tamanhos de KEM no playground de KEM pós-quântico.

Os fatos e as verificações por trás deles

Nada abaixo foi copiado da documentação. A verificação content/libraries/verify/libsodium/run.sh executou libsodium 1.0.22 na imagem de contêiner alpine:3.24.2 em 20 de outubro de 2026; a página precisa corresponder ao que a verificação imprimiu, e cada fato lista essas linhas.

  • Curvas ECDSA

    none

    Sem ECDSA: crypto_sign_PRIMITIVE é ed25519 e nenhum cabeçalho declara uma função ECDSA.

    Registrado pela verificação
    fact ecdsa-curves = none
    evidence ecdsa-curves: crypto_sign_PRIMITIVE is "ed25519"; the header set declares no ECDSA functions
  • EdDSA

    Ed25519Ed25519ph

    Ed25519 com crypto_sign_* e Ed25519ph com crypto_sign_init, _update e _final_*; o verificador simples rejeita assinaturas Ed25519ph.

    Registrado pela verificação
    fact eddsa = Ed25519, Ed25519ph
    evidence eddsa: crypto_sign_final_verify (Ed25519ph) accepts its signature: yes; the plain verifier rejects it: yes
  • Assinaturas Ed25519 determinísticas

    yes

    Duas assinaturas da mesma mensagem com a mesma chave foram idênticas.

    Registrado pela verificação
    fact ed25519-deterministic = yes
  • Estrutura da chave privada Ed25519

    expanded-64

    crypto_sign_SECRETKEYBYTES é 64: a semente seguida da chave pública.

    Registrado pela verificação
    fact ed25519-private-key = expanded-64
    evidence ed25519-private-key: crypto_sign_SECRETKEYBYTES = 64: the 32-byte seed followed by the 32-byte public key (seed matches: yes)
  • Assinatura Ed25519 com S não canônico

    rejected

    Uma assinatura com S substituído por S + L foi rejeitada.

    Registrado pela verificação
    fact ed25519-non-canonical-s = rejected
  • Chave pública Ed25519 de ordem pequena

    rejected

    A verificação com o ponto identidade como chave pública falhou.

    Registrado pela verificação
    fact ed25519-small-order-key = rejected
    evidence ed25519-small-order-key: the identity point as public key with R = identity, S = 0
  • Assinatura Ed25519 malformada

    rejected

    64 bytes de lixo fizeram crypto_sign_verify_detached retornar -1.

    Registrado pela verificação
    fact ed25519-malformed-signature = rejected
    evidence ed25519-malformed-signature: 64 bytes of 0xab: crypto_sign_verify_detached returned -1; the function takes no length and reads exactly crypto_sign_BYTES = 64 bytes
  • Modos de assinatura

    detachedcombined

    Os dois modos estão disponíveis: assinaturas desanexadas (64 bytes) e mensagens assinadas combinadas (a assinatura vem antes da mensagem).

    Registrado pela verificação
    fact signature-modes = detached, combined
    evidence signature-modes: crypto_sign prepends the 64-byte signature to the message: 82 bytes for a 18-byte message
  • Algoritmos pós-quânticos

    ML-KEMX-Wing

    O encapsulamento e o desencapsulamento funcionaram com ML-KEM-768 (crypto_kem_mlkem768_*) e X-Wing (crypto_kem_xwing_*, o padrão das funções genéricas crypto_kem_*); não há assinaturas pós-quânticas.

    Registrado pela verificação
    fact pqc = ML-KEM, X-Wing
    evidence pqc: crypto_kem_mlkem768: public key 1184 bytes, ciphertext 1088 bytes
    evidence pqc: crypto_kem_xwing: public key 1216 bytes, ciphertext 1120 bytes; generic crypto_kem_primitive() is "xwing"
  • Formatos de chave pública

    raw-32

    As chaves públicas são 32 bytes brutos; não há suporte a PEM, DER nem JWK.

    Registrado pela verificação
    fact public-key-formats = raw-32
  • Formatos de chave privada

    seed-32expanded-64

    As chaves derivam de uma semente de 32 bytes (crypto_sign_seed_keypair) e são armazenadas em 64 bytes; crypto_sign_ed25519_sk_to_seed recupera a semente.

    Registrado pela verificação
    fact private-key-formats = seed-32, expanded-64
    evidence private-key-formats: crypto_sign_seed_keypair reproduces the key from the seed: yes; crypto_sign_ed25519_sk_to_seed recovers it: yes

Uso

Gere uma chave Ed25519, extraia a semente de 32 bytes que outras bibliotecas esperam e crie e verifique uma assinatura desanexada.
#include <sodium.h>
#include <stdio.h>
#include <string.h>

int main(void) {
    if (sodium_init() < 0) return 1;
    const unsigned char msg[] = "order #1042 approved";
    unsigned char pk[crypto_sign_PUBLICKEYBYTES], sk[crypto_sign_SECRETKEYBYTES];
    unsigned char sig[crypto_sign_BYTES], seed[32];

    crypto_sign_keypair(pk, sk);
    /* Other libraries store the 32-byte seed; libsodium's secret key is seed || public key. */
    crypto_sign_ed25519_sk_to_seed(seed, sk);

    /* Detached signature: 64 bytes, deterministic per RFC 8032. */
    crypto_sign_detached(sig, NULL, msg, sizeof msg - 1, sk);
    int ok = crypto_sign_verify_detached(sig, msg, sizeof msg - 1, pk) == 0;

    printf("secret key %d bytes, seed %zu bytes, signature %d bytes, verified: %d\n",
           crypto_sign_SECRETKEYBYTES, sizeof seed, crypto_sign_BYTES, ok);
    return 0;
}

O executor de trechos de código roda cada exemplo literalmente na imagem de contêiner alpine:3.24.2, e a execução falha se a saída não corresponder.

Configuração
apk add --no-cache -q build-base libsodium-dev=1.0.22-r0 >/dev/null
Comando
cc -o usage usage.c -lsodium && ./usage
A saída deve corresponder a (expressão regular)
secret key 64 bytes, seed 32 bytes, signature 64 bytes, verified: 1

Bibliotecas