Criptografia no Nível do Protocolo: Uma Abordagem Prática

Criptografia no Nível do Protocolo: Uma Abordagem Prática

Este artigo explora como implementar criptografia no nível do protocolo, focando em ferramentas e técnicas para proteger dados sensíveis. O autor discute o uso de 'crypt' e 'PayloadContext' em Rust, oferecendo uma visão sobre como gerenciar chaves e integrar a criptografia em fluxos de dados.

MundiX News·29 de maio de 2026·10 min de leitura·👁 17 views

Como organizar a criptografia no nível do protocolo? Na verdade, o tema não é simples e, talvez (na minha humilde opinião), seja exatamente o tema onde chegar a um compromisso quase nunca funciona. A menos que você simplesmente não transmita dados confidenciais.

Eu vou contar como a criptografia pode ser organizada no nível do protocolo e, em nenhum caso, vou tocar nas decisões de princípio que afetam a segurança (como transmitir, para onde transmitir, enviar ou armazenar dados confidenciais). Em outras palavras, estamos interessados no lado instrumental da questão.

Então, em brec, existem duas funcionalidades adicionais: crypt e PayloadContext. Se crypt é um recurso que precisa ser ativado, então o contexto é uma ferramenta embutida que não precisa necessariamente estar relacionada à criptografia, mas sem ela, organizar a criptografia será muito caro. Portanto, primeiro, brevemente, sobre o que é contexto e por que ele é necessário.

Então você declarou um protocolo simples:

rust
use brec::prelude::*;
use serde::{Deserialize, Serialize};
use std::io::{Error, ErrorKind};

#[block]
pub struct MetaBlock {
    pub request_id: u32,
    pub level: u8,
}

#[payload]
#[derive(Serialize, Deserialize)]
pub struct GreetingPayload {
    pub message: String,
}

Vamos declarar um contexto primitivo:

rust
#[payload(ctx)]
pub struct CounterContext {
    pub encoded: u32,
    pub decoded: u32,
}

impl CounterContext {
    fn extract<'a>(ctx: &'a mut crate::PayloadContext<'_>) -> std::io::Result<&'a mut Self> {
        match ctx {
            crate::PayloadContext::CounterContext(ctx) => Ok(ctx),
            crate::PayloadContext::None => Err(Error::new(
                ErrorKind::InvalidInput,
                "GreetingPayload expects PayloadContext::CounterContext",
            )),
        }
    }
    fn inc_encoded<'a>(ctx: &'a mut crate::PayloadContext<'_>) -> std::io::Result<()> {
        Self::extract(ctx)?.encoded += 1;
        Ok(())
    }
    fn inc_decoded<'a>(ctx: &'a mut crate::PayloadContext<'_>) -> std::io::Result<()> {
        Self::extract(ctx)?.decoded += 1;
        Ok(())
    }
}

Declaramos o contexto usando a macro payload(ctx), que diz ao brec - faça desta estrutura um contexto para todos os meus Payload. Sim, vale a pena mencionar aqui que o contexto é sobre Payload, mas não sobre Blocks.

Este "tipo" que surgiu do nada crate::PayloadContext será gerado pelo brec e incluirá nosso contexto como crate::PayloadContext::CounterContext(ctx), ou seja, você pode ter vários contextos diferentes.

Agora vale a pena prestar atenção em como declaramos um pouco acima GreetingPayload. Se você olhar para este artigo, verá a diferença: em vez de payload(bincode), especificamos apenas payload. Assim, dissemos ao brec - não aplique nenhum codec embutido (bincode é apenas uma referência ao codec), nós o implementamos por conta própria. Abaixo, ainda uso bincode dentro da implementação manual, mas para brec este já não é um codec embutido, mas apenas nosso próprio código.

Isso não é difícil.

rust
impl GreetingPayload {
    fn to_bytes(&self) -> std::io::Result<Vec<u8>> {
        bincode::serde::encode_to_vec(self, bincode::config::standard())
            .map_err(|err| Error::new(ErrorKind::InvalidData, err))
    }

    fn from_bytes(buf: &[u8]) -> std::io::Result<Self> {
        let (payload, _): (Self, usize) =
            bincode::serde::decode_from_slice(buf, bincode::config::standard())
                .map_err(|err| Error::new(ErrorKind::InvalidData, err))?;
        Ok(payload)
    }
}

