Implementar encriptación MD5 y SHA en Java

8 agosto, 2010 por Herman Barrantes Dejar una respuesta »

MD5 y SHA son algoritmos de encriptación muy comúnmente usados, en la actualidad se ha demostrado su vulnerabilidad, sin embargo aun siguen siendo utilizados para almacenar contraseñas y mantener cierto nivel de seguridad en las aplicaciones (y no guardar la clave como texto plano en un archivo o base de datos :oops: ), para más información puedes leer los artículos de Wikipedia sobre MD5 y SHA


Ejemplo de implementación en Java mediante la clase MessageDigest

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 *
 * @author Herman Alonso Barrates Víquez
 */
public class StringMD {

    //algoritmos
    public static String MD2 = "MD2";
    public static String MD5 = "MD5";
    public static String SHA1 = "SHA-1";
    public static String SHA256 = "SHA-256";
    public static String SHA384 = "SHA-384";
    public static String SHA512 = "SHA-512";

    /***
     * Convierte un arreglo de bytes a String usando valores hexadecimales
     * @param digest arreglo de bytes a convertir
     * @return String creado a partir de <code>digest</code>
     */
    private static String toHexadecimal(byte[] digest){
        String hash = "";
        for(byte aux : digest) {
            int b = aux & 0xff;
            if (Integer.toHexString(b).length() == 1) hash += "0";
            hash += Integer.toHexString(b);
        }
        return hash;
    }

    /***
     * Encripta un mensaje de texto mediante algoritmo de resumen de mensaje.
     * @param message texto a encriptar
     * @param algorithm algoritmo de encriptacion, puede ser: MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512
     * @return mensaje encriptado
     */
    public static String getStringMessageDigest(String message, String algorithm){
        byte[] digest = null;
        byte[] buffer = message.getBytes();
        try {
            MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
            messageDigest.reset();
            messageDigest.update(buffer);
            digest = messageDigest.digest();
        } catch (NoSuchAlgorithmException ex) {
            System.out.println("Error creando Digest");
        }
        return toHexadecimal(digest);
    }
}
Descargar: StringMD.java

Para usar:

public static void main(String[] args) {
        String mensaje = "Mensaje secreto";
        System.out.println("Mensaje = " + mensaje);
        System.out.println("MD2 = " + StringMD.getStringMessageDigest(mensaje, StringMD.MD2));
        System.out.println("MD5 = " + StringMD.getStringMessageDigest(mensaje, StringMD.MD5));
        System.out.println("SHA-1 = " + StringMD.getStringMessageDigest(mensaje, StringMD.SHA1));
        System.out.println("SHA-256 = " + StringMD.getStringMessageDigest(mensaje, StringMD.SHA256));
        System.out.println("SHA-384 = " + StringMD.getStringMessageDigest(mensaje, StringMD.SHA384));
        System.out.println("SHA-512 = " + StringMD.getStringMessageDigest(mensaje, StringMD.SHA512));
    }

Obtendrás como resultado:
Mensaje = Mensaje secreto
MD2 = 554979825cd15157599d93ba762e1950
MD5 = baac73e0d9e99bad6ea493b865aa42c3
SHA-1 = c8d319697747df1cbf48430affb45bff182e2bb8
SHA-256 = e2af6f7c7e00f98a80064626c9049c4fb0826c9d73d50db9b986af8cd5a2c5bc
SHA-384 = 1313c905fd957f8d979812203657b05949cbea7452a1aeb2e8159affb67805ecd6bb515d51ed34f12a62377d7ac35f7f
SHA-512 = d28a8ce7f3a0c2ccb639a6e3b29413f7b0b7b56afdc66824491f7049d27301b9722e3e2c5ae0005ef4be26f9ba4fadce3e48eabb790a8575e252b53b03cff998

Publicidad

