Compare commits
3 commits
Author | SHA1 | Date | |
---|---|---|---|
ed4098983a | |||
599e155490 | |||
81db6720c9 |
12 changed files with 136 additions and 134 deletions
|
@ -1,7 +1,7 @@
|
||||||
language: java
|
language: java
|
||||||
|
|
||||||
jdk:
|
jdk:
|
||||||
- oraclejdk8
|
- oraclejdk8
|
||||||
|
|
||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
|
script:
|
||||||
|
- ./gradlew check
|
||||||
|
|
51
README.md
51
README.md
|
@ -1,36 +1,53 @@
|
||||||
# KeeCrack [![Build Status](https://travis-ci.org/wbrawner/keecrack.svg?branch=master)](https://travis-ci.org/wbrawner/keecrack)
|
# KeeCrack [![Build Status](https://travis-ci.org/wbrawner/keecrack.svg?branch=master)](https://travis-ci.org/wbrawner/keecrack)
|
||||||
[![Maintainability](https://api.codeclimate.com/v1/badges/a35dff49221e36abf189/maintainability)](https://codeclimate.com/github/wbrawner/keecrack/maintainability)
|
|
||||||
[![Test Coverage](https://api.codeclimate.com/v1/badges/a35dff49221e36abf189/test_coverage)](https://codeclimate.com/github/wbrawner/keecrack/test_coverage)
|
|
||||||
|
|
||||||
KeeCrack is a Java program used for brute-forcing KeePass database file master passwords. This should go without saying
|
KeeCrack is a Java program used for brute-forcing KeePass database file master passwords. This should go without saying
|
||||||
but use of this application is prohibited without the express consent of the owner of the database file. KeeCrack works
|
but use of this application is prohibited without the express consent of the owner of the database file. KeeCrack works
|
||||||
by taking a KeePass database file, an optional key file, and a word list, then attempts to open the database with the
|
by taking a KeePass database file, an optional key file, and a word list, then attempts to open the database with the
|
||||||
give key file/password pair until it finds a successful password. KeeCrack does not do incremental word list generation
|
give key file/password pair until it finds a successful password. The word list can either be a newline separated
|
||||||
at this time, though you can
|
file, or a regular expression pattern.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
You can download a DEB, JAR, or RPM from the releases page. Each build contains both a <abbr title="graphical user
|
You can download a JAR from the releases page. Each build contains both a <abbr title="graphical user
|
||||||
interface">GUI</abbr> and <abbr title="command line interface">CLI</abbr>. For the GUI, download and double-click the
|
interface">GUI</abbr> and <abbr title="command line interface">CLI</abbr>. For the GUI, download and double-click the
|
||||||
JAR file
|
JAR file. For command line usage, run the jar with `java -jar keecrack.jar -h` to get the following output:
|
||||||
|
|
||||||
|
```
|
||||||
|
usage: KeeCrack [-h] [--verbose] [--incremental] --word-list WORD-LIST-FILE [--key-file KEY-FILE] database
|
||||||
|
|
||||||
|
Brute force KeePass database files
|
||||||
|
|
||||||
|
positional arguments:
|
||||||
|
database the database file to brute force
|
||||||
|
|
||||||
|
named arguments:
|
||||||
|
-h, --help show this help message and exit
|
||||||
|
--verbose, -v Increase logging output
|
||||||
|
--incremental, -i Use pattern-based (incremental) guesses instead of a list of words from a file
|
||||||
|
--word-list WORD-LIST-FILE, -w WORD-LIST-FILE
|
||||||
|
a file containing newline-separated words to use as the passwords, or the pattern to generate words from if the --incremental flag is set
|
||||||
|
--key-file KEY-FILE, -k KEY-FILE
|
||||||
|
the key file to use with the database
|
||||||
|
```
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
KeeCrack makes use of Gradle, so to build it yourself, you can just run
|
KeeCrack makes use of Gradle, so to build it yourself, you can just run
|
||||||
|
|
||||||
./gradlew jfxJar
|
./gradlew shadowJar
|
||||||
|
|
||||||
This will produce a JAR output, though you can also create platform-specific binaries with the following:
|
|
||||||
|
|
||||||
./gradlew jfxNative
|
|
||||||
|
|
||||||
For more information on building for your OS, please see the README for the
|
|
||||||
[javafx-gradle-plugin](https://github .com/FibreFoX/javafx-gradle-plugin#requirements)
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
If you'd like to contribute, please fork the repository, make your changes, squash your commits, and send a pull request
|
If you'd like to contribute, please fork the repository, make your changes, squash your commits, and send a pull
|
||||||
.
|
request.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
KeeCrack is possible thanks to the following libraries:
|
||||||
|
|
||||||
|
[Generex](https://github.com/mifmif/Generex)
|
||||||
|
|
||||||
|
[KeePassJava2](https://github.com/jorabin/KeePassJava2)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@ -50,4 +67,4 @@ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
```
|
```
|
||||||
|
|
|
@ -30,7 +30,7 @@ allprojects {
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
group 'com.wbrawner'
|
group 'com.wbrawner'
|
||||||
version '1.0-SNAPSHOT'
|
version '1.0'
|
||||||
|
|
||||||
apply plugin: 'com.github.johnrengelman.shadow'
|
apply plugin: 'com.github.johnrengelman.shadow'
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
|
|
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,4 +1,5 @@
|
||||||
#Sun Apr 15 14:52:35 CDT 2018
|
# suppress inspection "UnusedProperty" for whole file
|
||||||
|
#Wed Apr 18 08:19:13 CDT 2018
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package com.wbrawner.keecrack.cli;
|
package com.wbrawner.keecrack.cli;
|
||||||
|
|
||||||
import com.wbrawner.keecrack.lib.Code;
|
import com.wbrawner.keecrack.lib.Code;
|
||||||
|
import com.wbrawner.keecrack.lib.CrackerFactory;
|
||||||
import com.wbrawner.keecrack.lib.KeeCrack;
|
import com.wbrawner.keecrack.lib.KeeCrack;
|
||||||
import com.wbrawner.keecrack.lib.view.CrackingView;
|
import com.wbrawner.keecrack.lib.view.CrackingView;
|
||||||
import net.sourceforge.argparse4j.ArgumentParsers;
|
import net.sourceforge.argparse4j.ArgumentParsers;
|
||||||
|
@ -71,7 +72,7 @@ public class Main {
|
||||||
Namespace res = parser.parseArgs(args);
|
Namespace res = parser.parseArgs(args);
|
||||||
isVerbose = res.getBoolean("verbose");
|
isVerbose = res.getBoolean("verbose");
|
||||||
isIncremental = res.getBoolean("incremental");
|
isIncremental = res.getBoolean("incremental");
|
||||||
KeeCrack keeCrack = KeeCrack.getInstance();
|
KeeCrack keeCrack = new CrackerFactory().getCracker(true);
|
||||||
keeCrack.setCrackingView(new CLICrackingView());
|
keeCrack.setCrackingView(new CLICrackingView());
|
||||||
|
|
||||||
String databasePath = res.getString("database");
|
String databasePath = res.getString("database");
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package com.wbrawner.keecrack.gui;
|
package com.wbrawner.keecrack.gui;
|
||||||
|
|
||||||
import com.wbrawner.keecrack.lib.Code;
|
import com.wbrawner.keecrack.lib.Code;
|
||||||
|
import com.wbrawner.keecrack.lib.CrackerFactory;
|
||||||
import com.wbrawner.keecrack.lib.KeeCrack;
|
import com.wbrawner.keecrack.lib.KeeCrack;
|
||||||
import com.wbrawner.keecrack.lib.view.CrackingView;
|
import com.wbrawner.keecrack.lib.view.CrackingView;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
@ -41,10 +42,11 @@ public class CrackingController implements Initializable, CrackingView {
|
||||||
private Label timeElapsed;
|
private Label timeElapsed;
|
||||||
|
|
||||||
private Stage stage;
|
private Stage stage;
|
||||||
|
private KeeCrack keeCrack;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
final KeeCrack keeCrack = KeeCrack.getInstance();
|
keeCrack = new CrackerFactory().getCracker(true);
|
||||||
keeCrack.setCrackingView(this);
|
keeCrack.setCrackingView(this);
|
||||||
new Thread(keeCrack::attack).start();
|
new Thread(keeCrack::attack).start();
|
||||||
}
|
}
|
||||||
|
@ -88,7 +90,6 @@ public class CrackingController implements Initializable, CrackingView {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onClose() {
|
private void onClose() {
|
||||||
KeeCrack keeCrack = KeeCrack.getInstance();
|
|
||||||
keeCrack.abort();
|
keeCrack.abort();
|
||||||
keeCrack.setCrackingView(null);
|
keeCrack.setCrackingView(null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package com.wbrawner.keecrack.gui;
|
package com.wbrawner.keecrack.gui;
|
||||||
|
|
||||||
import com.wbrawner.keecrack.lib.Code;
|
import com.wbrawner.keecrack.lib.Code;
|
||||||
|
import com.wbrawner.keecrack.lib.CrackerFactory;
|
||||||
import com.wbrawner.keecrack.lib.KeeCrack;
|
import com.wbrawner.keecrack.lib.KeeCrack;
|
||||||
import com.wbrawner.keecrack.lib.view.FormView;
|
import com.wbrawner.keecrack.lib.view.FormView;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
@ -48,7 +49,6 @@ public class MainController implements Initializable, FormView {
|
||||||
private TextField wordlist;
|
private TextField wordlist;
|
||||||
@FXML
|
@FXML
|
||||||
private Button crackButton;
|
private Button crackButton;
|
||||||
@FXML
|
|
||||||
private ToggleGroup wordlistType;
|
private ToggleGroup wordlistType;
|
||||||
@FXML
|
@FXML
|
||||||
private RadioButton wordlistFile;
|
private RadioButton wordlistFile;
|
||||||
|
@ -57,10 +57,10 @@ public class MainController implements Initializable, FormView {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
keeCrack = KeeCrack.getInstance();
|
keeCrack = new CrackerFactory().getCracker(true);
|
||||||
keeCrack.setFormView(this);
|
keeCrack.setFormView(this);
|
||||||
database.setOnMouseClicked(event -> {
|
database.setOnMouseClicked(event -> {
|
||||||
if (KeeCrack.getInstance().isCracking()) {
|
if (keeCrack.isCracking()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ public class MainController implements Initializable, FormView {
|
||||||
});
|
});
|
||||||
|
|
||||||
key.setOnMouseClicked(event -> {
|
key.setOnMouseClicked(event -> {
|
||||||
if (KeeCrack.getInstance().isCracking()) {
|
if (keeCrack.isCracking()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ public class MainController implements Initializable, FormView {
|
||||||
|
|
||||||
crackButton.setOnMouseClicked(event -> {
|
crackButton.setOnMouseClicked(event -> {
|
||||||
try {
|
try {
|
||||||
if (KeeCrack.getInstance().isCracking()) {
|
if (keeCrack.isCracking()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Stage stage = new Stage();
|
Stage stage = new Stage();
|
||||||
|
@ -107,13 +107,16 @@ public class MainController implements Initializable, FormView {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (wordlistType == null)
|
||||||
|
wordlistType = new ToggleGroup();
|
||||||
|
wordlistFile.setToggleGroup(wordlistType);
|
||||||
|
wordlistPattern.setToggleGroup(wordlistType);
|
||||||
wordlistType.selectedToggleProperty().addListener((observableValue, oldToggle, newToggle) ->
|
wordlistType.selectedToggleProperty().addListener((observableValue, oldToggle, newToggle) ->
|
||||||
updateWordListHandler());
|
updateWordListHandler());
|
||||||
|
|
||||||
if (keeCrack.getDatabaseFile() != null)
|
if (keeCrack.getDatabaseFile() != null)
|
||||||
onDatabaseFileSet(keeCrack.getDatabaseFile().getName());
|
onDatabaseFileSet(keeCrack.getDatabaseFile().getName());
|
||||||
if (keeCrack.getKeyFile() != null)
|
if (keeCrack.getKeyFile() != null)
|
||||||
onKeyFileSet(keeCrack.getKeyFile().getName());
|
|
||||||
if (keeCrack.getWordListName() != null)
|
if (keeCrack.getWordListName() != null)
|
||||||
onWordListSet(keeCrack.getWordListName());
|
onWordListSet(keeCrack.getWordListName());
|
||||||
}
|
}
|
||||||
|
@ -127,7 +130,7 @@ public class MainController implements Initializable, FormView {
|
||||||
new FileChooser.ExtensionFilter(description, extensions)
|
new FileChooser.ExtensionFilter(description, extensions)
|
||||||
);
|
);
|
||||||
Stage stage = new Stage();
|
Stage stage = new Stage();
|
||||||
stage.setOnHidden(e -> KeeCrack.getInstance().setFormView(null));
|
stage.setOnHidden(e -> keeCrack.setFormView(null));
|
||||||
return fileChooser.showOpenDialog(stage);
|
return fileChooser.showOpenDialog(stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +140,7 @@ public class MainController implements Initializable, FormView {
|
||||||
wordlist.setEditable(false);
|
wordlist.setEditable(false);
|
||||||
wordlist.setCursor(Cursor.HAND);
|
wordlist.setCursor(Cursor.HAND);
|
||||||
wordlist.setOnMouseClicked(event -> {
|
wordlist.setOnMouseClicked(event -> {
|
||||||
if (KeeCrack.getInstance().isCracking()) {
|
if (keeCrack.isCracking()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
File wordlistFile = getFile("Text Files", "txt");
|
File wordlistFile = getFile("Text Files", "txt");
|
||||||
|
|
|
@ -69,12 +69,8 @@
|
||||||
<HBox.margin>
|
<HBox.margin>
|
||||||
<Insets left="20.0"/>
|
<Insets left="20.0"/>
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
<toggleGroup>
|
|
||||||
<ToggleGroup fx:id="wordlistType"/>
|
|
||||||
</toggleGroup>
|
|
||||||
</RadioButton>
|
</RadioButton>
|
||||||
<RadioButton fx:id="wordlistFile" selected="true" text="From File"
|
<RadioButton fx:id="wordlistFile" selected="true" text="From File">
|
||||||
toggleGroup="wordlistType">
|
|
||||||
<HBox.margin>
|
<HBox.margin>
|
||||||
<Insets left="20.0"/>
|
<Insets left="20.0"/>
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 William Brawner
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.wbrawner.keecrack.lib;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class responsible for acquiring a {@link KeeCrack} instance
|
||||||
|
*/
|
||||||
|
public class CrackerFactory {
|
||||||
|
private static final Object singletonLock = new Object();
|
||||||
|
private static KeeCrack singleton;
|
||||||
|
|
||||||
|
public KeeCrack getCracker(boolean asSingleton) {
|
||||||
|
if (asSingleton) {
|
||||||
|
synchronized (singletonLock) {
|
||||||
|
if (singleton == null) {
|
||||||
|
singleton = new KeeCrack();
|
||||||
|
}
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new KeeCrack();
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,9 +22,7 @@ import org.linguafranca.pwdb.kdbx.KdbxCreds;
|
||||||
import org.linguafranca.pwdb.kdbx.stream_3_1.KdbxHeader;
|
import org.linguafranca.pwdb.kdbx.stream_3_1.KdbxHeader;
|
||||||
import org.linguafranca.pwdb.kdbx.stream_3_1.KdbxSerializer;
|
import org.linguafranca.pwdb.kdbx.stream_3_1.KdbxSerializer;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.*;
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -33,11 +31,11 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main class responsible for handling the brute forcing of the KeePass database. You do not contruct the
|
* The main class responsible for handling the brute forcing of the KeePass database. You do not contruct the
|
||||||
* KeeCrack instance directly, but rather call {@link #getInstance()}. To begin, you should set the form view and
|
* KeeCrack instance directly, but rather call {@link CrackerFactory#getCracker(boolean)}. To begin, you should set the
|
||||||
* cracking view with {@link #setFormView(FormView)} and {@link #setCrackingView(CrackingView)} respectively. These
|
* form view and cracking view with {@link #setFormView(FormView)} and {@link #setCrackingView(CrackingView)}
|
||||||
* views will be responsible for displaying information like error messages and status updates. The cracking will
|
* respectively. These views will be responsible for displaying information like error messages and status updates.
|
||||||
* work without these, though it's highly recommended to set them prior to beginning. The database and wordlist must
|
* The cracking will work without these, though it's highly recommended to set them prior to beginning. The database
|
||||||
* be set, while the key file is also optional. If either of the required parameters are missing, the
|
* and wordlist must be set, while the key file is also optional. If either of the required parameters are missing, the
|
||||||
* {@link #attack()} operation will abort, sending either {@link Code#ERROR_INVALID_DATABASE_FILE} or
|
* {@link #attack()} operation will abort, sending either {@link Code#ERROR_INVALID_DATABASE_FILE} or
|
||||||
* {@link Code#ERROR_INVALID_WORD_LIST}, respectively. The word list can either be a pattern, in which case
|
* {@link Code#ERROR_INVALID_WORD_LIST}, respectively. The word list can either be a pattern, in which case
|
||||||
* incremental guessing will take place, or a file, in which case each line of the file will be considered a password
|
* incremental guessing will take place, or a file, in which case each line of the file will be considered a password
|
||||||
|
@ -51,7 +49,6 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||||
* first parameter will be null.
|
* first parameter will be null.
|
||||||
*/
|
*/
|
||||||
public class KeeCrack {
|
public class KeeCrack {
|
||||||
private static final AtomicReference<KeeCrack> singleton = new AtomicReference<>(null);
|
|
||||||
private final Object keyFileLock = new Object();
|
private final Object keyFileLock = new Object();
|
||||||
private final AtomicBoolean isCracking = new AtomicBoolean(false);
|
private final AtomicBoolean isCracking = new AtomicBoolean(false);
|
||||||
/**
|
/**
|
||||||
|
@ -67,33 +64,40 @@ public class KeeCrack {
|
||||||
private WordList wordList;
|
private WordList wordList;
|
||||||
private int guessCount = 0;
|
private int guessCount = 0;
|
||||||
|
|
||||||
private KeeCrack() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static KeeCrack getInstance() {
|
|
||||||
if (singleton.get() == null) {
|
|
||||||
singleton.set(new KeeCrack());
|
|
||||||
}
|
|
||||||
|
|
||||||
return singleton.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this to reset the state of the KeeCrack instance. Note that you will need to set the views again after
|
* To get an instance of the class, use the {@link CrackerFactory}
|
||||||
* calling this
|
|
||||||
*/
|
*/
|
||||||
public void reset() {
|
KeeCrack() {
|
||||||
setDatabaseFile(null);
|
|
||||||
setKeyFile(null);
|
|
||||||
setWordListFile(null);
|
|
||||||
setCrackingView(null);
|
|
||||||
setFormView(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void abort() {
|
public void abort() {
|
||||||
abort.set(true);
|
abort.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void closeQuietly(Closeable closeable) {
|
||||||
|
if (closeable == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
closeable.close();
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||||
|
private static byte[] getFileBytes(File file) {
|
||||||
|
byte[] fileBytes;
|
||||||
|
try (InputStream inputStream = new FileInputStream(file)) {
|
||||||
|
fileBytes = new byte[inputStream.available()];
|
||||||
|
inputStream.read(fileBytes);
|
||||||
|
return fileBytes;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new byte[]{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this to begin brute-forcing the database file.
|
* Call this to begin brute-forcing the database file.
|
||||||
*/
|
*/
|
||||||
|
@ -123,6 +127,7 @@ public class KeeCrack {
|
||||||
while (!haveCorrectPassword && wordList.hasNext()) {
|
while (!haveCorrectPassword && wordList.hasNext()) {
|
||||||
if (abort.get()) {
|
if (abort.get()) {
|
||||||
sendErrorCode(Code.ERROR_CRACKING_INTERRUPTED);
|
sendErrorCode(Code.ERROR_CRACKING_INTERRUPTED);
|
||||||
|
cleanup();
|
||||||
isCracking.set(false);
|
isCracking.set(false);
|
||||||
abort.set(false);
|
abort.set(false);
|
||||||
return;
|
return;
|
||||||
|
@ -147,17 +152,23 @@ public class KeeCrack {
|
||||||
} catch (NullPointerException ignored) {
|
} catch (NullPointerException ignored) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cleanup();
|
||||||
isCracking.set(false);
|
isCracking.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void cleanup() {
|
||||||
|
databaseBytes = null;
|
||||||
|
keyBytes = null;
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||||
private void prepareByteArrays() {
|
private void prepareByteArrays() {
|
||||||
databaseBytes = Utils.getFileBytes(databaseFile);
|
databaseBytes = getFileBytes(databaseFile);
|
||||||
synchronized (keyFileLock) {
|
synchronized (keyFileLock) {
|
||||||
if (keyFile == null) {
|
if (keyFile == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
keyBytes = Utils.getFileBytes(keyFile);
|
keyBytes = getFileBytes(keyFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,8 +193,8 @@ public class KeeCrack {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} finally {
|
} finally {
|
||||||
Utils.closeQuietly(databaseInput);
|
closeQuietly(databaseInput);
|
||||||
Utils.closeQuietly(keyFileInput);
|
closeQuietly(keyFileInput);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2018 William Brawner
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.wbrawner.keecrack.lib;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
class Utils {
|
|
||||||
static void closeQuietly(Closeable closeable) {
|
|
||||||
if (closeable == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
closeable.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
|
||||||
static byte[] getFileBytes(File file) {
|
|
||||||
byte[] fileBytes;
|
|
||||||
try (InputStream inputStream = new FileInputStream(file)) {
|
|
||||||
fileBytes = new byte[inputStream.available()];
|
|
||||||
inputStream.read(fileBytes);
|
|
||||||
return fileBytes;
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return new byte[]{};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,13 +21,9 @@ import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
||||||
import static junit.framework.TestCase.assertFalse;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
@ -41,30 +37,14 @@ public class KeeCrackTest {
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mockCrackingView = mock(CrackingView.class);
|
mockCrackingView = mock(CrackingView.class);
|
||||||
mockFormView = mock(FormView.class);
|
mockFormView = mock(FormView.class);
|
||||||
keeCrack = KeeCrack.getInstance();
|
keeCrack = new CrackerFactory().getCracker(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
keeCrack.reset();
|
|
||||||
Utils.rmdir(Utils.getTmpDir());
|
Utils.rmdir(Utils.getTmpDir());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void resetTest() {
|
|
||||||
keeCrack.setDatabaseFile(new File("Database"));
|
|
||||||
keeCrack.setKeyFile(new File("Keyfile"));
|
|
||||||
keeCrack.setWordListPattern("Some pattern");
|
|
||||||
assertNotNull(keeCrack.getDatabaseFile());
|
|
||||||
assertNotNull(keeCrack.getKeyFile());
|
|
||||||
assertNotNull(keeCrack.getWordList());
|
|
||||||
keeCrack.reset();
|
|
||||||
assertNull(keeCrack.getDatabaseFile());
|
|
||||||
assertNull(keeCrack.getKeyFile());
|
|
||||||
assertNull(keeCrack.getWordList());
|
|
||||||
assertFalse(keeCrack.isCracking());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void abortTest() throws IOException {
|
public void abortTest() throws IOException {
|
||||||
keeCrack.setDatabaseFile(Utils.getDatabase("123456.kdbx"));
|
keeCrack.setDatabaseFile(Utils.getDatabase("123456.kdbx"));
|
||||||
|
|
Loading…
Reference in a new issue