Pular para conteúdo

Aula 11 – Criptografia na Prática com JavaScript 💻

O navegador também precisa cifrar dados — de senhas locais a comunicação ponta a ponta. Nesta aula vamos usar a Web Crypto API, nativa de todo navegador moderno e do Node.js.


📦 A Web Crypto API

Diferente do Python, o JavaScript não precisa instalar biblioteca nenhuma para operações criptográficas básicas — a crypto.subtle já vem embutida no navegador e no Node.js (via require('crypto').webcrypto).

Por que 'subtle'?

O nome é uma referência proposital: usar essa API de forma insegura é fácil e as consequências são "sutis" (subtle) — o nome é um lembrete para usar com cuidado e seguir as boas práticas.


#️⃣ Hash com crypto.subtle.digest

async function calcularHash(texto) {
    const encoder = new TextEncoder();
    const dados = encoder.encode(texto);
    const hashBuffer = await crypto.subtle.digest("SHA-256", dados);
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    return hashArray.map(b => b.toString(16).padStart(2, "0")).join("");
}

calcularHash("senha123").then(hash => console.log(hash));
// ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94

🔐 Criptografia Simétrica (AES-GCM) no Navegador

async function gerarChaveAES() {
    return await crypto.subtle.generateKey(
        { name: "AES-GCM", length: 256 },
        true,
        ["encrypt", "decrypt"]
    );
}

async function cifrar(chave, texto) {
    const iv = crypto.getRandomValues(new Uint8Array(12)); // IV aleatorio (Aula 04)
    const encoder = new TextEncoder();
    const cifrado = await crypto.subtle.encrypt(
        { name: "AES-GCM", iv },
        chave,
        encoder.encode(texto)
    );
    return { cifrado, iv };
}
graph LR
    A["Texto Claro"] --> B["generateKey AES-GCM 256"]
    B --> C["encrypt() com IV aleatorio"]
    C --> D["ArrayBuffer cifrado"]
    D --> E["decrypt() com a mesma chave + IV"]
    E --> A

Sempre gere um IV novo

Assim como vimos na Aula 04, reutilizar o mesmo IV com a mesma chave em AES-GCM compromete completamente a segurança da cifragem.


💻 Testando no Console do Navegador

$ # No console do navegador (F12) ou via Node.js $ node -e "crypto.subtle.digest('SHA-256', new TextEncoder().encode('teste')).then(h => console.log(Buffer.from(h).toString('hex')))" $ 4d967a...c91b3

📝 Exercícios de Fixação

  1. Básico: Por que a Web Crypto API não precisa de instalação, diferente da biblioteca Python da Aula 10?
  2. Básico: Escreva uma função que calcula o hash SHA-256 de uma senha digitada em um formulário HTML.
  3. Intermediário: Por que o IV é gerado com crypto.getRandomValues() e não com Math.random()?
  4. Intermediário: Complete o exemplo de AES-GCM com uma função decifrar() que reverte o processo de cifrar().
  5. Desafio: Pesquise a diferença entre crypto.getRandomValues() (criptograficamente seguro) e Math.random() (não seguro) — por que isso importa em segurança?

🚀 Mini-Projeto: Formulário com Hash no Cliente

Objetivo: Criar uma página HTML simples que calcula o hash SHA-256 de um texto digitado, em tempo real.

  1. Crie um input de texto e uma área para mostrar o resultado.
  2. A cada tecla digitada, calcule o hash SHA-256 do conteúdo atual usando crypto.subtle.digest.
  3. Exiba o hash resultante na tela, atualizado em tempo real.
  4. Bônus: adicione um botão para copiar o hash para a área de transferência.

Ir para Aula 12