0

学校の課題として、パスワードクラッキングプログラム(ウェブスター辞書の比較と一致の検索)を作成しています。これは、スレッドとバウンド バッファーを使用したパイプライン アーキテクチャです。最初の質問は次のとおりです。

  1. より多くのスレッドを使用しているにもかかわらず、集中型パスワード クラッカーよりもさらに遅いのはなぜですか (ファイルからの読み取りに 1 つ - 処理が高速であるため、バリエーションの作成に 1 つ - 3 倍の暗号化スレッド、暗号化に 3 つのスレッドよりも依然として高速であるため)。それは非常に遅いプロセスであり、最終的に比較するための1つのスレッドです)?

  2. 暗号化のために 4 番目のスレッドを追加すると、スレッドの終了時にプログラムの最後にビルド成功が書き込まれないのはなぜですか。

私の実験など、何かが必要な場合は、ご回答いただきありがとうございます。

CODE: 暗号化クラス

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);

    }

}}

バリエーションクラスの作成:

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);
        }
    }
}
}

バッファ クラス:

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;}
    }
}

クラスの比較:

パッケージパスワードクラッキング;

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;
}
}
4

2 に答える 2

0

独自の Buffers クラスの代わりにSynchronousQueueを試してください。これにより、速度が大幅に向上することは間違いありません(同期された実装のため)。

それ以外は、あなたのアーキテクチャは疑わしいです。生成スレッドが処理スレッドのオーバーフロー/アンダーフローを防ぐために SynchronousQueue が必要ですが、これらの処理スレッドが独自の作業を生成しないのはなぜですか?

辞書から 1 つの単語を取得し、バリエーションを生成して、それらを実際のパスワードに対してテストする Runnable を作成できます。これにより、コードが大幅に簡素化されるだけでなく、スレッドが実際の問題に対して 100% 動作することが保証され、何にどれだけのスレッドを費やすかを心配する必要がなくなります。

于 2013-10-29T16:15:49.533 に答える