Bibliotecas de Criptografia em Zig — Segurança e Performance

Bibliotecas de Criptografia em Zig — Segurança e Performance

A criptografia é uma das áreas onde o Zig demonstra vantagens únicas. O controle de memória, a ausência de comportamento indefinido e o modelo de execução determinístico tornam Zig uma escolha excelente para implementações criptográficas seguras. A biblioteca padrão do Zig inclui um módulo de criptografia abrangente e auditado, complementado por bibliotecas de terceiros para casos especializados.

std.crypto — A Biblioteca Padrão

O módulo std.crypto é impressionantemente completo para uma biblioteca padrão. Implementado inteiramente em Zig, sem dependências externas, ele oferece:

Funções de Hash

const std = @import("std");
const crypto = std.crypto;

pub fn main() !void {
    const dados = "Mensagem secreta";

    // SHA-256
    var sha256_hash: [32]u8 = undefined;
    crypto.hash.sha2.Sha256.hash(dados, &sha256_hash, .{});
    std.debug.print("SHA-256: {s}\n", .{std.fmt.fmtSliceHexLower(&sha256_hash)});

    // SHA-512
    var sha512_hash: [64]u8 = undefined;
    crypto.hash.sha2.Sha512.hash(dados, &sha512_hash, .{});

    // BLAKE2b
    var blake2_hash: [32]u8 = undefined;
    crypto.hash.Blake2b256.hash(dados, &blake2_hash, .{});

    // BLAKE3
    var blake3_hash: [32]u8 = undefined;
    crypto.hash.Blake3.hash(dados, &blake3_hash, .{});

    // SHA-3 (Keccak)
    var sha3_hash: [32]u8 = undefined;
    crypto.hash.sha3.Sha3_256.hash(dados, &sha3_hash, .{});
}

Hash Incremental

Para dados grandes ou streaming:

var hasher = crypto.hash.sha2.Sha256.init(.{});
hasher.update("parte 1 ");
hasher.update("parte 2 ");
hasher.update("parte 3");
var resultado: [32]u8 = undefined;
hasher.final(&resultado);

HMAC

const Hmac = crypto.auth.hmac.sha2.HmacSha256;

const chave = "minha-chave-secreta";
const mensagem = "dados para autenticar";

var mac: [Hmac.mac_length]u8 = undefined;
Hmac.create(&mac, mensagem, chave);

// Verificar HMAC
const valido = Hmac.verify(mensagem, mac, chave);

Cifras Simétricas

// AES-256-GCM (Authenticated Encryption)
const aes = crypto.aead.aes_gcm;

const chave: [32]u8 = ...; // 256 bits
const nonce: [12]u8 = ...; // 96 bits
const texto_plano = "Dados confidenciais";
const dados_adicionais = "metadados"; // AAD

var cifrado: [texto_plano.len]u8 = undefined;
var tag: [16]u8 = undefined;

// Cifrar
aes.Aes256Gcm.encrypt(
    &cifrado,
    &tag,
    texto_plano,
    dados_adicionais,
    nonce,
    chave,
);

// Decifrar
var decifrado: [texto_plano.len]u8 = undefined;
try aes.Aes256Gcm.decrypt(
    &decifrado,
    cifrado,
    tag,
    dados_adicionais,
    nonce,
    chave,
);

// ChaCha20-Poly1305
const chacha = crypto.aead.chacha_poly;
chacha.ChaCha20Poly1305.encrypt(
    &cifrado,
    &tag,
    texto_plano,
    dados_adicionais,
    nonce,
    chave,
);

Criptografia de Chave Pública

// Ed25519 (Assinaturas Digitais)
const Ed25519 = crypto.sign.Ed25519;

// Gerar par de chaves
const par_chaves = try Ed25519.KeyPair.create(null);

// Assinar mensagem
const assinatura = try par_chaves.sign("mensagem importante", null);

// Verificar assinatura
try Ed25519.verify(
    assinatura,
    "mensagem importante",
    par_chaves.public_key,
);

// X25519 (Diffie-Hellman)
const X25519 = crypto.dh.X25519;

const chave_privada_a = try X25519.KeyPair.create(null);
const chave_privada_b = try X25519.KeyPair.create(null);

// Derivar segredo compartilhado
const segredo_a = try X25519.scalarmult(
    chave_privada_a.secret_key,
    chave_privada_b.public_key,
);
const segredo_b = try X25519.scalarmult(
    chave_privada_b.secret_key,
    chave_privada_a.public_key,
);

