diff --git a/.travis.yml b/.travis.yml
index 8f37c05..bcc02a7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,7 @@
language: java
-
jdk:
- oraclejdk8
-
os:
- linux
+script:
+ - ./gradlew check
diff --git a/README.md b/README.md
index 832c5d7..0dfbd8d 100644
--- a/README.md
+++ b/README.md
@@ -1,36 +1,53 @@
# 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
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
-give key file/password pair until it finds a successful password. KeeCrack does not do incremental word list generation
-at this time, though you can
+give key file/password pair until it finds a successful password. The word list can either be a newline separated
+file, or a regular expression pattern.
## Usage
-You can download a DEB, JAR, or RPM from the releases page. Each build contains both a GUI and CLI. 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
KeeCrack makes use of Gradle, so to build it yourself, you can just run
- ./gradlew jfxJar
-
-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)
+ ./gradlew shadowJar
## 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
@@ -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.
See the License for the specific language governing permissions and
limitations under the License.
-```
\ No newline at end of file
+```
diff --git a/build.gradle b/build.gradle
index 4a4f0f0..b607da4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -30,7 +30,7 @@ allprojects {
subprojects {
group 'com.wbrawner'
- version '1.0-SNAPSHOT'
+ version '1.0'
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'java'
diff --git a/keecrack-lib/src/main/java/com/wbrawner/keecrack/lib/KeeCrack.java b/keecrack-lib/src/main/java/com/wbrawner/keecrack/lib/KeeCrack.java
index ce8e3b4..aca7177 100644
--- a/keecrack-lib/src/main/java/com/wbrawner/keecrack/lib/KeeCrack.java
+++ b/keecrack-lib/src/main/java/com/wbrawner/keecrack/lib/KeeCrack.java
@@ -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.KdbxSerializer;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.InputStream;
+import java.io.*;
import java.time.Duration;
import java.time.Instant;
import java.util.Objects;
@@ -94,6 +92,30 @@ public class KeeCrack {
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.
*/
@@ -123,6 +145,7 @@ public class KeeCrack {
while (!haveCorrectPassword && wordList.hasNext()) {
if (abort.get()) {
sendErrorCode(Code.ERROR_CRACKING_INTERRUPTED);
+ cleanup();
isCracking.set(false);
abort.set(false);
return;
@@ -147,17 +170,23 @@ public class KeeCrack {
} catch (NullPointerException ignored) {
}
+ cleanup();
isCracking.set(false);
}
+ private void cleanup() {
+ databaseBytes = null;
+ keyBytes = null;
+ }
+
@SuppressWarnings("ResultOfMethodCallIgnored")
private void prepareByteArrays() {
- databaseBytes = Utils.getFileBytes(databaseFile);
+ databaseBytes = getFileBytes(databaseFile);
synchronized (keyFileLock) {
if (keyFile == null) {
return;
}
- keyBytes = Utils.getFileBytes(keyFile);
+ keyBytes = getFileBytes(keyFile);
}
}
@@ -182,8 +211,8 @@ public class KeeCrack {
} catch (Exception e) {
e.printStackTrace();
} finally {
- Utils.closeQuietly(databaseInput);
- Utils.closeQuietly(keyFileInput);
+ closeQuietly(databaseInput);
+ closeQuietly(keyFileInput);
}
return false;
}
diff --git a/keecrack-lib/src/main/java/com/wbrawner/keecrack/lib/Utils.java b/keecrack-lib/src/main/java/com/wbrawner/keecrack/lib/Utils.java
deleted file mode 100644
index 972ac9a..0000000
--- a/keecrack-lib/src/main/java/com/wbrawner/keecrack/lib/Utils.java
+++ /dev/null
@@ -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[]{};
- }
- }
-}