Implementar threads com classe

Buenas, estou fazendo ainda meu trabalho para quebrar senhas com MD5. Queria usar threads estendendo uma classe thread, Neste código fazendo com que cada thread percorra uma parte do meu dicionário (dictAll), e não sei nem como começar. Alguém por favor poderia me dar uma luz?

código:

package testemd5;

import br.com.senacrs.util.MD5;

public class TesteMD5 {

    @SuppressWarnings("empty-statement")
    public static void main(String[] args) {
        char dictAll[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
            'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
            'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
            'W', 'V', 'X', 'Y', 'Z', '!', '@', '#', '$', '%', '&', '*', '(', ')', '_', '-',
            '+', '=', '[', ']', '{', '}', '?', '/', '|', '>', '<', '.', '\\'};

        String dicthash[] = {"13240457817d091164402b9604824b67", "5438364b0199c0004432ac04dae29525",
"2271dc8fa2a6ff3b4c23180a66c480dc", "19d6ebafc1e11bea79fb2b85aa760ad9", "f3f3aa37990860260b2e6ceeaf672837",
"dcaff46aec8f457fa874d0b7a04960be", "f21ee05fa5d24c7de11e4aca9700aa8f", "827ccb0eea8a706c4c34a16891f84e7b",
"9605eb53e0da2675998ad751baf255ce", "58396401112fa9245099fff81ba63dec", "972c16f442eba60469680bf869dd6a89",
"50e318711a43cc8e965d90337f49deb8", "fe60293345d3e4f675441f1c4424ed4e", "d79096188b670c2f81b7001f73801117",
"48a58da106a36dd10852b229dfdc2088", "36510ae837f23c4da6e541a3e8edafb8", "9d495d6a637e83e277de834c2b31a8a1",
"54d9d99fad304a6d0329fc1fb6bdb517", "dfa8327f5bfa4c672a04f9b38e348a70", "70d06803ce18c714944dac18cd58f292",
"7a32b47d202ac6f583bbd9c42a0961ef", "69e80cd4d08679e2739f801516bfb170", "6cfe61694ee1bb13ae719d47c2f80b7a",
"e2ba49209f8ce01f1025d5f14400bf5b",};

        System.out.println("Seja Bem Vindo!");

        char palavra2[] = new char[5];

        long timeI = System.currentTimeMillis();
        for (int k = 0; k < dictAll.length; k++) {
            palavra2[4] = dictAll[k];
            for (int f = 0; f < dictAll.length; f++) {
                palavra2[3] = dictAll[f];
                for (int b = 0; b < dictAll.length; b++) {
                    palavra2[2] = dictAll[b];
                    for (int j = 0; j < dictAll.length; j++) {
                        palavra2[0] = dictAll[j];
                        for (int i = 0; i < dictAll.length; i++) {
                            palavra2[1] = dictAll[i];
                            String hash = MD5.gerarMD5(String.valueOf(palavra2));
                            //System.out.println("VALOR -> " + String.valueOf(palavra2));
                            //System.out.println("HASH: " + hash);

                            for (int h = 0; h < dicthash.length; h++) {
                                if (hash.equalsIgnoreCase(dicthash[h])) {
                                    long total_quebra = ((System.currentTimeMillis() - timeI) / 1000);
                                    System.out.println("SENHA QUEBRADA! EM: " + total_quebra + " segundos");
                                    System.out.println("SENHA: " + String.valueOf(palavra2));
                                    System.out.println("HASH: " + hash);


                                }
                            }
                        }
                    }
                }

            }
        }
        long timeF = System.currentTimeMillis();
        long total = timeF - timeI;
        System.out.println("Tempo Final: " + total);

    }
}

Bom galer, ninguém me ajudou ainda, mas estou tentando e lendo alguns livros. ou passar aqui o avanço das minhas pesquisas e dos meus códigos fontes

Classe MD5: está correta!

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.senacrs.util;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 *
 * @author Angelo
 */
public class MD5 {

