Question

I am making pasword cracking program(webster dictionary comparing and finding matches) as a school assigment. It is pipeline architecture using threads and bounded buffers. First question would be:

  1. Why it is even slower than centralized pasword cracker even though it is using more threads(one for reading from file-because it is fast process, one for making variations- because it is still faster than 3x encrypting thread, 3 threads for encrypting- because it is very slow process and finnaly one thread for comparing)?

  2. Why when i add 4th thread for encrypting there is no Build successful written in the end of the program when threads finish.

Thank you very much for any answer if need something e.g. my experiments just ask.

CODE: Encrypting class

package passwordcracking;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Encrypt implements Runnable {

private static final Logger LOGGER = Logger.getLogger("passwordCracker");
private final Buffers<String> bufferTakeFrom;
private final Buffers<PairEncPWandClearPW> bufferPutTo;
String possiblePassword;
private MessageDigest messageDigest;

/**
 *
 * @param bufferTakeFrom
 */
public Encrypt(Buffers<String> bufferTakeFrom, Buffers<PairEncPWandClearPW>        

bufferPutTo) 
{
    this.bufferTakeFrom = bufferTakeFrom;
    this.bufferPutTo = bufferPutTo;
    try {
        messageDigest = MessageDigest.getInstance("SHA");
    } catch (NoSuchAlgorithmException ex) {
        LOGGER.log(Level.SEVERE, ex.getMessage());
        throw new RuntimeException(ex);
    }
}

@Override
public void run() {
    do {
        possiblePassword = bufferTakeFrom.take();
        EncryptSingleWord(possiblePassword);
    } while (!possiblePassword.equals("-1"));

}

private void EncryptSingleWord(final String possiblePassword) {
    byte[] digest = null;
    try {
        digest = messageDigest.digest(possiblePassword.getBytes());
        PairEncPWandClearPW pair = new PairEncPWandClearPW(digest, possiblePassword);
        bufferPutTo.put(pair);
    } catch (Exception ex) {
        System.out.println("Exception: " + ex);
        System.out.println("possible password bytes: " + possiblePassword.getBytes());
        System.out.println("password:" + possiblePassword);

    }

}}

Making variations class:

package passwordcracking;

import utilities.StringUtilities;

/**
 *
 * @author zatokar
 */
public class MakeVariations implements Runnable {

Buffers<String> bufferTakeFrom;
Buffers<String> bufferPutTo;
String dictionaryEntry;

public MakeVariations(Buffers<String> bufferTakeFrom, Buffers<String> bufferPutTo) {
    this.bufferTakeFrom = bufferTakeFrom;
    this.bufferPutTo = bufferPutTo;
}

@Override
public void run() {
    do {
        dictionaryEntry = bufferTakeFrom.take();
        makeVariations(dictionaryEntry);
        if (dictionaryEntry.equals("-1")) {
            System.out.println("Make variations thread finished.");
        }
    } while (!dictionaryEntry.equals("-1"));
}

public void makeVariations(final String dictionaryEntry) {
    final String possiblePassword = dictionaryEntry;
    bufferPutTo.put(dictionaryEntry);
    final String possiblePasswordUpperCase = dictionaryEntry.toUpperCase();
    bufferPutTo.put(possiblePasswordUpperCase);
    final String possiblePasswordCapitalized = StringUtilities.capitalize(dictionaryEntry);
    bufferPutTo.put(possiblePasswordCapitalized);
    final String possiblePasswordReverse = new StringBuilder(dictionaryEntry).reverse().toString();
    bufferPutTo.put(possiblePasswordReverse);
    for (int i = 0; i < 100; i++) {
        final String possiblePasswordEndDigit = dictionaryEntry + i;
        bufferPutTo.put(possiblePasswordEndDigit);
    }
    for (int i = 0; i < 100; i++) {
        final String possiblePasswordStartDigit = i + dictionaryEntry;
        bufferPutTo.put(possiblePasswordStartDigit);
    }
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 100; j++) {
            final String possiblePasswordStartEndDigit = i + dictionaryEntry + j;
            bufferPutTo.put(possiblePasswordStartEndDigit);
        }
    }
}
}

