Criptografia Simétrica (Symmetric Encryption)¶
A criptografia simétrica usa uma única chave secreta compartilhada tanto para criptografia quanto para descriptografia. É a forma mais eficiente de criptografia, tornando-se ideal para criptografar grandes quantidades de dados em repouso ou em trânsito quando a troca segura de chaves pode ser estabelecida previamente.
Fundamento Matemático¶
Operação Básica¶
Dado: - Texto plano $M$ (mensagem a ser criptografada) - Chave secreta $K$ - Função de criptografia $E_K(\cdot)$ - Função de descriptografia $D_K(\cdot)$
O processo de criptografia é: $$C = E_K(M)$$
O processo de descriptografia é: $$M = D_K(C)$$
Onde $C$ é o texto cifrado.
Requisito de Segurança¶
Para que um cifra seja seguro, ele deve satisfazer: $$D_K(E_K(M)) = M \quad \text{para todo } M$$
E idealmente: $$D_{K'}(E_K(M)) \neq M \quad \text{para qualquer } K' \neq K$$
AES (Advanced Encryption Standard)¶
O AES é o algoritmo de criptografia simétrica mais amplamente usado hoje, adotado pelo NIST em 2001. Ele substituiu o antigo Data Encryption Standard (DES).
Tamanhos de Chave¶
| Variante | Tamanho do Bloco | Tamanho da Chave | Nível de Segurança |
|---|---|---|---|
| AES-128 | 128 bits | 128 bits | ~128-bit security |
| AES-192 | 128 bits | 192 bits | ~192-bit security |
| AES-256 | 128 bits | 256 bits | ~256-bit security |
Estrutura: Rede de Substituição-Permutação (SPN)¶
O AES opera em uma matriz de estado 4×4 de bytes e realiza as seguintes operações em cada rodada:
1. Rodada Inicial¶
- AddRoundKey: XOR o estado com a chave da rodada
2. Rodadas Principais (9 para AES-128, 11 para AES-256)¶
Cada rodada principal consiste de: - SubBytes: Substituição não-linear usando S-box - ShiftRows: Deslocamento cíclico das linhas na matriz de estado - MixColumns: Mistura linear das colunas - AddRoundKey: XOR com chave da rodada
3. Rodada Final¶
Mesma que as rodadas principais, mas sem MixColumns
Representação da Matriz de Estado do AES¶
Estado (bloco de 128 bits):
+--------+--------+--------+--------+
| s00 | s01 | s02 | s03 |
+--------+--------+--------+--------+
| s10 | s11 | s12 | s13 |
+--------+--------+--------+--------+
| s20 | s21 | s22 | s23 |
+--------+--------+--------+--------+
| s30 | s31 | s32 | s33 |
+--------+--------+--------+--------+
Cada byte de estado é 8 bits, total = 4 × 4 × 8 = 128 bits
S-Box (Caixa de Substituição)¶
A S-box fornece não-linearidade. Ela é derivada do inverso multiplicativo em GF(2^8):
$$S[x] = \text{Inverse}(x)^{-1} \oplus \text{Constante}$$
Onde a constante é 0x63 para propriedades de uniformidade diferencial.
Implementação em Java¶
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import java.security.SecureRandom;
import java.util.Base64;
public class CriptografiaSimetrica {
private static final String ALGORITMO = "AES/GCM/NoPadding";
private static final int IV_LENGTH = 12; // 96 bits para GCM
/**
* Gera uma nova chave AES-256.
*/
public static SecretKey gerarChave() throws Exception {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256); // Tamanho da chave em bits
return keyGen.generateKey();
}
/**
* Criptografa dados usando AES-GCM.
* @param textoPlano Os dados a serem criptografados
* @param chave A chave secreta
* @return Texto cifrado codificado em Base64 com IV prependido
*/
public static String criptografar(String textoPlano, SecretKey chave) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITMO);
// Gerar vetor de inicialização (IV) aleatório
byte[] iv = new byte[IV_LENGTH];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(iv);
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.ENCRYPT_MODE, chave, parameterSpec);
byte[] textoCifrado = cipher.doFinal(textoPlano.getBytes());
// Combinar IV e texto cifrado, depois codificar
byte[] combinado = new byte[iv.length + textoCifrado.length];
System.arraycopy(iv, 0, combinado, 0, iv.length);
System.arraycopy(textoCifrado, 0, combinado, iv.length, textoCifrado.length);
return Base64.getEncoder().encodeToString(combinado);
}
/**
* Descriptografa dados criptografados com AES-GCM.
*/
public static String descriptografar(String textoCifradoCodificado, SecretKey chave) throws Exception {
// Decodificar e separar IV do texto cifrado
byte[] combinado = Base64.getDecoder().decode(textoCifradoCodificado);
byte[] iv = new byte[IV_LENGTH];
byte[] bytesTextoCifrado = new byte[combinado.length - IV_LENGTH];
System.arraycopy(combinado, 0, iv, 0, IV_LENGTH);
System.arraycopy(combinado, IV_LENGTH, bytesTextoCifrado, 0, bytesTextoCifrado.length);
Cipher cipher = Cipher.getInstance(ALGORITMO);
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.DECRYPT_MODE, chave, parameterSpec);
byte[] bytesTextoPlano = cipher.doFinal(bytesTextoCifrado);
return new String(bytesTextoPlano);
}
public static void main(String[] args) throws Exception {
SecretKey chave = gerarChave();
String mensagem = "Mensagem secreta para criptografar";
// Criptografar
String criptografado = criptografar(mensagem, chave);
System.out.println("Criptografado: " + criptografado);
// Descriptografar
String descriptografado = descriptografar(criptografado, chave);
System.out.println("Descriptografado: " + descriptografado);
}
}
Usando a Classe Cipher do Java (Exemplo Simples)¶
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.util.Base64;
public class AESSimples {
public static String criptografar(String textoPlano, byte[] bytesChave) throws Exception {
SecretKeySpec keySpec = new SecretKeySpec(bytesChave, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
return Base64.getEncoder().encodeToString(cipher.doFinal(textoPlano.getBytes()));
}
public static String descriptografar(String textoCifradoCodificado, byte[] bytesChave) throws Exception {
SecretKeySpec keySpec = new SecretKeySpec(bytesChave, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, keySpec);
return new String(cipher.doFinal(Base64.getDecoder().decode(textoCifradoCodificado)));
}
public static byte[] gerarChave() throws Exception {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
SecretKey chave = keyGen.generateKey();
return chave.getEncoded();
}
}
Modos de Operação¶
ECB (Electronic Codebook) - NÃO RECOMENDADO¶
Cada bloco é criptografado independentemente. Blocos de texto plano idênticos produzem blocos de texto cifrado idênticos, vazando padrões:
CBC (Cipher Block Chaining)¶
Cada bloco de texto plano é XORado com o bloco de texto cifrado anterior antes da criptografia. Requer um vetor de inicialização (IV):
$$C_i = E_K(P_i \oplus C_{i-1})$$
Com $C_0 = IV$.
Segurança: Esconde padrões, mas erros propagam para o bloco seguinte.
GCM (Galois/Counter Mode) - RECOMENDADO¶
Fornece tanto confidencialidade quanto autenticação: - Usa modo Counter para criptografia - Fornece criptografia autenticada via multiplicação de campo Galois - Escolha mais segura moderna
Gerenciamento de Chaves¶
Funções de Derivação de Chave (KDFs)¶
Convertem senhas ou chaves de baixa entropia em chaves criptográficas:
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
public class DerivacaoChave {
public static byte[] derivarChave(char[] senha, byte[] salt) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
PBEKeySpec spec = new PBEKeySpec(senha, salt, 65536, 256); // 65k iterações
return factory.generateSecret(spec).getEncoded();
}
}
Melhores Práticas para Gerenciamento de Chaves¶
- Nunca codifique chaves no código fonte
- Use armazenamento seguro: HashiCorp Vault, AWS KMS, Azure Key Vault
- Rode chaves regularmente
- Use chaves diferentes para diferentes propósitos (criptografia vs assinatura)
- Implemente controles de acesso ao armazenamento de chaves
Análise de Segurança¶
Pontos Fortes e Fracos¶
| Aspecto | Avaliação |
|---|---|
| Velocidade | Muito rápida, adequada para grandes dados |
| Tamanho da Chave | 128-256 bits (segurança computacional) |
| Implementação | Padrões bem avaliados (AES) |
| Vulnerabilidade | Requer troca segura de chaves |
Por que o AES é Seguro¶
- Espaço de Chave Grande: $2^{256}$ chaves possíveis para AES-256
- Resistência a Ataques Conhecidos: Nenhum ataque prático mais rápido que força bruta
- Padronização: Análise extensiva por criptógrafos em todo o mundo
- Aceleração de Hardware: Disponível na maioria dos processadores modernos
DES está Obsoleto¶
O antigo Data Encryption Standard (DES) usa apenas chaves de 56 bits: - Espaço de chave: $2^{56} \approx 7,2 \times 10^{16}$ combinações - Quebrado desde os anos 1990 - Nunca use DES para novas aplicações
Comparação com Criptografia Assimétrica¶
| Característica | Simétrica (AES) | Assimétrica (RSA/ECC) |
|---|---|---|
| Tamanho da Chave | 128-256 bits | 2048-4096 bits |
| Velocidade | Muito rápida (~$10^3\times$ mais rápido) | Mais lento |
| Uso | Criptografar dados | Troca de chaves, assinaturas |
| Troca de Chave | Requer segredo pré-compartilhado | Troca segura embutida |
Criptografia Híbrida (TLS/SSL)¶
Protocolos modernos combinam ambas as abordagens:
1. Cliente e Servidor realizam troca de chaves Diffie-Hellman
2. Estabelecer chave simétrica compartilhada
3. Usar AES para criptografar a transferência real de dados
4. Assinar com RSA/ECC para autenticação
Isso fornece a eficiência da criptografia simétrica com a troca segura de chaves da criptografia assimétrica.
Referências¶
- NIST FIPS 197: Advanced Encryption Standard (AES)
- Daemen, J., & Rijmen, V. (2002). The Design of Rijndael. Springer.
- Ferguson, N., Schneier, B., & Kohno, T. (2010). Cryptographic Engineering. MIT Press.
- Stinson, D. R. (2005). Cryptography: Theory and Practice. CRC Press.