    public static String gerarMD5(String senha) {
        MessageDigest md;
        String crypto;
        try {
            /**
             * Aqui dizemos qual o tipo de hash vamos trabalhar, poderia ser
             * outro, como SHA.
             */
            md = MessageDigest.getInstance("MD5");
            /**
             * Aqui trablamos com BigInteger para suportar uma grande quantia de
             * caracteres.
             */
            BigInteger hash = new BigInteger(1, md.digest(senha.getBytes()));

            /**
             * Transforma o hash em String.
             */
            crypto = hash.toString(16);

            /**
             * Verifica de um 0 a esquerda não foi ignorado, caso positivo,
             * readiciona.
             */
            if (crypto.length() % 2 != 0) {
                crypto = "0" + crypto;
            }

            /**
             * Retorna a palavra criptografada.
             */
            return crypto;
        } catch (NoSuchAlgorithmException ex) {
            System.out.println("Um erro ocorreu ao tentar gerar o Hash da palavra");
            return "ERRO";
        }



    }
}

Classe Threads: não funcionando!

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package quebrahash;

import br.com.senacrs.util.MD5;

/**
 *
 * @author Maxwell
 */
public class Threads extends Thread {
    public Threads (String threadName) {
        
    }

    Threads(int i, int i0) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
    public void run () {
        char dictAll[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
            'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
            'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
            'W', 'V', 'X', 'Y', 'Z', '!', '@', '#', '$', '%', '&', '*', '(', ')', '_', '-',
            '+', '=', '[', ']', '{', '}', '?', '/', '|', '>', '<', '.', '\\'};
       
        String dicthash[] = {"13240457817d091164402b9604824b67", "5438364b0199c0004432ac04dae29525",
            "2271dc8fa2a6ff3b4c23180a66c480dc", "19d6ebafc1e11bea79fb2b85aa760ad9", "f3f3aa37990860260b2e6ceeaf672837",
            "dcaff46aec8f457fa874d0b7a04960be", "f21ee05fa5d24c7de11e4aca9700aa8f", "827ccb0eea8a706c4c34a16891f84e7b",
            "9605eb53e0da2675998ad751baf255ce", "58396401112fa9245099fff81ba63dec", "972c16f442eba60469680bf869dd6a89",
            "50e318711a43cc8e965d90337f49deb8", "fe60293345d3e4f675441f1c4424ed4e", "d79096188b670c2f81b7001f73801117",
            "48a58da106a36dd10852b229dfdc2088", "36510ae837f23c4da6e541a3e8edafb8", "9d495d6a637e83e277de834c2b31a8a1",
            "54d9d99fad304a6d0329fc1fb6bdb517", "dfa8327f5bfa4c672a04f9b38e348a70", "70d06803ce18c714944dac18cd58f292",
            "7a32b47d202ac6f583bbd9c42a0961ef", "69e80cd4d08679e2739f801516bfb170", "6cfe61694ee1bb13ae719d47c2f80b7a",
            "e2ba49209f8ce01f1025d5f14400bf5b",};

        char palavra2[] = new char[5];

        long timeI = System.currentTimeMillis();
        for (int k = 0; k < dictAll.length; k++) {
            palavra2[4] = dictAll[k];
            for (int f = 0; f < dictAll.length; f++) {
                palavra2[3] = dictAll[f];
                for (int b = 0; b < dictAll.length; b++) {
                    palavra2[2] = dictAll[b];
                    for (int j = 0; j < dictAll.length; j++) {
                        palavra2[0] = dictAll[j];
                        for (int i = 0; i < dictAll.length; i++) {
                            palavra2[1] = dictAll[i];
                            String hash = MD5.gerarMD5(String.valueOf(palavra2));
                            //System.out.println("VALOR -> " + String.valueOf(palavra2));
                            //System.out.println("HASH: " + hash);

                            for (int h = 0; h < dicthash.length; h++) {
                                if (hash.equalsIgnoreCase(dicthash[h])) {
                                    long total_quebra = ((System.currentTimeMillis() - timeI) / 1000);
                                    System.out.println("SENHA QUEBRADA! EM: " + total_quebra + " segundos");
                                    System.out.println("SENHA: " + String.valueOf(palavra2));
                                    System.out.println("HASH: " + hash);
                                }
                            }
                        }
                    }
                }
            }
        }
        long timeF = System.currentTimeMillis();
        long total = timeF - timeI;
        System.out.println("Tempo Final: " + total);
    }
}

E assim que eu estou chamando a thread no meu main:

package quebrahash;

