代码
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
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
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
long combinations = (long) Math.pow(chars.length, len)
if (remaining < combinations) {
length = len
break
}
remaining -= combinations
}
for (int i = 0
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
long combinations = calculateCombinations(len)
if (remaining < combinations) {
length = len
break
}
remaining -= combinations
}
// 生成密码字符
for (int i = 0
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
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("未能找到正确的密码。")
}
}
}
zip4j
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>2.10.0</version>
</dependency>