viernes, octubre 01, 2010

Reversar MD5

Para encontrar la clave a partir de la cuál se generó el MD5 se utiliza un procedimiento que evalúa todas las posibles combinaciones de caracteres o letras de un tamaño determinado:

/**
* Construye recursivamente cadenas de un tamaño determinado para generarles
* su MD5 y compararlo con el MD5 objetivo.
* 
* @param alfabeto - Arreglo con los posibles caracteres que pueden formar claves
* @param objetivo - Cadena de caracteres con el MD5 conocido
* @param actual   - Subcadena de la posible clave previamente formada
* @param size     - Cantidad faltante de caracteres a completar en la posible clave
* @return Clave encontrada
*/
public static String buscarClave(char[] alfabeto, String objetivo, 
                                 String actual, int size) {
    // Cuando el tamaño es 0, la subcadena recibida es la clave candidata a evaluar
    if(size == 0 ) {
        String tmpOut = generarMD5(actual);
        if(tmpOut.equals(objetivo)) return actual;
        else return null;
    }
    // Si el tamaño no es 0, se le agrega a la subcadena candidata cada uno
    // de los caracteres del alfabeto y se llama recursivamente al mismo método.
    // Si se encontró la clave, se retorna, y si no, se evalúa el siguiente caracter.
    for(char caracter: alfabeto) {
        String clave = buscarClave(alfabeto, objetivo, actual+caracter, size-1);
        if(clave!=null) return clave;
    }
    // Si la clave no se pudo encontrar se retorna el valor nulo
    return null;
}


Para simplificar el proceso de búsqueda de claves de cualquier tamaño se crea un método similar al anterior que hace un ciclo para generar y evaluar cadenas de diferentes tamaños. En este método he involucrado código adicional para calcular el tiempo tardado en realizar la evaluación para cada uno de los tamaños:

public static String buscarClave(String alfabeto, String cadena) {
    char[] alfa = alfabeto.toCharArray();
    for(int i=1; i<20; i++) {
        System.out.printf("Evaluando claves de tamaño %2d -> ",i);
        long  t1 = System.currentTimeMillis();
        String clave = buscarClave(alfa, cadena, "", i);
        long  t2 = System.currentTimeMillis();
        double t = (t2-t1)/1000.0;
        System.out.printf("tiempo: %,10.3f segs %n", t);
        if(clave != null) return clave;
    }
    return null;
}

No hay comentarios.:

Publicar un comentario

Multiprocesamiento recursivo en JAVA 7

Una de las estrategias de diseño de algoritmos más comunes es la de "divide y vencerás", en la cual, un problema de tamaño relativ...