impl PayloadEncode for GreetingPayload {
    fn encode(&self, ctx: &mut Self::Context<'_>) -> std::io::Result<Vec<u8>> {
        // Aumentamos o contador
        CounterContext::inc_encoded(ctx)?;
        // Codificamos nosso Payload
        self.to_bytes()
    }
}

impl PayloadEncodeReferred for GreetingPayload {
    fn encode(&self, _ctx: &mut Self::Context<'_>) -> std::io::Result<Option<&[u8]>> {
        // Isso pode ser implementado opcionalmente, se quisermos acesso "barato" aos nossos dados, o que
        // infelizmente nem sempre é possível
        Ok(None)
    }
}

impl PayloadDecode<GreetingPayload> for GreetingPayload {
    fn decode(buf: &[u8], ctx: &mut Self::Context<'_>) -> std::io::Result<GreetingPayload> {
        // Aumentamos o contador
        CounterContext::inc_decoded(ctx)?;
        // Decodificamos nosso Payload
        Self::from_bytes(buf)
    }
}

impl PayloadSize for GreetingPayload {
    fn size(&self, _ctx: &mut Self::Context<'_>) -> std::io::Result<u64> {
        // Implementamos a capacidade de descobrir o tamanho do Payload
        Ok(self.to_bytes()?.len() as u64)
    }
}

impl PayloadCrc for GreetingPayload {
    // Isso geralmente não precisa de sua própria implementação.
    // Default é suficiente
}

// Tudo está pronto, chamamos o gerador, que irá entregar
// - `Block`
// - `Payload`
// - `Packet`
// - `PayloadContext<'a>`
// - `PacketBufReader`
// - `Reader` / `Writer`
brec::generate!();

Eu acho que a partir deste código agora é claramente visível pelo que exatamente o contexto é responsável. Uma tarefa bastante trivial - compartilhar dados entre iterações de codificação/decodificação sem a necessidade de entidades globais. Na prática, esta tarefa trivial pode se transformar em uma enorme dor de cabeça, mas brec contém a solução já na caixa.

E aqui está um detalhe importante: o contexto não torna o estado "oculto" ou "global". Pelo contrário, ele força você a trazer explicitamente este estado para o ponto de leitura ou escrita. Isso é conveniente tanto para testes quanto para código produtor/consumidor: se o payload requer dados adicionais em tempo de execução, isso é visível diretamente na API, e não escondido em algum lugar em um singleton.

E o que a criptografia tem a ver com isso? E como armazenamos as chaves? Não é para manter globalmente na memória. É aqui que está a mesma "ponte" para o recurso crypt, que usa ativamente o contexto. Mas antes, vamos concordar - apenas o Payload é coberto pela criptografia. Esta é uma decisão consciente. Os Blocks permanecem sem criptografia sempre, como uma espécie de índice para uma busca de dados eficiente e rápida.

À primeira vista, isso pode parecer estranho: se você já está criptografando, por que não tudo de uma vez? Mas no protocolo, muitas vezes existem duas camadas diferentes de dados. Payload é o conteúdo, onde geralmente vivem informações confidenciais. Blocks são metadados que são convenientes para filtrar, rotear, pesquisar e ignorar pacotes rapidamente sem descompactação completa. Se você criptografar tudo de uma vez, cada um desses cenários exigirá primeiro a descriptografia do pacote, o que significa perder parte da utilidade prática da estrutura do protocolo. Portanto, a regra é simples: confidencial - no Payload, indexando e seguro para revelação - no Block.

Então, adicionamos o recurso e declaramos nosso protocolo novamente:

rust
[dependencies]
brec = { version = "...", features = ["bincode", "crypt"] }
serde = { version = "1.0", features = ["derive"] }
use brec::prelude::*;
use serde::{Deserialize, Serialize};

#[block]
pub struct MetaBlock {
    pub request_id: u32,
    pub level: u8,
}

#[payload(bincode, crypt)]
#[derive(Serialize, Deserialize)]
pub struct GreetingPayload {
    pub message: String,
}

brec::generate!();

Preste atenção em como agora declaramos GreetingPayload, ou seja, através de payload(bincode, crypt). Em primeiro lugar, indicamos o uso do codec embutido bincode, para não escrever o codec nós mesmos. Em segundo lugar, indicamos através de crypt que GreetingPayload requer criptografia. Ao mesmo tempo, a criptografia permanece seletiva: payloads sem crypt podem viver no mesmo protocolo e não exigir um contexto criptográfico.