public class QuebraHash {

    public static void main(String[] args) {
        new Thread (new Threads (0,22)).start();
        new Thread (new Threads (22,44)).start();
        new Thread (new Threads (44,86)).start();
    }
}

Preciso de ajuda para saber porque não está funcionando, se está faltando algo ou sei lá.
Este é o erro na saída:
Exception in thread “main” java.lang.UnsupportedOperationException: Not supported yet.
at quebrahash.Threads.(Threads.java:19)
at quebrahash.QuebraHash.main(QuebraHash.java:6)
Java Result: 1
CONSTRUÍDO COM SUCESSO (tempo total: 0 segundos)

Desde já agradeço!

Aí galera acabei de descobrir o erro. Tenho de implementar um método. Mas não faço nem ideia do que seja isso e nem como fazer. Alguém da uma luz ai?

cara, eu n sei se entendi mto o seu codigo, mas isso q vc ta fazendo me parece loucura…
enfim, o erro ta acontecendo por causa dessa parte do codigo:

Threads(int i, int i0) {  
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.  
    }  

vc tem q ver o q esse metodo vai fazer, posta a parte onde ta lançando esse metodo, c vc n acha q ele tem utilidade, n implementa, só deleta essa parte do codigo ou tira a linha q lan~ça a exceção…

n tinha visto q ja tinha colcoado xD
então cara, o q acontece é q vc ta usando o construtor q pede 2 ints, e td q esse construtor faz é lançar uma exceção, vc tem q usar o construtor q n pede nenhum argumento, ou alterar o construtor q pede os 2 ints, pra q serve esses parametros? pelo jeito q vc chamou parece q esses valores vao ser usados pra alguma coisa, altera o metodo pra usar esses valores

bem interessante sua ideia.
Percebi que você esta setando a posição do que a thread vai percorrer do seu hash(dicionário de hash).
Mas e quando uma das threads encontra o hash? Como você vai informar para as outras pararem?.

Talvez seria interessante se você criar uma classe ?container? a qual “controla” a execução das threads,
e as sincroniza, mas eu acredito que isto vai gerar uma complexidade a mais.

E sendo um pouco chato, eu acredito que seria melhor você exportar o seu dicionário a um XML
ou até mesmo a um banco.

Mas é mais interessante fazer isto depois que você decidir como vai manipular as threads certo?(XML library: jdom, xstream, etc…)

Eu aconselho, dar uma olhada a alguns sistemas já existentes tais como o “John the Ripper
O qual é um software open-source, especializado em ataques de força bruta,
Ele trabalha em 3 modos, e um deles é o WordList(Com dicionário) o qual lhe interessa

Opa! Obrigado pelas dicas galera. Agora dei uma aprimorada no meu código, ele está funcionando, pelo que vi na minha máquina quando executo o programa o cpu fica em 100% de utilização. Só não sei se está rodando totalmente certo.

Classe da Thread: Agora está para quebrar senhas de 6 caracteres

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package quebrahash;

import br.com.senacrs.util.MD5;

/**
 *
 * @author Maxwell
 */
public class Threads extends Thread {
int i;
int i0;
    
    
    public Threads(String threadName) {
        super(threadName);
    }

    public Threads() {
    }
    

