在添加一个线程,密码破解管道后,构建成功未显示

时间:2013-10-29 11:25:23

标签: java multithreading pipeline cracking

我正在制作密码破解程序(webster字典比较和查找匹配)作为学校的分配。它是使用线程和有界缓冲区的管道架构。第一个问题是:

  1. 为什么它甚至比集中式密码破解程序更慢,即使它使用更多线程(一个用于从文件读取 - 因为它是快速进程,一个用于进行变化 - 因为它仍然比3x加密线程更快,用于加密的3个线程 - 因为它是一个非常慢的进程,并且有一个用于比较的线程)?

  2. 为什么当我添加第4个线程进行加密时,当线程完成时,在程序结束时没有编写Build成功。

  3. 非常感谢您的任何答案,如果需要的话,例如我的实验只是问。

    代码:加密课程

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

2 个答案:

答案 0 :(得分:0)

尝试使用SynchronousQueue代替您自己的Buffers类。我很确定这将是一个主要的速度提升(因为你的同步实现)。

除此之外,您的架构值得怀疑。它需要SynchroneousQueue来保持生成线程不会溢出/下溢处理线程,为什么这些处理线程不能生成自己的工作呢?

您可以编写一个Runnable,它从字典中获取一个单词,生成变体,然后根据真实密码测试它们。这不仅可以简化代码,还可以确保线程在实际问题上100%工作,您不必担心花费多少线程。

答案 1 :(得分:0)

好吧,感谢TwoThe他几乎完全解决了我的问题。主要的加速是用LinkedBlockingQueue替换LinkedList队列(他回答我使用SynchronousQueue但它没有实现容量构造函数),它与容量构造函数一起使用是必要的,因为在做出变化并将它放入LinkedList之后你肯定获取OutOfMemoryException。非常感谢你的速度减少了3倍。问题是我自己在缓冲类中的同步。