Criptografia é o ato de codificar dados em informações aparentemente sem sentido, para que pessoas não consigam ter acesso às informações que foram cifradas. Há vários usos para a criptografia em nosso dia-a-dia: proteger documentos secretos, transmitir informações confidenciais pela Internet ou por uma rede local, etc.

A técnica usada em Criptografia envolve pura e simples matemática. O sistema de criptografia usado atualmente é extremamente seguro. Especialistas estimam que para alguém conseguir quebrar uma criptografia usando chaves de 64 bits na base da tentativa e erro, levaria cerca de 100.000 anos usando um PC comum.

Mas porque é tão seguro? Simples, uma chave de 2 bits terá 4 combinações possíveis. Uma chave de 4 bits, terá 16 combinações possíveis e assim por diante. Agora, vejamos a grande diferença: uma chave de apenas 8 bits terá 65.356 combinações possíveis e, em uma chave de 32 bits existem mais de 4 bilhões de combinações, que para serem decifradas levariam mais de 2 meses (levando em conta 1000 tentativas por segundo, por parte do computador).

Neste artigo veremos como implementar um sistema de criptografia usando MD5. Implementaremos uma classe que criptografa os dados de uma senha usada em uma autenticação (login).

MD5

O MD5 (Message-Digest algorithm 5) é um algoritmo de hash de 128 bits unidirecional desenvolvido pela RSA Data Security, Inc., descrito na RFC 1321, usado por softwares com protocolo ponto-a-ponto (P2P), verificação de integridade e logins. Foi desenvolvido para suceder ao MD4 que tinha alguns problemas de segurança.

Por ser um algoritmo unidirecional, um hash MD5 não pode ser transformado novamente na password (ou texto) que lhe deu origem. O método de verificação é, então, feito pela comparação das duas hash (uma da base de dados, e a outra da tentativa de login). O MD5 também é usado para verificar a integridade de um ficheiro através, por exemplo, do programa md5sum, que cria a hash de um ficheiro. Isto pode-se tornar muito útil para downloads de ficheiros grandes, para programas P2P que constroem o ficheiro através de pedaços e estão sujeitos à corrupção de ficheiros.

O MD5 é de domínio público para uso em geral. A partir de uma mensagem de um tamanho qualquer, ele gera um valor hash de 128 bits; com este algoritmo, é computacionalmente impraticável descobrir duas mensagens que gerem o mesmo valor, bem como reproduzir uma mensagem a partir do seu digest. O algoritmo MD5 é utilizado como mecanismo de integridade em vários protocolos de padrão Internet (RFC1352, RFC1446, etc.), bem como pelo CERT e CIAC.

Se o MD5 não pode ser descriptografado, qual é então sua utilidade?

Message Digests são funções hash que geram código de tamanho fixo, em uma única direção, a partir de dados de tamanho arbitrário. Esses códigos hash são extremamente úteis para segurança de senhas. Como ele não pode ser descriptografado, o código hash precisa ser re-gerado e comparado com a seqüência disponível anteriormente. Se ambos se igualarem, o acesso é liberado.

A API Java implementa dois algoritmos de Message Digest: o MD5 e o SHA-1.

A API do Message Digest (java.security.MessageDigest)

Para que se possa gerar textos cripografados, é necessário seguir os seguintes passos.

  1. Obter uma instância do algoritmo a ser usado.
  2. Passar a informação que se deseja criptografar para o algoritmo.
  3. Efetuar a criptografia.

Para se obter uma instância de um algoritmo de criptografia Message Digest, utiliza-se o método getInstance() da classe MessageDigest.

Listagem 1: Método getInstance da classe MessageDigest

MessageDigest md = MessageDigest.getInstance(“MD5”);

Após a chamada a getInstance(), você possui uma referência a um objeto pronto para criptografar seus dados utilizando o algoritmo especificado. Neste caso o MD5.

Finalmente, para gerar a chave criptografada, você chama o método digest().

As assinaturas existentes são:

  1. byte[] digest();
  2. byte[] digest(byte[] input);
  3. int digest(byte[] buf, int offset, int len) throws DigestException;

Construindo uma classe para criptografar dados

Primeiramente vamos criar um método estático para geração do algoritmo de criptografia:

Listagem 2: Método para geração do algoritmo


private static MessageDigest md = null;
 
    static {
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        }
    }

Em seguida criamos um método estático para gerar a chave criptografada.

Listagem 3: Método para gerar a chave


private static char[] hexCodes(byte[] text) {
        char[] hexOutput = new char[text.length * 2];
        String hexString;
 
        for (int i = 0; i < text.length; i++) {
            hexString = "00" + Integer.toHexString(text[i]);
            hexString.toUpperCase().getChars(hexString.length() - 2,
                                    hexString.length(), hexOutput, i * 2);
        }
        return hexOutput;
}

Feito isto, criaremos agora um método público que receberá o texto a ser criptografado:

Listagem 4: Método para criptografar texto


public static String criptografar(String pwd) {
        if (md != null) {
            return new String(hexCodes(md.digest(pwd.getBytes())));
        }
        return null;
}

O código completo da classe é mostrado abaixo:

Listagem 5: Código completo da classe

 
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
 
public class Criptografia {
 
    private static MessageDigest md = null;
 
    static {
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        }
    }
 
  private static char[] hexCodes(byte[] text) {
        char[] hexOutput = new char[text.length * 2];
        String hexString;
 
        for (int i = 0; i < text.length; i++) {
            hexString = "00" + Integer.toHexString(text[i]);
            hexString.toUpperCase().getChars(hexString.length() - 2,
                                	hexString.length(), hexOutput, i * 2);
        }
        return hexOutput;
    }
 
public static String criptografar(String pwd) {
        if (md != null) {
            return new String(hexCodes(md.digest(pwd.getBytes())));
        }
        return null;
    }
}

Para fazer chamadas a esta classe, fazemos o seguinte:

Listagem 6: Utilizando a classe


public static void main(String[] args){
        String senha = " senhadeteste ";
        System.out.println(Criptografia.criptografar(senha));
}

A saída para o código acima será: 97D3B7B38E306F4A3AC787333A02E5DF.

Atenção

Prefira usar o JDK 1.4.2 ou superior. Versões anteriores do JDK possuem restrições para o uso de criptografia, portanto é melhor usar versões mais novas.

Referencias Bibliográficas

  • C. L. Lucchesi, Introdução à Criptografia Computacional, Editora Papirus/UNICAMP, 1986.
  • J. Franco e E. Kerr, Criptologia: Protegendo a Informaçãona Era da Informação, ConteXto, nº 6, mar. 1995.
  • Spyman, Introdução Manual Completo do hacker, Editora Book Express 3ª ed, 2000.