// segredo_a == segredo_b (mesmo segredo compartilhado)

Derivação de Chaves

// Argon2 para hash de senhas
const argon2 = crypto.pwhash.argon2;

const senha = "senha_do_usuario";
const salt: [16]u8 = ...; // Gerado aleatoriamente

var hash_senha: [32]u8 = undefined;
try argon2.kdf(
    &hash_senha,
    senha,
    salt,
    .{
        .t = 3,         // iterações
        .m = 65536,     // memória em KB
        .p = 4,         // paralelismo
    },
);

// HKDF (HMAC-based Key Derivation Function)
const hkdf = crypto.kdf.hkdf;
const HkdfSha256 = hkdf.HkdfSha256;

const material_chave = "material-de-entrada";
const salt_hkdf: [32]u8 = ...; // Salt opcional
const info = "contexto-de-uso";

var chave_derivada: [32]u8 = undefined;
const prk = HkdfSha256.extract(&salt_hkdf, material_chave);
HkdfSha256.expand(&chave_derivada, prk, info);

Geração de Números Aleatórios

// CSPRNG (Cryptographically Secure PRNG)
var bytes_aleatorios: [32]u8 = undefined;
std.crypto.random.bytes(&bytes_aleatorios);

// Número aleatório em range
const numero = std.crypto.random.intRangeAtMost(u32, 1, 100);

TLS na Biblioteca Padrão

O Zig inclui uma implementação TLS 1.3 na biblioteca padrão:

const std = @import("std");
const tls = std.crypto.tls;

pub fn main() !void {
    const allocator = std.heap.page_allocator;

    // Conectar via TLS
    const stream = try std.net.tcpConnectToHost(allocator, "example.com", 443);
    defer stream.close();

    var tls_stream = try tls.client(stream, .{
        .host = "example.com",
    });
    defer tls_stream.close();

    // Enviar requisição HTTPS
    try tls_stream.writeAll("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n");

    // Ler resposta
    var buf: [4096]u8 = undefined;
    const n = try tls_stream.read(&buf);
    std.debug.print("{s}\n", .{buf[0..n]});
}

Bibliotecas de Terceiros

zig-bearssl

Bindings para BearSSL, uma implementação TLS minimalista e segura:

const bearssl = @import("zig-bearssl");

var ssl_ctx = try bearssl.SslClient.init(allocator);
defer ssl_ctx.deinit();

try ssl_ctx.connect(stream, "example.com");
try ssl_ctx.writeAll("GET / HTTP/1.1\r\n\r\n");

zig-openssl

Para projetos que necessitam compatibilidade com OpenSSL:

const openssl = @import("zig-openssl");

const ctx = try openssl.SslContext.init(.tls_client);
defer ctx.deinit();

const ssl = try ctx.newSsl();
try ssl.connect(fd);

Segurança de Implementação

As implementações criptográficas em Zig seguem boas práticas de segurança:

Tempo Constante

Operações de comparação em tempo constante evitam side-channel attacks:

// Comparação segura em tempo constante
const iguais = std.crypto.utils.timingSafeEql(u8, hash_esperado, hash_calculado);

// Zerar memória sensível
std.crypto.utils.secureZero(u8, &chave_privada);

Proteção de Memória

// Usar alocador que zera memória ao liberar
const secure_allocator = std.heap.SecureAllocator.init(std.heap.page_allocator);

var chave = try secure_allocator.alloc(u8, 32);
defer {
    std.crypto.utils.secureZero(u8, chave);
    secure_allocator.free(chave);
}

Boas Práticas

  1. Use algoritmos modernos: Prefira ChaCha20-Poly1305, Ed25519, BLAKE3 e Argon2
  2. Nunca reutilize nonces: Cada operação de cifra deve usar um nonce único
  3. Zere memória sensível: Use secureZero para limpar chaves e senhas da memória
  4. Use comparação em tempo constante: Para verificação de MACs e hashes
  5. Gere chaves com CSPRNG: Sempre use std.crypto.random para material criptográfico

Próximos Passos

Explore as bibliotecas de rede para comunicação segura, os frameworks web para APIs HTTPS, e as bibliotecas de serialização para formatos seguros de dados. Veja como fintechs usam criptografia Zig em produção. Para aprender mais, visite nossos tutoriais.

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.