BruteForceProxy.java
package edu.jiangxin.apktoolbox.file.password.recovery.category.bruteforce;
import edu.jiangxin.apktoolbox.file.password.recovery.RecoveryPanel;
import edu.jiangxin.apktoolbox.file.password.recovery.State;
import edu.jiangxin.apktoolbox.file.password.recovery.category.ICategory;
import edu.jiangxin.apktoolbox.file.password.recovery.checker.FileChecker;
import edu.jiangxin.apktoolbox.file.password.recovery.checker.IChecker;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.swing.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class BruteForceProxy implements ICategory {
private static final Logger logger = LogManager.getLogger(BruteForceProxy.class.getSimpleName());
private ExecutorService executorService;
private BruteForceFuture bruteForceFuture;
private static class BruteForceProxyHolder {
private static final BruteForceProxy instance = new BruteForceProxy();
}
private BruteForceProxy() {
}
public static BruteForceProxy getInstance() {
return BruteForceProxyHolder.instance;
}
private String startAndGet(int numThreads, int passwordLength, IChecker checker, String charsSet, RecoveryPanel panel) {
executorService = Executors.newFixedThreadPool(numThreads);
bruteForceFuture = new BruteForceFuture(numThreads);
BruteForceTaskParam param = new BruteForceTaskParam(numThreads, passwordLength, checker, charsSet);
for (int taskId = 0; taskId < numThreads; taskId++) {
BruteForceRunnable task = new BruteForceRunnable(taskId, param, bruteForceFuture, panel);
executorService.execute(task);
}
String password = null;
try {
password = bruteForceFuture.get();
} catch (Exception e) {
logger.info("Exception test: ", e);
} finally {
if (executorService.isShutdown()) {
executorService.shutdown();
}
}
return password;
}
@Override
public void start(RecoveryPanel panel) {
String charset = panel.getCharset();
logger.info("Charset: {}", charset);
if (StringUtils.isEmpty(charset)) {
JOptionPane.showMessageDialog(panel, "Character set is empty!");
return;
}
int minLength = panel.getMinLength();
int maxLength = panel.getMaxLength();
if (minLength > maxLength) {
JOptionPane.showMessageDialog(panel, "Minimum length is bigger than maximum length!");
return;
}
String password = null;
int totalNumber = 0;
for (int length = minLength; length <= maxLength; length++) {
totalNumber += (int)Math.pow(charset.length(), length);
}
panel.resetProgressMaxValue(totalNumber);
for (int length = minLength; length <= maxLength; length++) {
long startTime = System.currentTimeMillis();
FileChecker fileChecker = panel.getCurrentFileChecker();
int processorCount = Runtime.getRuntime().availableProcessors();
int numThreads = getThreadCount(charset.length(), length, processorCount);
logger.info("[{}]Current attempt length: {}, thread number: {}", fileChecker, length, numThreads);
password = startAndGet(numThreads, length, fileChecker, charset, panel);
long endTime = System.currentTimeMillis();
logger.info("Current attempt length: {}, Cost time: {}ms", length, (endTime - startTime));
if (password != null || panel.getCurrentState() != State.WORKING) {
logger.info("Break state: {}", panel.getCurrentState());
break;
}
}
panel.showResultWithDialog(password);
}
@Override
public void cancel() {
if (bruteForceFuture != null) {
bruteForceFuture.cancel(false);
}
if (executorService != null && !executorService.isShutdown()) {
executorService.shutdown();
}
while (executorService != null && !executorService.isTerminated()) {
try {
final boolean isTimeout = !executorService.awaitTermination(100, TimeUnit.SECONDS);
logger.info("awaitTermination isTimeout: " + isTimeout);
} catch (InterruptedException e) {
logger.error("awaitTermination InterruptedException");
Thread.currentThread().interrupt();
}
}
}
private int getThreadCount(int charSetSize, int length, int maxThreadCount) {
int result = 1;
for (int i = 1; i <= length; i++) {
result *= charSetSize;
if (result >= maxThreadCount) {
return maxThreadCount;
}
}
return result;
}
}