我正在制作密码破解程序(webster字典比较和查找匹配)作为学校的分配。它是使用线程和有界缓冲区的管道架构。第一个问题是:
为什么它甚至比集中式密码破解程序更慢,即使它使用更多线程(一个用于从文件读取 - 因为它是快速进程,一个用于进行变化 - 因为它仍然比3x加密线程更快,用于加密的3个线程 - 因为它是一个非常慢的进程,并且有一个用于比较的线程)?
为什么当我添加第4个线程进行加密时,当线程完成时,在程序结束时没有编写Build成功。
非常感谢您的任何答案,如果需要的话,例如我的实验只是问。
代码:加密课程
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;
}
}
答案 0 :(得分:0)
尝试使用SynchronousQueue代替您自己的Buffers类。我很确定这将是一个主要的速度提升(因为你的同步实现)。
除此之外,您的架构值得怀疑。它需要SynchroneousQueue来保持生成线程不会溢出/下溢处理线程,为什么这些处理线程不能生成自己的工作呢?
您可以编写一个Runnable,它从字典中获取一个单词,生成变体,然后根据真实密码测试它们。这不仅可以简化代码,还可以确保线程在实际问题上100%工作,您不必担心花费多少线程。
答案 1 :(得分:0)