Vamos ver como trabalhar com isso agora:

rust
const EXAMPLE_PUBLIC_KEY_PEM: &str = r#"-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----#";

const EXAMPLE_PRIVATE_KEY_PEM: &str = r#"-----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----#";

const KEY_ID: &[u8] = b"some_crypt_demo-key";

fn encode(
    message: String,
    request_id: u32,
    level: u8,
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
    // Criamos um pacote. Sem criptografia.
    let mut packet = Packet::new(
        vec![Block::MetaBlock(MetaBlock { request_id, level })],
        Some(Payload::GreetingPayload(GreetingPayload {
            message,
        })),
    );

    // Agora criamos um contexto que se tornou disponível para nós quando o recurso `crypt` foi ativado
    let mut encrypt = EncryptOptions::from_public_key_pem(EXAMPLE_PUBLIC_KEY_PEM)?
        .with_key_id(KEY_ID.to_vec());
    let mut encrypt_ctx = PayloadContext::Encrypt(&mut encrypt);

    // Gravamos o pacote, nosso GreetingPayload dentro do pacote será criptografado
    let mut bytes = Vec::new();
    packet.write_all(&mut bytes, &mut encrypt_ctx)?;

    Ok(bytes)
}

fn decode(
    bytes: Vec<u8>,
) -> Result<Packet, Box<dyn std::error::Error>> {
    use std::io::Cursor;

    // Criamos um contexto para decodificação
    let mut decrypt = DecryptOptions::from_private_key_pem(EXAMPLE_PRIVATE_KEY_PEM)?
        .with_expected_key_id(KEY_ID.to_vec());
    let mut decrypt_ctx = PayloadContext::Decrypt(&mut decrypt);

    // Lemos o pacote
    let mut source = Cursor::new(bytes.as_slice());
    let mut reader = PacketBufReader::new(&mut source);

    match reader.read(&mut decrypt_ctx)? {
        NextPacket::Found(packet) => Ok(packet),
        NextPacket::NotEnoughData(_) =>
            Err("unexpected read status: NotEnoughData".into()),
        NextPacket::NoData => Err("unexpected read status: NoData".into()),
        NextPacket::NotFound => Err("unexpected read status: NotFound".into()),
        NextPacket::Skipped => Err("unexpected read status: Skipped".into()),
    }
}

Claro, para a compacidade do exemplo, nossas chaves estão na memória, estão estaticamente. Mas esta é apenas uma demonstração. Na prática, você cria EncryptOptions / DecryptOptions, passa para o produtor / consumidor e não se lembra. Ou seja, o material-chave e a política de criptografia pertencem ao seu aplicativo, e PayloadContext apenas os entrega cuidadosamente ao codec de payload no momento da escrita ou leitura.

E aqui a pergunta surge honestamente: por que ativar crypt se você pode fazer um payload com o campo bytes: Vec<u8>, criptografar esses bytes em algum lugar do lado de fora e, em seguida, passá-los para brec? Este é um caminho absolutamente funcional. Além disso, em um grande número de sistemas, é assim que eles fazem: o protocolo vê apenas bytes, e a camada criptográfica vive separadamente. Se você já tem essa camada, ela foi testada, coberta por auditoria, sabe como fazer a rotação de chaves, versionamento, key id, envelope-format e erros, então a transição para o modelo brec + crypt não tem pré-requisitos óbvios.

O significado de crypt não é que a criptografia seja impossível sem ele. O significado é que brec assume a parte repetitiva e desagradável do protocolo: serializar o payload, embrulhá-lo em um único envelope criptográfico, gravar a versão, algoritmo, session id, RSA-wrapped session key, nonce, ciphertext/tag e key_id opcional, e na leitura, verificar tudo isso na direção oposta. Em outras palavras, crypt remove o contêiner caseiro ao redor de Vec<u8> do código do aplicativo. Você continua trabalhando com um GreetingPayload tipado, e não com um "saco de bytes" que você não deve esquecer de descriptografar, verificar, analisar e corresponder corretamente à chave.

