Column-level encryption: protegendo dados sensíveis
1. Introdução à Criptografia em Nível de Coluna
A criptografia em nível de coluna é uma técnica de segurança que permite proteger dados sensíveis armazenados em uma ou mais colunas específicas de uma tabela do banco de dados. Diferentemente da criptografia em nível de arquivo ou disco (at-rest), que protege todo o arquivo físico do banco, a criptografia de coluna oferece granularidade fina: apenas os dados que realmente necessitam de proteção são criptografados.
É crucial distinguir dois conceitos fundamentais:
- Criptografia em repouso (at-rest): protege os dados enquanto estão armazenados no disco, mas não impede que um usuário autorizado do banco leia os dados descriptografados em memória.
- Criptografia em trânsito (in-transit): protege os dados durante a transmissão entre cliente e servidor (ex.: TLS/SSL).
- Criptografia de coluna: atua no nível da aplicação ou do SGBD, garantindo que mesmo administradores do banco não possam ler os dados sem a chave correta.
Casos de uso típicos incluem números de CPF, números de cartões de crédito, senhas, dados de saúde (HIPAA), informações bancárias e qualquer dado classificado como pessoalmente identificável (PII) sob regulamentações como LGPD ou GDPR.
2. Abordagens de Implementação no SQL
Existem duas abordagens principais para implementar criptografia em nível de coluna:
Criptografia Nativa do SGBD
PostgreSQL com pgcrypto
-- Habilitar a extensão
CREATE EXTENSION IF NOT EXISTS pgcrypto;
-- Criar tabela com coluna criptografada
CREATE TABLE clientes (
id SERIAL PRIMARY KEY,
nome TEXT NOT NULL,
cpf BYTEA NOT NULL, -- Armazenará o CPF criptografado
email TEXT NOT NULL
);
-- Inserir dado criptografado com chave simétrica
INSERT INTO clientes (nome, cpf, email)
VALUES (
'João Silva',
pgp_sym_encrypt('123.456.789-00', 'minha_chave_secreta'),
'joao@email.com'
);
-- Consultar com descriptografia
SELECT nome, pgp_sym_decrypt(cpf, 'minha_chave_secreta') AS cpf_decifrado
FROM clientes;
SQL Server com ENCRYPTBYKEY
-- Criar chave mestra e certificado
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'SenhaForte123!';
CREATE CERTIFICATE CertificadoCPF WITH SUBJECT = 'Proteção CPF';
-- Criar chave simétrica
CREATE SYMMETRIC KEY ChaveCPF WITH ALGORITHM = AES_256
ENCRYPTION BY CERTIFICATE CertificadoCPF;
-- Abrir chave e criptografar
OPEN SYMMETRIC KEY ChaveCPF DECRYPTION BY CERTIFICATE CertificadoCPF;
INSERT INTO clientes (cpf_cripto)
VALUES (ENCRYPTBYKEY(KEY_GUID('ChaveCPF'), '123.456.789-00'));
-- Fechar chave
CLOSE SYMMETRIC KEY ChaveCPF;
Gerenciamento de Chaves
A segurança da criptografia de coluna depende diretamente do gerenciamento adequado das chaves. Recomenda-se:
- Chave mestra: protege as demais chaves e deve ser armazenada em hardware seguro (HSM) ou cofre de chaves.
- Chave por coluna: cada coluna sensível pode ter sua própria chave, limitando o impacto de um vazamento.
- Rotação periódica: as chaves devem ser trocadas regularmente, com procedimento de re-criptografia dos dados existentes.
3. Modelagem de Dados com Colunas Criptografadas
Escolha do Tipo de Dado
O tipo de dado para armazenar o resultado da criptografia depende do SGBD:
- BYTEA (PostgreSQL): ideal para dados binários, sem overhead de codificação.
- VARBINARY (SQL Server): similar ao BYTEA, nativo para dados binários.
- TEXT com Base64: alternativa para sistemas que não suportam binários nativamente, mas adiciona ~33% de overhead.
-- Exemplo com Base64 (MySQL)
CREATE TABLE clientes (
id INT PRIMARY KEY,
cpf_base64 TEXT NOT NULL
);
-- Inserir com codificação Base64
INSERT INTO clientes (cpf_base64)
VALUES (TO_BASE64(AES_ENCRYPT('123.456.789-00', 'chave_aes')));
Índices em Colunas Criptografadas
Colunas criptografadas não podem ser indexadas diretamente para buscas eficientes. A criptografia produz resultados diferentes mesmo para valores iguais (quando usa IV aleatório). Soluções:
- Hash determinístico: armazenar um hash SHA-256 do valor original em coluna separada para busca exata.
- Bloom filters: para verificações de existência com falso positivo controlado.
-- Tabela com hash para indexação
CREATE TABLE clientes (
id SERIAL PRIMARY KEY,
cpf BYTEA NOT NULL,
cpf_hash TEXT NOT NULL UNIQUE -- SHA-256 do CPF original
);
-- Inserir com hash
INSERT INTO clientes (cpf, cpf_hash)
VALUES (
pgp_sym_encrypt('123.456.789-00', 'chave'),
encode(digest('123.456.789-00', 'sha256'), 'hex')
);
-- Busca eficiente pelo hash
SELECT id, pgp_sym_decrypt(cpf, 'chave') AS cpf
FROM clientes
WHERE cpf_hash = encode(digest('123.456.789-00', 'sha256'), 'hex');
4. Operações de Inserção e Consulta
Inserção de Dados Criptografados
-- PostgreSQL: função customizada para facilitar inserções
CREATE OR REPLACE FUNCTION criptografa_cpf(p_cpf TEXT, p_chave TEXT)
RETURNS BYTEA AS $$
BEGIN
RETURN pgp_sym_encrypt(p_cpf, p_chave);
END;
$$ LANGUAGE plpgsql;
-- Uso simplificado
INSERT INTO clientes (nome, cpf)
VALUES ('Maria', criptografa_cpf('987.654.321-00', 'chave_mestra'));
Consultas com Descriptografia
-- Consulta segura: apenas usuários com permissão podem descriptografar
SELECT
nome,
pgp_sym_decrypt(cpf, 'chave_mestra') AS cpf_visivel
FROM clientes
WHERE id = 1;
-- Filtro por hash (sem descriptografar todos os registros)
SELECT * FROM clientes
WHERE cpf_hash = encode(digest('987.654.321-00', 'sha256'), 'hex');
Busca por Prefixo (via Hash Determinístico)
Para buscas parciais (ex.: "clientes cujo CPF começa com 123"), armazene hashes de prefixos:
-- Tabela auxiliar para prefixos
CREATE TABLE prefixos_cpf (
cliente_id INT REFERENCES clientes(id),
prefixo_3 TEXT, -- hash dos 3 primeiros dígitos
prefixo_6 TEXT -- hash dos 6 primeiros dígitos
);
-- Busca por prefixo
SELECT c.*
FROM clientes c
JOIN prefixos_cpf p ON c.id = p.cliente_id
WHERE p.prefixo_3 = encode(digest('123', 'sha256'), 'hex');
5. Controle de Acesso e Permissões
Restrição de Acesso às Funções de Criptografia
-- PostgreSQL: revogar acesso público às funções de criptografia
REVOKE EXECUTE ON FUNCTION pgp_sym_decrypt FROM PUBLIC;
-- Criar role específica para descriptografia
CREATE ROLE leitor_sensivel;
GRANT EXECUTE ON FUNCTION pgp_sym_decrypt TO leitor_sensivel;
-- Atribuir role apenas a usuários autorizados
GRANT leitor_sensivel TO analista_confiavel;
Views como Camada de Segurança
-- View que expõe apenas dados não sensíveis
CREATE VIEW clientes_publico AS
SELECT id, nome, email
FROM clientes;
-- View para usuários autorizados (com descriptografia)
CREATE VIEW clientes_completo AS
SELECT
id,
nome,
pgp_sym_decrypt(cpf, current_setting('app.chave_cpf')) AS cpf,
email
FROM clientes;
-- Conceder acesso apenas às views
GRANT SELECT ON clientes_publico TO public;
GRANT SELECT ON clientes_completo TO leitor_sensivel;
6. Performance e Boas Práticas
Overhead Computacional
A criptografia e descriptografia são operações computacionalmente intensivas. Para minimizar o impacto:
- Cache de chaves: carregue a chave uma vez por sessão, não por consulta.
- Descriptografia sob demanda: só descriptografe quando necessário.
-- Evitar descriptografia em massa sem necessidade
-- RUIM: descriptografa todos os registros
SELECT pgp_sym_decrypt(cpf, 'chave') FROM clientes;
-- BOM: filtra antes de descriptografar
SELECT pgp_sym_decrypt(cpf, 'chave')
FROM clientes
WHERE id = 123;
Estratégias Híbridas
Para sistemas críticos, considere criptografar apenas parte dos dados:
-- Criptografar apenas os 4 últimos dígitos do CPF
CREATE TABLE clientes_hibrido (
id SERIAL PRIMARY KEY,
cpf_prefixo TEXT, -- "123.456.789" (não sensível isoladamente)
cpf_digitos BYTEA -- "00" criptografado
);
7. Integração com Recursos Vizinhos
Row-Level Security (RLS) Combinado com Criptografia
-- PostgreSQL RLS: usuário só vê seus próprios dados
ALTER TABLE clientes ENABLE ROW LEVEL SECURITY;
CREATE POLICY cliente_policy ON clientes
USING (usuario_id = current_user_id());
Audit Logging Seguro
-- Log de tentativas de acesso sem expor dados
CREATE TABLE audit_log (
id SERIAL PRIMARY KEY,
usuario TEXT,
acao TEXT,
coluna_acessada TEXT,
timestamp TIMESTAMP DEFAULT NOW()
);
-- Trigger que registra acesso à coluna criptografada
CREATE OR REPLACE FUNCTION log_acesso_cpf()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO audit_log (usuario, acao, coluna_acessada)
VALUES (current_user, 'SELECT', 'clientes.cpf');
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
8. Considerações Finais e Próximos Passos
Backup e Point-in-Time Recovery
Backups de bancos com colunas criptografadas devem ser tratados com cuidado:
- A chave de criptografia não deve ser armazenada junto com o backup.
- Utilize serviços de gerenciamento de chaves (KMS) separados do banco.
- Para recovery point-in-time, garanta que a chave esteja disponível no momento da restauração.
Rotação de Chaves
Procedimento seguro para trocar a chave sem interrupção:
-- 1. Criar nova chave
-- 2. Adicionar nova coluna para armazenar dados com nova chave
ALTER TABLE clientes ADD COLUMN cpf_novo BYTEA;
-- 3. Migrar dados gradualmente (em lotes)
UPDATE clientes
SET cpf_novo = pgp_sym_encrypt(
pgp_sym_decrypt(cpf, 'chave_antiga'),
'chave_nova'
)
WHERE cpf_novo IS NULL
LIMIT 1000;
-- 4. Após migração completa, remover coluna antiga
ALTER TABLE clientes DROP COLUMN cpf;
ALTER TABLE clientes RENAME COLUMN cpf_novo TO cpf;
A criptografia em nível de coluna é uma camada essencial de defesa em profundidade, mas não substitui outras práticas de segurança como controle de acesso, auditoria e criptografia em repouso e trânsito. Para conformidade com padrões como PCI-DSS, HIPAA e LGPD, é frequentemente um requisito obrigatório.
Referências
- PostgreSQL pgcrypto Documentation — Documentação oficial da extensão pgcrypto para criptografia simétrica e assimétrica no PostgreSQL.
- SQL Server Column-Level Encryption — Guia completo da Microsoft sobre como criptografar colunas usando SQL Server.
- MySQL AES Encryption Functions — Documentação oficial das funções de criptografia AES no MySQL.
- NIST Guidelines for Encryption Key Management — Padrões do NIST para gerenciamento de chaves criptográficas, essencial para implementações seguras.
- PCI-DSS Encryption Requirements — Requisitos oficiais do PCI Security Standards Council para criptografia de dados de cartão de pagamento.
- LGPD e Proteção de Dados: Guia de Criptografia — Orientações da Autoridade Nacional de Proteção de Dados sobre técnicas de criptografia para conformidade com a LGPD.
- OWASP Cryptographic Storage Cheat Sheet — Guia de boas práticas do OWASP para armazenamento criptográfico seguro em aplicações.