Skip to content

criptografia curvas

mobius1qwe edited this page Nov 10, 2026 · 1 revision

Home > Curvas elípticas e AES-GCM 🚧

Curvas elípticas, HKDF e AES-GCM

Important

Em desenvolvimento (2.0). Ainda não está numa versão lançada e pode mudar.

Vale para a 2.0 · Delphi XE em diante e Lazarus/FPC 3.2 em diante · Nível: avançado

Em uma frase: o pacote RALCryptoCurvesPackage traz X25519 (troca de chaves), Ed25519 (assinatura), HKDF (derivação de chaves) e AES-GCM (cifra autenticada), em Pascal puro, sem OpenSSL nem DLL, para quem precisa dessas primitivas por conta própria.

Você vai precisar: o pacote RALCryptoCurvesPackage (sem componentes; só units), que requer o PascalRAL. Não confunda com a criptografia ponto a ponto, que cifra o corpo das requisições com AES-CBC.

Para que serve

  • verificar a assinatura Ed25519 de webhooks (a Interactions do Discord assina cada chamada);
  • assinar e conferir DKIM Ed25519 de e-mails;
  • protocolos que combinam X25519, HKDF e AES-GCM, como o Noise usado pelo WhatsApp;
  • cifrar com autenticação (quem altera o texto cifrado é detectado).

Todas trabalham com TBytes.

X25519 (RFC 7748) · unit RALCurve25519

rotina
RALX25519(escalar, ponto) o valor compartilhado (32 bytes) do seu escalar privado com o u do ponto do outro lado
RALX25519Base(escalar) a chave pública do escalar (ponto base, u = 9)
RALX25519GenerateKeyPair(priv, pub) gera um par a partir de 32 bytes aleatórios
uses RALCurve25519, RALHKDF;

RALX25519GenerateKeyPair(PrivA, PubA);
RALX25519GenerateKeyPair(PrivB, PubB);
SegredoA := RALX25519(PrivA, PubB);
SegredoB := RALX25519(PrivB, PubA);   // igual a SegredoA
if IsZero(SegredoA) then              // ver "Limites"
  raise Exception.Create('ponto inválido');

Ed25519 (RFC 8032) · unit RALEd25519

rotina
RALEd25519PublicKey(semente) a chave pública (32 bytes) da semente (a chave privada, 32 bytes)
RALEd25519Sign(mensagem, semente) a assinatura (64 bytes)
RALEd25519Verify(mensagem, assinatura, chavePublica) True se a assinatura vale; recusa S >= L e pontos fora da curva
RALEd25519GenerateKeyPair(semente, pub) gera o par
uses RALEd25519;

// webhook: a chave pública, a assinatura e o carimbo vêm em hexa; o texto assinado é carimbo + corpo
if not RALEd25519Verify(Concat(Carimbo, Corpo), Assinatura, ChavePublica) then
  AResponse.StatusCode := 401;

HKDF (RFC 5869) · unit RALHKDF

TRALHKDFHash escolhe o hash: rhkSHA256 ou rhkSHA512.

rotina
RALHKDFExtract(hash, sal, material) o PRK; sal vazio vale uma sequência de zeros
RALHKDFExpand(hash, prk, info, tamanho) tamanho bytes (no máximo 255 vezes o tamanho do resumo)
RALHKDFDerive(hash, material, sal, info, tamanho) Extract e Expand juntos
Chave := RALHKDFDerive(rhkSHA256, SegredoA, Sal, TEncoding.UTF8.GetBytes('minha-app v1'), 32);

AES-GCM (NIST SP 800-38D) · unit RALAESGCM

rotina
RALAESGCMEncrypt(chave, iv, aad, texto) o texto cifrado seguido da etiqueta de 16 bytes; chave de 16, 24 ou 32 bytes
RALAESGCMDecrypt(chave, iv, aad, cifradoEtiqueta, texto) True e o texto, ou False e texto vazio quando a etiqueta não bate

O aad é o que só se autentica (cabeçalhos, por exemplo) e pode ser vazio. O IV recomendado tem 12 bytes e nunca pode se repetir com a mesma chave. A etiqueta é comparada em tempo constante.

uses RALAESGCM;

Cifrado := RALAESGCMEncrypt(Chave, IV, nil, TEncoding.UTF8.GetBytes('olá'));
if RALAESGCMDecrypt(Chave, IV, nil, Cifrado, Texto) then
  // Texto é o original; se alguém mexeu em Cifrado, o resultado é False

Limites conhecidos

  • O AES é por tabelas, e por isso não resiste a ataques de cache (timing) de quem roda código na mesma máquina. Serve para uma API em servidor próprio; não para código de terceiros executando ao lado do seu.
  • X25519 com ponto de ordem pequena devolve só zeros. O RAL não recusa por você: confira o resultado e abandone a troca se ele for todo zero (RFC 7748, seção 6.1).
  • Pascal puro é mais lento que o OpenSSL; para volume alto de dados, prefira a criptografia externa ou o motor com TLS.
  • Chave privada e semente devem vir de bytes aleatórios do sistema; GenerateKeyPair já faz isso.

Veja também

Começar

Servidor

MQTT 🚧

E-mail 🚧

Cliente

Motores

Avançado

Ajuda

🚧 = em desenvolvimento, pode mudar

Clone this wiki locally