Sim, qualquer recurso criptográfico embutido expande a superfície do código que deve estar correto. Esta não é uma magia gratuita. Mas a alternativa com bytes manuais também expande o campo para erros, mas já em cada aplicativo específico: alguém esquecerá o key id, alguém não colocará a versão do envelope, alguém reutilizará o session key de forma não óbvia, alguém misturará erros de decodificação e erros de descriptografia. Em brec, esse risco se concentra em um lugar pequeno e explícito, onde primitivas prontas são usadas (ChaCha20Poly1305 para o corpo do payload e RSA-OAEP-SHA256 para a session key), há um formato de envelope e um modelo de erro unificado. Portanto, a escolha aqui é pragmática: se você precisa de controle total ou já tem sua própria camada criptográfica - use Vec<u8> e o caminho manual. Mas se você precisa de criptografia como parte do protocolo brec, sem espalhar boilerplate pelo código produtor/consumidor, crypt oferece uma rota mais suave e verificável.

Não vou sobrecarregá-lo com detalhes técnicos e uma lista dos métodos e configurações suportados para EncryptOptions / DecryptOptions, há documentação para isso, mas, como sempre, peço que você compartilhe uma "estrela" no GitHub. Para você, é apenas um clique, e para mim - feedback e motivação para não abandonar o projeto, mas desenvolvê-lo ainda mais. Com antecedência, raios de bondade e luz para todos que não passarem por perto.

PS: toda vez que peço para marcar o projeto com uma estrela no GitHub, me sinto como um modelo onlyfuns) só que não há nada para mostrar além do código) Em geral, apoie, se não for difícil, se for difícil, então não precisa)

Obrigado.

🛡️⚡

Pare de pesquisar. Comece a hackear.

O MundiX é seu copiloto de pentest com IA: comandos exatos, análise de outputs e próximo passo na kill chain — em segundos.

Testar grátis por 7 dias →

Sem cartão para começar · Planos a partir de R$49/mês

📤 Compartilhar & Baixar

🧰 Ferramentas recomendadas

Divulgação: alguns links são patrocinados. Podemos receber comissão se você comprar — sem custo extra para você. Só indicamos o que faz sentido para a comunidade.

Aprendendo Kali Linux: Teste de segurança, pentest e hacking ético

Aprendendo Kali Linux: Teste de segurança, pentest e hacking ético

Com centenas de ferramentas pré-instaladas, a distribuição Kali Linux facilita o trabalho de os profissionais de segurança começarem a fazer testes de segurança rapidamente. No entanto, com mais de 600 ferramentas em seu arsenal, o Kali Linux também pode ser desafiador. A nova edição deste prático livro abrange as atualizações nas ferramentas e inclui uma melhor abordagem da análise forense e da engenharia reversa. Ric Messier, autor, não fica apenas no teste de segurança, mas também faz uma abordagem sobre a execução de análise forense, incluindo a análise em disco e na memória, assim como alguma análise básica de malware. • Explore as diversas ferramentas disponíveis no Kali Linux • Entenda o valor do teste de segurança e examine os tipos de teste disponíveis • Aprenda os aspectos básicos do pentest em todo o ciclo de vida do ataque • Instale o Kali Linux em vários sistemas, tanto físicos quanto virtuais • Descubra como usar diferentes ferramentas destinadas à segurança • Estruture um teste de segurança baseado nas ferramentas do Kali Linux • Estenda as ferramentas do Kali para criar técnicas de ataque avançadas • Use o Kali Linux para ajudar a criar relatórios quando o teste terminar “A abordagem concisa, clara e baseada na experiência adotada por Ric Messier para a introdução do Kali Linux e dos testes de cibersegurança é incomparável. Este livro é uma leitura excelente e acessível para iniciantes e um recurso valioso para qualquer pessoa.” —Alexander Arlt, Consultor sênior de segurança, Google

Ver na Amazon
Gshield 2 em 1 Hub Extensor Conector USB-C + USB-A e Adaptador de Rede Ethernet LAN RJ45 com 3 Entradas USB 3.0 até 5 Gbps em Liga de Alumínio para Computador e Notebook, Cinza

Gshield 2 em 1 Hub Extensor Conector USB-C + USB-A e Adaptador de Rede Ethernet LAN RJ45 com 3 Entradas USB 3.0 até 5 Gbps em Liga de Alumínio para Computador e Notebook, Cinza

