Back-End

1 ago, 2011

Criptografia segura no PHP

Publicidade

Se você é
um desenvolvedor web profissional, segurança é um aspecto importante do seu
trabalho. Se você estiver planejando armazenar dados críticos ou sensíveis em
sua aplicação web, como senhas, cartões de credito etc, você deveria usar uma criptografia segura (strong
cryptography) para proteger esses dados.

O que é criptografia segura?

Criptografia seguraé o uso de sistemas ou componentes que são considerados altamente
resistentes à criptoanálise, o estudo de métodos para decifrar códigos.

Teoricamente falando, se criptografarmos e
armazenarmos dados confidenciais em um banco de dados, arquivo, ou qualquer outra
coisa, um atacante malicioso não será capaz de descriptografá-los sem saber a
chave, uma sequência de números usada para criptografar ou para descriptografar
dados. Como podemos provar que o atacante não será capaz de descriptografar os
dados?

Infelizmente, a resposta correta é que não
podemos ter certeza. Podemos apenas ter um bom nível de segurança usando
algoritmos bem testados de criptografia (criptografia segura).

Por
exemplo, a cifra ENIGMA, usada na Segunda guerra Mundial
como um sistema para criptografar a comunicação entre soldados alemães, hoje
não é considerada criptograficamente forte. O DES, um algoritmo padrão do FIST em 1976, que infelizmente ainda é utilizado em muitos sistemas, não é
considerado criptograficamente forte mais. Em 1998, a Electronic Frontier
Foundation (EFF) construiu uma máquina, o EFF DES cracker, para executar uma pesquisa por força bruta pela key space (o conjunto das possíveis senhas) da encriptação cipher – ou seja, para descriptografar uma
mensagem criptografada tentando cada chave possível. O objetivo é
provar que a chave DES não é mais segura. Essa máquina era capaz de encontrar a
chave de uma mensagem criptografada em menos de um dia, e estamos falando de
1998!

Atualmente, alguns dos
algoritmos que podem ser considerados criptograficamente fortes sao:
Blowfish, Twofish, Advanced
Encryption Standard (AES, Rijndael), 3DES, Serpent, RSA etc. É importante
dizer que a segurança de qualquer algoritmo é relacionada à força e ao tamanho
da chave, e iremos falar desse ponto a seguir.

Por que
devemos usar criptografia segura?

Muitos
desenvolvedores, quando têm a necessidade de criptografar alguma informação,
tentam implementar suas cifras pessoas usando diferentes abordagens. Na
internet, você consegue encontrar várias implementações de cifras domésticas no
PHP.

Eu
desencorajo fortemente o uso dessas cifras, e vou dizer por quê. Criar uma cifra
segura é algo bastante complicado e, se você não for um expert, eu diria que é
uma tarefa praticamente impossível. Além disso, estamos falando de criptografia segura,
o que significa que mesmo se você for capaz de criar uma nova cifra, você
precisa de tempo para provar que ela é segura, compartilhando a implementação
do algoritmo na comunidade open source (se você estiver pensando que a
segurança da sua cifra está relacionada com a política de não compartilhar seus
detalhes, por favor continue a ler este artigo).

Criptografia segura no PHP

O PHP oferece
diferentes implementações dos algoritmos de criptografia mais importantes. Em
particular, o PHP tem as extensões de criptografia a seguir:

  • Hash
  • mcrypt
  • OpenSSL

A
extensão Hash não precisa de bibliotecas externas e é acionada por
padrão no PHP 5.1.2. Essa extensão substitui a antiga extensão mhash. Com essa
extensão, você pode gerar hashes ou HMAC (Hash-based Message Authentication
Code). Ela suporta os algoritmos de geração hash mais comuns usados na
criptografia segura. Se você quiser saber quais algoritmos são suportados pelo
seu ambiente PHP, pode utilizar a função hash_algos(), que te dá uma lista
de todos os algoritmos suportados. Para mais informações sobre essa extensão,
veja o manual PHP aqui.

A
extensão mcrypt é uma interface para a biblioteca mcrypt, que suporta
uma grande variedade de blocos de algoritmos, como DES, 3DES, Blowfish
(default), 3-WAY, SAFER-SK64, SAFER-SK128, TWOFISH, TEA, RC2 e GOST nos métodos de encriptação CBC,
OFB, CFB e ECB. Essa extensão é a mais utilizada para criptografar
dados usando cifras simétricas. Para mais informações sobre ela extensão, veja
o manual PHP aqui.

A
extensão OpenSSL usa as funções do OpenSSL
project
para
geração e verificação de assinaturas e para lacrar (criptografar) e abrir
(descriptografar) dados. Você pode utilizar o OpenSSL para proteger dados
usando a criptografia pública de chaves com o algoritmo RSA. Para mais
informações sobre essa extensão, veja o manual PHP aqui.

Melhores práticas no PHP

Até agora,
discutimos os aspectos gerais da criptografia segura. Agora eu gostaria de te
falar quais são as melhores práticas em como usar a criptografia segura no PHP.
Aqui você pode encontrar algumas das minhas recomendações:

  • Use algoritmos
    padrão

Sempre use um algoritmo padrão para criptografar seus dados. Não tente
implementar sua cifra doméstica, você irá gastar muito tempo e energia sem
conseguir obter uma segurança real. Minha sugestão é usar os melhores algoritmos
disponíveis. Exemplos de algoritmos criptograficamente sólidos são:

