ini
复制代码
import java.io.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import org.apache.commons.io.FileUtils;
/**
* 密码生成器接口 - 策略模式
*/
interface PasswordGenerator {
String nextPassword(Integer lastExecutePosition);
long getCurrentCount();
long getTotalCombinations();
}
/**
* 破解状态接口 - 状态模式
*/
interface CrackState {
void crack(ZipFile password, ZipCracker.ProgressMonitor progressMonitor);
void onSuccess(String password);
void onFailure();
}
/**
* 破解命令接口 - 命令模式
*/
interface CrackCommand {
void execute();
void undo();
}
/**
* 观察者接口 - 观察者模式
*/
interface CrackObserver {
void onProgressUpdate(long current, long total);
void onPasswordFound(String password);
void onCrackComplete();
}
/**
* 破解器构建器 - 建造者模式
* <p>
* 用于创建复杂对象
* 提供流式接口设置参数
* 将对象创建与参数设置分离
*/
class ZipCrackerBuilder {
// 修改为protected,允许ZipCracker访问
protected int threadCount = Runtime.getRuntime().availableProcessors() * 2;
protected String zipFilePath;
protected int minLength;
protected int maxLength;
protected String outputDir;
protected CrackObserver observer;
protected PasswordGenerator passwordGenerator;
protected ZipCracker.ProgressMonitor progressMonitor;
public ZipCrackerBuilder setThreadCount(int count) {
this.threadCount = count;
return this;
}
public ZipCrackerBuilder setZipFilePath(String path) {
this.zipFilePath = path;
return this;
}
public ZipCrackerBuilder setPasswordLength(int min, int max) {
this.minLength = min;
this.maxLength = max;
return this;
}
public ZipCrackerBuilder setOutputDir(String dir) {
this.outputDir = dir;
return this;
}
public ZipCrackerBuilder setObserver(CrackObserver observer) {
this.observer = observer;
return this;
}
public ZipCrackerBuilder setPasswordGenerator(PasswordGenerator passwordGenerator) {
this.passwordGenerator = passwordGenerator;
return this;
}
public ZipCrackerBuilder setProgressMonitor(ZipCracker.ProgressMonitor progressMonitor) {
this.progressMonitor = progressMonitor;
return this;
}
public ZipCracker build() {
return new ZipCracker(this);
}
}
/**
* ClassName: ZipCracker
* Description: ZIP密码破解工具,支持多线程和进度显示
* 使用多种设计模式优化代码结构
*
* @author wanjinjun
* @version 1.0
* @Copyright: Copyright (c) wanjinjun
* @Date 2025/3/30 22:42
*/
public class ZipCracker {
// 单例模式:管理全局状态
private static final AtomicBoolean passwordFound = new AtomicBoolean(false);
private static String FOUND_PASSWORD = new String();
// 建造者模式:配置参数
private final int threadCount;
private final String zipFilePath;
private final int minLength;
private final int maxLength;
private final String outputDir;
private final CrackObserver observer;
private final PasswordGenerator passwordGenerator;
private final ProgressMonitor progressMonitor;
private final ZipFile zipFile;
// 状态模式:当前破解状态
private CrackState currentState;
// 修改为protected,允许ZipCrackerBuilder访问
protected ZipCracker(ZipCrackerBuilder builder) {
this.threadCount = builder.threadCount;
this.zipFilePath = builder.zipFilePath;
this.minLength = builder.minLength;
this.maxLength = builder.maxLength;
this.outputDir = builder.outputDir;
this.zipFile = new ZipFile(zipFilePath);
this.observer = builder.observer;
this.passwordGenerator = new BruteForcePasswordGenerator(minLength, maxLength);
this.progressMonitor = new ProgressMonitor(passwordGenerator);
this.currentState = new InitialState(this);
}
/**
* 执行密码破解
* 模板方法模式:定义破解流程骨架
*/
public String crack() {
try {
// 1. 初始化
initialize();
// 2. 创建线程池
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
// 3. 提交破解任务
submitCrackTasks(executor);
// 4. 等待完成
waitForCompletion(executor);
// 5. 返回结果
return getResult();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private void initialize() {
// 初始化工作
new File(outputDir).mkdirs();
}
private void submitCrackTasks(ExecutorService executor) {
// 提交破解任务
for (int i = 0; i < threadCount; i++) {
executor.submit(new Runnable() {
@Override
public void run() {
// 创建破解命令
CrackCommand command = new CrackCommand() {
@Override
public void execute() {
currentState.crack(zipFile, progressMonitor);
}
@Override
public void undo() {
// 清理临时文件等
}
};
// 执行命令
command.execute();
}
});
}
}
private void waitForCompletion(ExecutorService executor) throws InterruptedException {
executor.shutdown();
executor.awaitTermination(12, TimeUnit.HOURS);
}
private String getResult() {
return passwordFound.get() ? FOUND_PASSWORD : null;
}
// 状态类实现
private class InitialState implements CrackState {
private final ZipCracker cracker;
public InitialState(ZipCracker cracker) {
this.cracker = cracker;
}
@Override
public void crack(ZipFile zipFile, ZipCracker.ProgressMonitor progressMonitor) {
// 实现破解逻辑
while (!passwordFound.get()) {
observer.onProgressUpdate(progressMonitor.generator.getCurrentCount(),
progressMonitor.generator.getTotalCombinations());
String password = progressMonitor.generator.nextPassword(null);
System.out.println("此次密码 : " + password);
if (password == null) {
break;
}
try {
zipFile.setPassword(password.toCharArray());
zipFile.setCharset(java.nio.charset.Charset.forName("GBK"));
// 获取第一个文件
FileHeader firstFile = zipFile.getFileHeaders().get(0);
// 尝试解压第一个文件到临时目录
String tempDir = outputDir + "temp_" + Thread.currentThread().getId();
new File(tempDir).mkdirs();
zipFile.extractFile(firstFile, tempDir);
// 如果成功解压,说明密码正确
onSuccess(password);
// 清理临时文件
FileUtils.deleteDirectory(new File(tempDir));
break;
} catch (Exception e) {
// net.lingala.zip4j.exception.ZipException: Wrong password! 密码错误,继续尝试
continue;
}
}
}
@Override
public void onSuccess(String password) {
passwordFound.set(true);
FOUND_PASSWORD = password;
if (observer != null) {
observer.onPasswordFound(password);
}
System.out.println("正确 此次密码 : " + password);
}
@Override
public void onFailure() {
// 处理失败情况
}
}
// 进度监控器实现
public static class ProgressMonitor implements CrackObserver {
private final PasswordGenerator generator;
private volatile boolean running = true;
public ProgressMonitor(PasswordGenerator generator) {
this.generator = generator;
}
public void stop() {
running = false;
}
@Override
public void onProgressUpdate(long current, long total) {
double progress = (double) current / total * 100;
System.out.printf("破解进度: %.2f%% (已尝试: %d/%d)\n", progress, current, total);
}
@Override
public void onPasswordFound(String password) {
System.out.println("密码已找到: " + password);
}
@Override
public void onCrackComplete() {
System.out.println("破解完成");
stop();
}
}
// 密码生成器实现
private static class BruteForcePasswordGenerator implements PasswordGenerator {
private final int minLength;
private final int maxLength;
private final char[] chars ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.@~!#$".toCharArray();
private long currentCount = 0;
private final long totalCombinations;
public BruteForcePasswordGenerator(int minLength, int maxLength) {
this.minLength = minLength;
this.maxLength = maxLength;
this.totalCombinations = calculateTotalCombinations();
}
private long calculateTotalCombinations() {
long total = 0;
for (int len = minLength; len <= maxLength; len++) {
total += (long) Math.pow(chars.length, len);
}
return total;
}
@Override
public synchronized String nextPassword(Integer lastExecutePosition) {
if (lastExecutePosition != null) {
currentCount = lastExecutePosition;
}
if (currentCount >= totalCombinations) {
return null;
}
return generatePassword(currentCount++);
}
private String generatePassword1(long currentCount) {
StringBuilder password = new StringBuilder();
int length = minLength;
long remaining = currentCount;
for (int len = minLength; len <= maxLength; len++) {
long combinations = (long) Math.pow(chars.length, len);
if (remaining < combinations) {
length = len;
break;
}
remaining -= combinations;
}
for (int i = 0; i < length; i++) {
password.append(chars[(int) (remaining % chars.length)]);
remaining /= chars.length;
}
return password.toString();
}
private String generatePassword(long currentCount) {
StringBuilder password = new StringBuilder();
int length = minLength;
long remaining = currentCount;
// 确定密码长度
for (int len = minLength; len <= maxLength; len++) {
long combinations = calculateCombinations(len);
if (remaining < combinations) {
length = len;
break;
}
remaining -= combinations;
}
// 生成密码字符
for (int i = 0; i < length; i++) {
password.append(chars[(int) (remaining % chars.length)]);
remaining /= chars.length;
}
// 反转字符串以修正顺序
return password.reverse().toString();
}
/**
* long combinations = (long) Math.pow(chars.length, len);
* @param len
* @return
*/
private long calculateCombinations(int len) {
long combinations = 1;
for (int i = 0; i < len; i++) {
if (combinations > Long.MAX_VALUE / chars.length) {
return Long.MAX_VALUE;
}
combinations *= chars.length;
}
return combinations;
}
@Override
public long getCurrentCount() {
return currentCount;
}
@Override
public long getTotalCombinations() {
return totalCombinations;
}
}
// 主方法示例
public static void main(String[] args) {
String zipFilePath = "E:\\Project\\tmp.zip";
String outputFilePath = "E:\\Project\\output";
System.out.println("----------------测试单密码破解--------- Begin-------------");
String password = "123456";
ZipFile zipFile = new ZipFile(zipFilePath);
try {
zipFile.setPassword(password.toCharArray());
zipFile.setCharset(java.nio.charset.Charset.forName("GBK"));
zipFile.extractAll(outputFilePath);
} catch (ZipException e) {
e.printStackTrace();
}
System.out.println("---------------测试单密码破解-----------End----------");
PasswordGenerator passwordGenerator= new BruteForcePasswordGenerator(6, 6);
ProgressMonitor progressMonitor = new ProgressMonitor(passwordGenerator);
// 使用建造者模式创建破解器
ZipCracker cracker = new ZipCrackerBuilder()
.setZipFilePath(zipFilePath)
.setPasswordLength(4, 12)
.setOutputDir(outputFilePath)
.setPasswordGenerator(passwordGenerator)
.setProgressMonitor(progressMonitor)
.setObserver( progressMonitor)
.build();
// 执行破解
String result = cracker.crack();
if (result != null) {
System.out.println("密码破解成功!密码是: " + result);
} else {
System.out.println("未能找到正确的密码。");
}
}
}