    Threads(int i, int i0) {
       this.i=i;
       this.i0=i0;
    }

@Override
    public void run() {
       char dictAll[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
            'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
            'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
            'W', 'V', 'X', 'Y', 'Z', '!', '@', '#', '$', '%', '&', '*', '(', ')', '_', '-',
            '+', '=', '[', ']', '{', '}', '?', '/', '|', '>', '<', '.', '\\'};
        String dicthash[] = {"8ab337e58e81398a0d5af82a4e9a0c79", "eb30670bb0e1c5edee08135db93efa77",
            "76a2173be6393254e72ffa4d6df1030a", "920d22766c3e612e964ac8eafc14a0d6", "8c1200ce22d3d580f91021403c1a85e7",
            "c25a57af7ba864e66fd702e27d149d89", "a6277e6334d4fe8c60c95af0cdf20217", "60f991ba32d0fc91a57499bd74304151",
            "778252ea76f7f2e5dc56392f41dfb629", "3d945423f8e9496c429a5d8c65b4604f", "733d7be2196ff70efaf6913fc8bdcabf",
            "05dc54fe448e122a4ffc072989c6a4da", "1d867c84d76d2c19579c75e6e4f254bf", "05e124f4627deea91cd084e69bd59e70",
            "3b9fd53e2cddd988bfaab9b2bccf8a68", "8f04712639a44a796d200da1879e9086", "a11e3ff6ce4b8296b9c23fcb6900e176",
            "d9e9aa0dc2bae9810b46775dd4341591", "0589b4628622a3c9b96d72804e68f9b9", "e16ad9b2312744576485c258973ed048",
            "34751c79b023a5da62e40f84b39d7152", "31e1e26ebead31ff89268e28aaa5f238", "b6237e0583f7a0604ffae20003e5ec5a",
            "bee4dc86f94515966d17479983ebb06e", "c41613341914d2a60bf6946c21fb8559", "00f8f0a585c90c88230dab78690f5092",
            "1ad986911cd5e67c70af2d16e40f5690"};

        char palavra2[] = new char[6];

        long timeI = System.currentTimeMillis();
        for (int k = i; k < i0; k++) {
            palavra2[5] = dictAll[k];
            for (int g = 0; g < dictAll.length; g++) {
                palavra2[4] = dictAll[g];
                for (int f = 0; f < dictAll.length; f++) {
                    palavra2[3] = dictAll[f];
                    for (int b = 0; b < dictAll.length; b++) {
                        palavra2[2] = dictAll[b];
                        for (int j = 0; j < dictAll.length; j++) {
                            palavra2[1] = dictAll[j];
                            for (int m = 0; m < dictAll.length; m++) {
                                palavra2[0] = dictAll[m];
                                String hash = MD5.gerarMD5(String.valueOf(palavra2));
                                //System.out.println("VALOR -> " + String.valueOf(palavra2));
                                //System.out.println("HASH: " + hash);

                                for (int h = 0; h < dicthash.length; h++) {
                                    if (hash.equalsIgnoreCase(dicthash[h])) {
                                        long total_quebra = ((System.currentTimeMillis() - timeI) / 1000);
                                        System.out.println("SENHA QUEBRADA! EM: " + total_quebra + " segundos");
                                        System.out.println("SENHA: " + String.valueOf(palavra2));
                                        System.out.println("HASH: " + hash);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            long timeF = System.currentTimeMillis();
            long total = timeF - timeI;
            System.out.println("Tempo Final: " + total);
        }
    }
    
}

Main:

package quebrahash;

public class QuebraHash {

    public static void main(String[] args) {
        new Thread (new Threads (0,10)).start();
        new Thread (new Threads (11,20)).start();
        new Thread (new Threads (20,40)).start();
        new Thread (new Threads (40,86)).start();
    }
}

O objetivo de implementar threads seria para acelerar o processo de quebra das hashs, pois meu professor com seu código e uma máquina com um processador de 8 núcleos quebrou as hashs propostas do trabalho em quase 10 horas.

Se vcs puderem dar uma analisada no meu código e ver se ele ta funcionando certinho e realmente está acelerando este processo, eu agradeço muito!

MD5:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.senacrs.util;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 *
 * @author Angelo
 */
public class MD5 {

    public static String gerarMD5(String senha) {
        MessageDigest md;
        String crypto;
        try {
            /**
             * Aqui dizemos qual o tipo de hash vamos trabalhar, poderia ser
             * outro, como SHA.
             */
            md = MessageDigest.getInstance("MD5");
            /**
             * Aqui trablamos com BigInteger para suportar uma grande quantia de
             * caracteres.
             */
            BigInteger hash = new BigInteger(1, md.digest(senha.getBytes()));

            /**
             * Transforma o hash em String.
             */
            crypto = hash.toString(16);

            /**
             * Verifica de um 0 a esquerda não foi ignorado, caso positivo,
             * readiciona.
             */
            if (crypto.length() % 2 != 0) {
                crypto = "0" + crypto;
            }

            /**
             * Retorna a palavra criptografada.
             */
            return crypto;
        } catch (NoSuchAlgorithmException ex) {
            System.out.println("Um erro ocorreu ao tentar gerar o Hash da palavra");
            return "ERRO";
        }



    }
}