– algoritmos de chave simétrica: AES, que é um padrão FIST 197
desde 2001;
– algoritmos de chaves públicas: RSA, um algoritmo padrão da industria utilizado em
muitos produtos;
– Funções Hash: SHA-x, em que x pode ser 1,256,384, e
512. SHA é um padrão NIST.

  • Espaço
    da chave

Quando falamos em segurança de uma cifra, o espaço chave é um dos parâmetros
mais importantes. Se nenhum design sólido explícito é dado pela cifra, a força
do design é igual ao tamanho da chave. Por exemplo, a cifra DES usa uma chave
de 56 bits, o que significa que o espaço da chave é de 2^56. Estes números
parecem imensos, mas computadores modernos podem suportá-los, e o EFF prova isso com o cracker DES. Então o espaço da chave é muito importante. Para cifras
simétricas, eu diria que 128 bits é o tamanho mínimo para uma chave de
criptografia forte. Com relação à criptografia de chaves públicas, os experts
recomendam um tamanho mínimo de 2048 bits se quisermos proteger
nossos dados por 20 anos.

  • Princípio de Kerchoof

Auguste Kerckhoffs foi um linguista alemão e criptógrafo do Higher Commercial
Studies em Paris no final do século 19. Ele escreveu, em um artigo famoso do “le
Journal des Sciences Militaires”, a seguinte frase, que é considerada o máximo
na criptografia moderna:

Um sistema de criptografia deve ser seguro
mesmo se tudo que disser respeito ao sistema, exceto a chave, seja de
conhecimento público.

Usando a
interpretação da Shannon, “O inimigo
conhece o sistema”. Na minha opinião, no mundo do software, você somente
tem segurança com o uso de algoritmos open source. Se o código-fonte foi
testado por milhares de pessoas ao redor do mundo, a probabilidade de encontrar
um bug de segurança e consequentemente de consertá-lo é mais alta usando um
software open source do que comparada à chance do uso de um software proprietário.

  • Não use rand() ou mt_rand()

Até para este ponto, não tente implementar seu gerador aleatório. Você não pode
implementar um gerador de números aleatório seguro usando a função rand() no
PHP. Essa função usa a biblioteca libc para gerar números pesudoaleatórios
que não são seguros para aplicativos de criptografia. Ela gera números
aleatórios usando um método aditivo linear de feedback, com um período curto,
que é previsível. Até a função mt_rand() não é segura do ponto de vista da
criptografia. Ela uso o algoritmo Mersenne Twister
para gerar números pseudoaleatórios. Essa função é melhor que a rand(), porque é mais rápida e produz números
pseudoaleatórios com um período maior, mas ainda é um algoritmo determinista,
então também é previsível. Para gerar um número aleatório criptograficamente
forte no PHP, você tem que usar a função openssl_random_pseudo_bytes() da
biblioteca OpenSSL. Essa função está
disponível a partir do PHP 5.3. Se você estiver usando uma versão antiga do PHP, pode usar esta implementação:

function secure_rand($length) {
if(function_exists('openssl_random_pseudo_bytes')) {
$rnd = openssl_random_pseudo_bytes($length, $strong);
if($strong === TRUE)
return $rnd;
}
for ($i=0;$i<$length;$i++) {
$sha= sha1(mt_rand());
$char= mt_rand(0,30);
$rnd.= chr(hexdec($sha[$char].$sha[$char+1]));
}
return $rnd;
}

Nessa
implementação, eu encriptei os outputs da mt_rand() para hash. Esse método aumenta a
segurança do Mersenne Twister, mas não tem o mesmo nível de segurança da
implementação OpenSSL.

  • Use
    um valor salt em funções hash

Se você estiver usando uma função hash para proteger os dados, como por exemplo
uma senha, concatene os dados com um valor randômico (salt) antes de gerar o
hash. Um salt randômico irá proteger seus dados de Dictionary attacks.

  • Tamanho
    e força de senhas

Não dê a possibilidade para os usuários da sua aplicação web de escolherem senhas
bobas e pequenas. Você deve sempre usar uma senha com no mínimo 8 caracteres
misturados com números e letras. Você pode usar a biblioteca CrackLib para testar a “força” de uma senha.

  • Não use senhas com texto puro como chave para encriptar

Uma boa prática na criptografia, usando cifras simétricas, é usar um valor
hashed como chave de uma cifra. Esse método aumenta a segurança dos dados
criptografados ao adicionar maior aleatoriedade. Isso significa que se você
quiser gerar uma boa chave para a cifra, você deve usar o hash da senha e
usá-lo como a chave do seu algoritmo de criptografia.

  • Use
    Base64 para codificar dados criptografados

Se você precisar migrar dados criptografados entre sistemas diferentes, como transmitir dados pela internet, é recomendado codificar os dados em Base64.
No PHP, você pode usar as funções base64_encode() e base64_decode(). Essa
codificação irá garantir que seus dados sejam armazenados corretamente,
independentemente do sistema de codificação utilizado no seu ambiente.

É claro
que essas são apenas sugestões gerais, e os pontos relacionados ao uso correto
da criptografia são mais do isso. Se você estiver interessado em
criptografia aplicada, eu fortemente recomendo ler os livros de Bruce
Schneier
: Applied Cryptography, Practical Cryptography, e Cryptography Engineering.

?

Texto original disponível em http://www.zimuel.it/blog/2011/01/strong-cryptography-in-php/