11 comentarios

  1. Nancy dice:

    Muy buen ejemplo, sobre todo porque lo puedes hacer un bean, encapsularlo y solo utilizarlo, aunque me queda una duda, para hacer la inserción en la bd solo le envias la cadena ya encriptada, cierto?

  2. barrantesgerman dice:

    @Nancy
    Si, eso es correcto, normalmente la clase MessageDigest al utilizar el método digest() retorna un arreglo de bytes, en mi caso yo prefiero guardar en la base de datos la clave como un Varchar2 osea un String, por lo que añadí el método toHexadecimal() para hacer la conversión.

    estos algoritmos son solo de encriptación por lo que Java y hasta donde se ningún lenguaje tiene una clase o método para desencriptarlos

    lo que se hace normalmente es encriptar el campo de contraseña del login nuevamente y hacer una consulta donde se verifique que la clave que acabas de encriptar es igual a la que se encuentra encriptada en la base de dato.

  3. Nancy dice:

    Pues que bueno que pusiste el método toHexadecimal, porque es realmente útil.

    Según lo que leí en wikipedia, MD5 y SHA-1 son vulnerables a ataques, sobre todo MD5, pero SHA-2(SHA-256, 384 y 512) no lo son, de momento, y espero que se mantengan así por un buen rato, jaja.

    Muchas gracias por tu aporte, de hecho lo utilizaré para el login de mi aplicación.

  4. erodriguez_s dice:

    @barrantesgerman
    Que pasa si necesitas una nueva funcionalidad que sea recuperar contraseña, en donde debes enviar la contraseña original? Como se puede hacer en esos casos?

  5. barrantesgerman dice:

    @erodriguez_s
    MD5 y SHA son algoritmos de encriptación que originalmente fueron diseñados para solo hacer eso encriptar, como dije no existe ninguna funcionalidad para desencriptarlos, por lo que en tu caso MD5 y SHA no son de utilidad.

    Sin embargo Java tiene unas librerías dentro del JDK llamadas: javax.crypto y java.security las cuales cuentan con clases y algoritmos para encriptar y desencriptar todo tipo de contenido.

    Este fin de semana tratare de tomar algo de tiempo y haré una entrada sobre el tema y un ejemplo :grin:

  6. Genaro dice:

    @barrantesgerman
    Los algoritmos MD5 y SHA no son algoritmos de encriptación son algoritmos para la generación de claves, estos algoritmos pueden ser aplicados a diferentes tipos de documentos, información, etc. obteniendose un clave, el proposito de estos algoritmos es verificar si estos documentos son los originales o fueron alterados.

  7. barrantesgerman dice:

    @Genaro
    Ciertamente el termino Encriptar no es del todo correcto ya que MD5 se puede usar para otros propósitos, pero “generación de claves” es también incorrecto, como tu mismo dices y yo acabo de repetir se usa para múltiples propósitos que no tiene que ver con claves, de hecho tengo otro artículo donde lo uso para hacer CheckSum de archivos, el algoritmo resume los bytes del mensaje mediante un tipo de sumatoria para generar un valor único, básicamente es un tipo de hash.

    Yo entiendo el termino encriptar como conversión de los datos propios a un código privado e ininteligible para los demás. El error del título (Encriptar en MD5) radica en el hecho de que el código de MD5 no es privado, lo puedes obtener fácilmente y además, la encriptación no es el único propósito.

  8. Joxpg dice:

    Buenas muy buen apunte pero intento correrlo en Netbeans y sale un error en la linea 25
    for(byte aux:digest){

    Alguien me podria colarorar en JCreator Funciona bn pero lo necesito correr en Netbeans

  9. barrantesgerman dice:

    @Joxpg
    Ese tipo de for esta implementado en Java 6 (semejante a foreach), si tiene un problema con el es porque esta corriendo Java 5 o inferior, simplemente hazlo con un for normal.

    for(int i = 0; i < digest.lengh, i ){

    byte aux = digest[i];

  10. Germán Fernández dice:

    Eso esta bien … boi a implementarlo en mi codigo de seccione de JSP

Deja un comentario