Buffers class:

package passwordcracking;

import java.util.LinkedList;
import java.util.Queue;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author zatokar
 */
public class Buffers <T>{
final Queue<T> ll = new LinkedList<>();
int capacity=500000;
public synchronized T take(){

    while (ll.isEmpty()) {
        try {
//             System.out.println("empty");
            wait();
        } catch (InterruptedException ex) {
            Logger.getLogger(Buffers.class.getName()).log(Level.SEVERE, null, ex);
        }
        }
  T element = ll.remove();
  notifyAll();
  return element;

}

    public synchronized void put(T element) {
    while (isFull()) {
        try {

//            System.out.println("full "+element);
            wait();
        } catch (InterruptedException e) {
        }
    }

    ll.add(element);
    notifyAll();
}
  public boolean isFull(){
      return (ll.size()==capacity);
      }


    public boolean isEmpty(){
        if (ll.isEmpty()){
            return true;
        }
        else{
            return false;}
    }
}

Comparing class:

package passwordcracking;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Compare implements Runnable {

Buffers<PairEncPWandClearPW> bufferTakeFrom;
final List<UserInfo> userInfos;
byte[] digest;
PairEncPWandClearPW pair;
String possiblePassword;

public Compare(Buffers<PairEncPWandClearPW> bufferTakeFrom) throws IOException {
    this.bufferTakeFrom = bufferTakeFrom;
    userInfos = PasswordFileHandler.readPasswordFile("passwords.txt");
}

@Override
public void run() {
    do {
        pair=bufferTakeFrom.take();
        possiblePassword = pair.getClearPW();
        digest = pair.getEncryptedPW();
        List<UserInfoClearText> list = checkSingleWord(userInfos, digest, 

possiblePassword);
        if (!list.isEmpty()) {
            System.out.println(list);
        }
        if (possiblePassword.equals("-1")) {
            System.out.println("Comparing thread finished.");
            final long endTime = System.currentTimeMillis();
            final long usedTime = endTime - PasswordCracking.startTime;
            System.out.println("Used time: " + usedTime / 1000 + " seconds = " +     

usedTime / 60000.0 + " minutes");
        }
    } while (!possiblePassword.equals("-1"));
}

private List<UserInfoClearText> checkSingleWord(final List<UserInfo> userInfos, final     

byte[] digest, final String possiblePassword) {
    final List<UserInfoClearText> results = new ArrayList<UserInfoClearText>();
    for (UserInfo userInfo : userInfos) {
        if (Arrays.equals(userInfo.getEntryptedPassword(), digest)) {
           results.add(new UserInfoClearText(userInfo.getUsername(),     

possiblePassword));
        }
    }
    return results;
}
}
Was it helpful?

Solution

Try a SynchronousQueue instead of your own Buffers class. I am pretty sure this will be a major speed improvement (because of your synchronized implementation) as well.

Other than that, your architecture is questionable. It requires the SynchroneousQueue to keep the generating threads from overflowing/underflowing the processing threads, why don't these processing threads generate their own work?

You could write a Runnable that takes one word form the dictionary, generates variations and then test those against the real password. This would not only simplify the code a lot, it would as well ensure that threads are working 100% on the actual problem and you wouldn't have to worry about how many threads to spend on what.

OTHER TIPS

Okey so thanks to TwoThe he almost totaly solved my problem. The main speed up was replacing LinkedList queue with a LinkedBlockingQueue (he answered me to use SynchronousQueue but it does not have capacity constructor implemented) which is used with a capacity constructor what is necessary because after making variations and putting it into a LinkedList you for sure get OutOfMemoryException. Thank you so much the speed is 3 times less. The problem was my own synchronization in buffer class.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top