Compatível com portas USB-C e USB-A, ideal para ampliar a conectividade de dispositivos como MacBook Pro e outros com portas USB-C. Inclui um adaptador USB-A extra, proporcionando uma conexão Ethernet estável e veloz de até 1 Gbps, perfeita para filmes, jogos online e videoconferências. Oferece três portas USB 3.0 com velocidades de transferência de até 5 Gbps, permitindo conectar mouse, teclado, discos rígidos e outros periféricos. Fabricado em alumínio durável, garantindo longa vida útil e resistência ao uso diário. Design compacto e leve, ideal para viagens de negócios e uso diário, facilitando o transporte e armazenamento. Funciona com Windows 10/8.1/8, Mac OS e Chrome OS, oferecendo versatilidade incomparável para diversas necessidades de conectividade. Assegura uma conectividade estável e rápida, perfeita para tarefas exigentes como transferência de dados, streaming e mais.

Ver na Amazon
Hacking APIs: Breaking Web Application Programming Interfaces

Hacking APIs: Breaking Web Application Programming Interfaces

Hacking APIs is a crash course on web API security testing that will prepare you to penetration-test APIs, reap high rewards on bug bounty programs, and make your own APIs more secure. You'll learn how REST and GraphQL APIs work in the wild and set up a streamlined API testing lab with Burp Suite and Postman. Then you'll master tools useful for reconnaissance, endpoint analysis, and fuzzing, such as Kiterunner and OWASP Amass. Next, you'll learn to perform common attacks, like those targeting an API's authentication mechanisms and the injection vulnerabilities commonly found in web applications. You'll also learn techniques for bypassing protections against these attacks. In the book's nine guided labs, which target intentionally vulnerable APIs, you'll practice: Enumerating APIs users and endpoints using fuzzing techniques Using Postman to discover an excessive data exposure vulnerability Performing a JSON Web Token attack against an API authentication process Combining multiple API attack techniques to perform a NoSQL injection Attacking a GraphQL API to uncover a broken object level authorization vulnerability

Ver oferta
Gray Hat Hacking: The Ethical Hacker's Handbook, Sixth Edition

Gray Hat Hacking: The Ethical Hacker's Handbook, Sixth Edition

Up-to-date strategies for thwarting the latest, most insidious network attacks This fully updated, industry-standard security resource shows, step by step, how to fortify computer networks by learning and applying effective ethical hacking techniques. Based on curricula developed by the authors at major security conferences and colleges, the book features actionable planning and analysis methods as well as practical steps for identifying and combating both targeted and opportunistic attacks. Gray Hat Hacking: The Ethical Hacker's Handbook, Sixth Edition clearly explains the enemy's devious weapons, skills, and tactics and offers field-tested remedies, case studies, and testing labs. You will get complete coverage of Internet of Things, mobile, and Cloud security along with penetration testing, malware analysis, and reverse engineering techniques. State-of-the-art malware, ransomware, and system exploits are thoroughly explained. Fully revised content includes 7 new chapters covering the latest threats Includes proof-of-concept code stored on the GitHub repository Authors train attendees at major security conferences, including RSA, Black Hat, Defcon, and B-Sides

Ver na Amazon
Bloqueador USB de privacidade de porta USB para PC, notebook, bloco de laptop,

Bloqueador USB de privacidade de porta USB para PC, notebook, bloco de laptop,

Proteção de privacidade aprimorada: protege o link de transmissão de dados para evitar roubo de informações, fornecendo proteção de segurança robusta que protege a privacidade do usuário durante transferências de arquivos e garante uma conexão segura para interações de dispositivos sem preocupações em vários ambientes Uso a longo prazo: a camada protetora resistente ao desgaste, combinada com um corpo de metal resistente, oferece gerenciamento de calor confiável e qualidade duradoura durante o uso diário Entrega eficiente de energia: a tecnologia de chip inteligente garante a identificação automática dos requisitos de energia, fornecendo carregamento eficiente alinhando-se com vários protocolos de carregamento rápido para maior conveniência Proteção contra sobrecarga: evitando riscos de sobrecarga, este bloqueador de dados USB protege a vida útil da bateria e garante um desempenho estável, mantendo um fluxo estável de energia para melhorar a longevidade do dispositivo de forma eficaz Prático de transportar: com atenção à portabilidade, este bloqueador de dados USB oferece um design compacto que é leve e fácil de transportar, melhorando a conveniência do usuário e operação eficiente

Ver na Amazon

📩 Newsletter MundiX

Receba novidades de cibersegurança + um checklist de pentest grátis. Sem spam.

Ao assinar você concorda em receber e-mails. Cancele quando quiser.