diff --git a/jPasswordObfuscator-bin/pom.xml b/jPasswordObfuscator-bin/pom.xml
index bae10af..e0ce0ca 100644
--- a/jPasswordObfuscator-bin/pom.xml
+++ b/jPasswordObfuscator-bin/pom.xml
@@ -58,7 +58,13 @@
rs.in.zivanovic
j-password-obfuscator
- 1.0.0
+ 1.0.1-SNAPSHOT
+
+
+ junit
+ junit
+ 4.10
+ test
diff --git a/jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/Main.java b/jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/Main.java
index 97fc6b4..70af81b 100644
--- a/jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/Main.java
+++ b/jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/Main.java
@@ -23,41 +23,31 @@
*/
package rs.in.zivanovic.obfuscator;
-import com.beust.jcommander.JCommander;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
+import java.util.concurrent.Callable;
/**
- * Main entry point.
+ * Obfuscator command line utility main class.
*/
public class Main {
private Main() {
}
+ /**
+ * Entry point.
+ *
+ * @param args command line arguments
+ */
public static void main(String[] args) {
- JCommander jc = new JCommander();
- Map commands = new HashMap<>();
- Map aliases = new HashMap<>();
- commands.put("o", new ObfuscateCommand());
- aliases.put("o", new String[]{"ob", "obfuscate"});
- commands.put("d", new DeObfuscateCommand());
- aliases.put("d", new String[]{"deob", "deobfuscate"});
- for (Entry e : commands.entrySet()) {
- String[] a = aliases.get(e.getKey());
- jc.addCommand(e.getKey(), e.getValue(), a);
- }
-
try {
- jc.parse(args);
- if (commands.keySet().contains(jc.getParsedCommand())) {
- Runnable r = commands.get(jc.getParsedCommand());
- r.run();
+ ParsedCommandLine pcl = new ParsedCommandLine(args);
+ Callable command = pcl.getCommand();
+ if (command == null) {
+ System.out.println(pcl.getHelpText());
} else {
- jc.usage();
+ System.out.println(command.call());
}
- } catch (RuntimeException ex) {
+ } catch (Exception ex) {
System.err.println("ERROR: " + ex.getMessage());
}
}
diff --git a/jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/ObfuscateCommand.java b/jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/ObfuscateCommand.java
index b596844..64f76c1 100644
--- a/jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/ObfuscateCommand.java
+++ b/jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/ObfuscateCommand.java
@@ -26,14 +26,14 @@ package rs.in.zivanovic.obfuscator;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.google.common.base.Joiner;
-import java.nio.charset.StandardCharsets;
import java.util.List;
+import java.util.concurrent.Callable;
/**
* Implementation of the obfuscate command.
*/
@Parameters(commandDescription = "Obfuscate sensitive data")
-public class ObfuscateCommand implements Runnable {
+public class ObfuscateCommand implements Callable {
@Parameter(names = {"-k", "--key"}, description = "Master key to use for obfuscation", required = true)
private String masterKey;
@@ -43,14 +43,12 @@ public class ObfuscateCommand implements Runnable {
private int version = 1;
@Parameter(description = "data to obfuscate", required = true)
- private List data;
+ private List params;
@Override
- public void run() {
- JPasswordObfuscator jpo = new JPasswordObfuscator();
- byte[] dataBytes = Joiner.on(' ').join(data).getBytes(StandardCharsets.UTF_8);
- String s = jpo.obfuscate(masterKey.toCharArray(), dataBytes, version);
- System.out.println(s);
+ public String call() {
+ String data = Joiner.on(' ').join(params);
+ return new Obfuscated(masterKey.toCharArray(), data, version).toString();
}
}
diff --git a/jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/ParsedCommandLine.java b/jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/ParsedCommandLine.java
new file mode 100644
index 0000000..8687db1
--- /dev/null
+++ b/jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/ParsedCommandLine.java
@@ -0,0 +1,94 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2015 Marko Zivanovic .
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package rs.in.zivanovic.obfuscator;
+
+import com.beust.jcommander.JCommander;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+/**
+ * Wrapper around command line arguments that performs parsing and returns callable that executes required command.
+ */
+public class ParsedCommandLine {
+
+ private static final Map> COMMANDS = new HashMap<>();
+ private static final Map ALIASES = new HashMap<>();
+ private final Callable command;
+ private final StringBuilder usage = new StringBuilder();
+
+ static {
+ COMMANDS.put("o", new ObfuscateCommand());
+ ALIASES.put("o", new String[]{"ob", "obfuscate"});
+ COMMANDS.put("u", new UnobfuscateCommand());
+ ALIASES.put("u", new String[]{"unob", "unobfuscate"});
+ }
+
+ /**
+ * Parse command line arguments and prepare command to execute and usage help text.
+ *
+ * @param args command line arguments to parse
+ */
+ public ParsedCommandLine(String[] args) {
+ JCommander jc = new JCommander();
+ addCommands(jc);
+ jc.usage(usage);
+ this.command = parse(jc, args);
+ }
+
+ /**
+ * Get the command to execute.
+ *
+ * @return command to execute
+ */
+ public Callable getCommand() {
+ return command;
+ }
+
+ /**
+ * Get usage help text.
+ *
+ * @return usage help text
+ */
+ public String getHelpText() {
+ return usage.toString();
+ }
+
+ private void addCommands(JCommander jc) {
+ for (Map.Entry> e : COMMANDS.entrySet()) {
+ String[] a = ALIASES.get(e.getKey());
+ jc.addCommand(e.getKey(), e.getValue(), a);
+ }
+ }
+
+ private Callable parse(JCommander jc, String[] args) {
+ Callable ret = null;
+ jc.parse(args);
+ if (COMMANDS.keySet().contains(jc.getParsedCommand())) {
+ ret = COMMANDS.get(jc.getParsedCommand());
+ }
+ return ret;
+ }
+
+}
diff --git a/jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/DeObfuscateCommand.java b/jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/UnobfuscateCommand.java
similarity index 68%
rename from jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/DeObfuscateCommand.java
rename to jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/UnobfuscateCommand.java
index c66dfe8..1269836 100644
--- a/jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/DeObfuscateCommand.java
+++ b/jPasswordObfuscator-bin/src/main/java/rs/in/zivanovic/obfuscator/UnobfuscateCommand.java
@@ -26,27 +26,25 @@ package rs.in.zivanovic.obfuscator;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.google.common.base.Joiner;
-import java.nio.charset.StandardCharsets;
import java.util.List;
+import java.util.concurrent.Callable;
/**
- * Implementation of the de-obfuscate command.
+ * Implementation of the un-obfuscate command.
*/
-@Parameters(commandDescription = "De-obfuscate sensitive data")
-public class DeObfuscateCommand implements Runnable {
+@Parameters(commandDescription = "Un-obfuscate sensitive data")
+public class UnobfuscateCommand implements Callable {
- @Parameter(names = {"-k", "--key"}, description = "Master key to use for de-obfuscation", required = true)
+ @Parameter(names = {"-k", "--key"}, description = "Master key to use for un-obfuscation", required = true)
private String masterKey;
- @Parameter(description = "obfuscated string to de-obfuscate", required = true)
- private List data;
+ @Parameter(description = "obfuscated string to un-obfuscate", required = true)
+ private List params;
@Override
- public void run() {
- JPasswordObfuscator jpo = new JPasswordObfuscator();
- String obfuscated = Joiner.on(' ').skipNulls().join(data);
- byte[] deObfuscated = jpo.deObfuscate(masterKey.toCharArray(), obfuscated);
- System.out.println(new String(deObfuscated, StandardCharsets.UTF_8));
+ public String call() {
+ String obfuscated = Joiner.on(' ').skipNulls().join(params);
+ return new Unobfuscated(masterKey.toCharArray(), obfuscated).asString();
}
}
diff --git a/jPasswordObfuscator-bin/src/test/java/rs/in/zivanovic/obfuscator/ObfuscateCommandTest.java b/jPasswordObfuscator-bin/src/test/java/rs/in/zivanovic/obfuscator/ObfuscateCommandTest.java
new file mode 100644
index 0000000..4d79d35
--- /dev/null
+++ b/jPasswordObfuscator-bin/src/test/java/rs/in/zivanovic/obfuscator/ObfuscateCommandTest.java
@@ -0,0 +1,52 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2015 Marko Zivanovic .
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package rs.in.zivanovic.obfuscator;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+import java.util.concurrent.Callable;
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+/**
+ * Obfuscator command-line utility unit tests.
+ */
+public class ObfuscateCommandTest {
+
+ private String run(String args) throws Exception {
+ Iterable a = Splitter.on(' ').split(args);
+ ParsedCommandLine pcl = new ParsedCommandLine(Iterables.toArray(a, String.class));
+ Callable c = pcl.getCommand();
+ return c.call();
+ }
+
+ @Test
+ public void testObfuscateUnobfuscate() throws Exception {
+ String o = run("o -k test test");
+ String d = run("u -k test " + o);
+ assertThat("test", equalTo(d));
+ }
+
+}
diff --git a/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/Obfuscated.java b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/Obfuscated.java
index e450c4f..db61385 100644
--- a/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/Obfuscated.java
+++ b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/Obfuscated.java
@@ -40,7 +40,7 @@ public class Obfuscated {
/**
* Build new obfuscation wrapper using latest obfuscation algorithm version.
*
- * @param key master key to use for obfuscation
+ * @param key master key to use for obfuscation
* @param data data to obfuscate
*/
public Obfuscated(char[] key, String data) {
@@ -50,7 +50,18 @@ public class Obfuscated {
/**
* Build new obfuscation wrapper using latest obfuscation algorithm version.
*
- * @param key master key to use for obfuscation
+ * @param key master key to use for obfuscation
+ * @param data data to obfuscate
+ * @param version version of the obfuscation algorithm to use
+ */
+ public Obfuscated(char[] key, String data, int version) {
+ this(key, data.getBytes(StandardCharsets.UTF_8), version);
+ }
+
+ /**
+ * Build new obfuscation wrapper using latest obfuscation algorithm version.
+ *
+ * @param key master key to use for obfuscation
* @param data data to obfuscate
*/
public Obfuscated(char[] key, byte[] data) {
@@ -60,8 +71,8 @@ public class Obfuscated {
/**
* Build new obfuscation wrapper using specified obfuscation algorithm version.
*
- * @param key master key to use for obfuscation
- * @param data data to obfuscate
+ * @param key master key to use for obfuscation
+ * @param data data to obfuscate
* @param version version of the obfuscation algorithm to use
*/
public Obfuscated(char[] key, byte[] data, int version) {
diff --git a/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/ObfuscatedData.java b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/ObfuscatedData.java
index 5e5c34c..b6d023c 100644
--- a/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/ObfuscatedData.java
+++ b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/ObfuscatedData.java
@@ -36,6 +36,13 @@ public class ObfuscatedData {
private final byte[] salt;
private final byte[] cipherText;
+ /**
+ * Build new obfuscated data container.
+ *
+ * @param version version of the algorithm used to obfuscate data
+ * @param salt random salt bytes
+ * @param cipherText obfuscated data
+ */
public ObfuscatedData(int version, byte[] salt, byte[] cipherText) {
this.version = version;
this.salt = Arrays.copyOf(salt, salt.length);
@@ -48,6 +55,13 @@ public class ObfuscatedData {
Base64.toBase64String(cipherText));
}
+ /**
+ * Parse string containing obfuscated data.
+ *
+ * @param obfuscatedString obfuscated string to parse
+ *
+ * @return parsed data
+ */
public static ObfuscatedData fromString(String obfuscatedString) {
String[] parts = obfuscatedString.split("\\$");
if (parts.length != 5) {
diff --git a/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/ObfuscatorException.java b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/ObfuscatorException.java
index 0c9f7f0..1e8c810 100644
--- a/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/ObfuscatorException.java
+++ b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/ObfuscatorException.java
@@ -28,6 +28,11 @@ package rs.in.zivanovic.obfuscator.impl;
*/
public class ObfuscatorException extends RuntimeException {
+ /**
+ * Wrap throwable into obfuscator exception.
+ *
+ * @param cause throwable to wrap
+ */
public ObfuscatorException(Throwable cause) {
super(cause);
}
diff --git a/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/PBEObfuscatorImpl.java b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/PBEObfuscatorImpl.java
index 724ad25..dda02d4 100644
--- a/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/PBEObfuscatorImpl.java
+++ b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/PBEObfuscatorImpl.java
@@ -40,6 +40,15 @@ public class PBEObfuscatorImpl implements Obfuscator {
private final int iterations;
private final int saltLen;
+ /**
+ * Build new PBE-based obfuscator with specified parameters.
+ *
+ * @param version version number for this set of parameters
+ * @param algo encryption algorithm to use
+ * @param provider crypto provider
+ * @param iterations number of key derivation rounds
+ * @param saltLen length of random salt in bytes
+ */
public PBEObfuscatorImpl(int version, String algo, String provider, int iterations, int saltLen) {
this.algo = algo;
this.provider = provider;
diff --git a/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/V1ObfuscatorImpl.java b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/V1ObfuscatorImpl.java
index a228111..ce47ffc 100644
--- a/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/V1ObfuscatorImpl.java
+++ b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/V1ObfuscatorImpl.java
@@ -41,6 +41,10 @@ public class V1ObfuscatorImpl extends PBEObfuscatorImpl {
private static final int SALT_LEN = 8;
private static final int ITERATION_COUNT = 16_000;
+ /**
+ * Build new PBE-based obfuscator using PBEWithSHA256And128BitAES-CBC-BC with 8 bytes random salt and 16000
+ * iterations.
+ */
public V1ObfuscatorImpl() {
super(VERSION, ALGO, PROVIDER, ITERATION_COUNT, SALT_LEN);
}
diff --git a/jPasswordObfuscator-lib/src/test/java/rs/in/zivanovic/obfuscator/NewApiTest.java b/jPasswordObfuscator-lib/src/test/java/rs/in/zivanovic/obfuscator/NewApiTest.java
index 43acece..56406c0 100644
--- a/jPasswordObfuscator-lib/src/test/java/rs/in/zivanovic/obfuscator/NewApiTest.java
+++ b/jPasswordObfuscator-lib/src/test/java/rs/in/zivanovic/obfuscator/NewApiTest.java
@@ -51,6 +51,20 @@ public class NewApiTest {
assertThat(unob, equalTo(dataS));
}
+ @Test
+ public void testObfuscateUnobfuscateArraysV1() {
+ String o = new Obfuscated(key, dataBA, 1).toString();
+ byte[] unob = new Unobfuscated(key, o).asByteArray();
+ assertThat(unob, equalTo(dataBA));
+ }
+
+ @Test
+ public void testObfuscateUnobfuscateStringsV1() {
+ String o = new Obfuscated(key, dataS, 1).toString();
+ String unob = new Unobfuscated(key, o).asString();
+ assertThat(unob, equalTo(dataS));
+ }
+
@Test(expected = NullPointerException.class)
public void testUnobfuscationClearsData() {
String o = new Obfuscated(key, dataBA).toString();
@@ -59,4 +73,14 @@ public class NewApiTest {
unob.asByteArray();
}
+ @Test(expected = IllegalArgumentException.class)
+ public void testObfuscatedInvalidVersion() {
+ String o = new Obfuscated(key, dataS, -1).toString();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUnobfuscatedInvalidVersion() {
+ String o = new Unobfuscated(key, "$rizobf$-1$F6Krv4H91RE=$NjytmuPjmfZbwQjqUWcbDg==").asString();
+ }
+
}