diff --git a/README.md b/README.md
index f3c1b85..6a864f9 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ Maven dependency is available at:
rs.in.zivanovic
j-password-obfuscator
- 1.0.0
+ 1.1.0
## Typical usage
@@ -23,8 +23,7 @@ Maven dependency is available at:
Say we want to obfuscate our super secret data string "Hello World" using the secret key "key".
We'd use the following snippet:
- JPasswordObfuscator obfuscator = new JPasswordObfuscator();
- String obfuscated = obfuscator.obfuscate("key".toCharArray(), "Hello World".getBytes(StandardCharsets.UTF_8));
+ String obfuscated = new Obfuscated("key".toCharArray(), "Hello World").toString();
System.out.println(obfuscated);
output will resemble this:
@@ -40,8 +39,7 @@ As with all secret keys, it is recommended to use random, or, at least, not easi
When we want to un-obfuscate data:
- JPasswordObfuscator obfuscator = new JPasswordObfuscator();
- String original = obfuscator.deObfuscate("key".toCharArray(), "$rizobf$1$l7IwmuwEZnY=$F5K7LeIP0u1cSluV3wBXqQ==");
+ String original = new Unobfuscated("key".toCharArray(), "$rizobf$1$l7IwmuwEZnY=$F5K7LeIP0u1cSluV3wBXqQ==").asString();
System.out.println(original);
and we get our original super secret data back:
diff --git a/jPasswordObfuscator-bin/pom.xml b/jPasswordObfuscator-bin/pom.xml
index bae10af..496e224 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.1.0-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/pom.xml b/jPasswordObfuscator-lib/pom.xml
index 0bd44d8..ce563c1 100644
--- a/jPasswordObfuscator-lib/pom.xml
+++ b/jPasswordObfuscator-lib/pom.xml
@@ -3,7 +3,7 @@
4.0.0
rs.in.zivanovic
j-password-obfuscator
- 1.0.1-SNAPSHOT
+ 1.1.0-SNAPSHOT
jar
JPasswordObfuscator library
@@ -51,7 +51,7 @@
junit
junit
- 4.10
+ 4.12
test
@@ -117,7 +117,7 @@
org.apache.maven.plugins
maven-gpg-plugin
- 1.5
+ 1.6
sign-artifacts
diff --git a/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/JPasswordObfuscator.java b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/JPasswordObfuscator.java
index 97cd80b..3a38540 100644
--- a/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/JPasswordObfuscator.java
+++ b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/JPasswordObfuscator.java
@@ -29,7 +29,7 @@ import rs.in.zivanovic.obfuscator.impl.Obfuscator;
import rs.in.zivanovic.obfuscator.impl.V1ObfuscatorImpl;
/**
- * Obfuscate and de-obfuscate sensitive data.
+ * Obfuscate and un-obfuscate sensitive data.
*
* This method is useful for protecting potentially sensitive data from casual onlookers. It is NOT secure against
* attackers with access to source code or live systems.
@@ -44,7 +44,7 @@ public final class JPasswordObfuscator {
* @param masterKey master key to use for obfuscation
* @param data data to obfuscate
*
- * @return string containing obfuscated data; use {@link #deObfuscate} to get secret data from this string
+ * @return string containing obfuscated data; use {@link #unObfuscate} to get secret data from this string
*/
public String obfuscate(char[] masterKey, byte[] data) {
return obfuscate(masterKey, data, 1);
@@ -57,7 +57,7 @@ public final class JPasswordObfuscator {
* @param data data to obfuscate
* @param version obfuscation algorithm version to use
*
- * @return string containing obfuscated data; use {@link #deObfuscate} to get secret data from this string
+ * @return string containing obfuscated data; use {@link #unObfuscate} to get secret data from this string
*/
public String obfuscate(char[] masterKey, byte[] data, int version) {
Objects.requireNonNull(masterKey);
@@ -71,20 +71,20 @@ public final class JPasswordObfuscator {
}
/**
- * De-obfuscate string generated with {@link #obfuscate} method.
+ * Un-obfuscate string generated with {@link #obfuscate} method.
*
- * @param masterKey master key to use for de-obfuscation; must match the key used for obfuscation
+ * @param masterKey master key to use for un-obfuscation; must match the key used for obfuscation
* @param obfuscatedString obfuscated string generated using one of {@link #obfuscate} methods
*
- * @return original, de-obfuscated data
+ * @return original, un-obfuscated data
*/
- public byte[] deObfuscate(char[] masterKey, String obfuscatedString) {
+ public byte[] unObfuscate(char[] masterKey, String obfuscatedString) {
Objects.requireNonNull(masterKey);
Objects.requireNonNull(obfuscatedString);
ObfuscatedData ob = ObfuscatedData.fromString(obfuscatedString);
switch (ob.getVersion()) {
case 1:
- return v1Obfuscator.deObfuscate(masterKey, ob);
+ return v1Obfuscator.unObfuscate(masterKey, ob);
default:
throw new IllegalArgumentException("Unsupported version: " + ob.getVersion());
}
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
new file mode 100644
index 0000000..db61385
--- /dev/null
+++ b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/Obfuscated.java
@@ -0,0 +1,96 @@
+/*
+ * 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 java.nio.charset.StandardCharsets;
+import java.util.Objects;
+import rs.in.zivanovic.obfuscator.impl.ObfuscatedData;
+import rs.in.zivanovic.obfuscator.impl.V1ObfuscatorImpl;
+
+/**
+ * Wrapper around sensitive data that performs obfuscation using secret key and generate output string. For the sake of
+ * security, you should zero your secret key data as soon as possible after constructing Obfuscated object. Objects of
+ * this class do not retain any sensitive data after being constructed.
+ */
+public class Obfuscated {
+
+ private final ObfuscatedData obfuscatedData;
+
+ /**
+ * 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, String data) {
+ this(key, data.getBytes(StandardCharsets.UTF_8), 1);
+ }
+
+ /**
+ * Build new obfuscation wrapper using latest obfuscation algorithm version.
+ *
+ * @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) {
+ this(key, data, 1);
+ }
+
+ /**
+ * Build new obfuscation wrapper using specified obfuscation algorithm version.
+ *
+ * @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) {
+ Objects.requireNonNull(key);
+ Objects.requireNonNull(data);
+ Objects.requireNonNull(version);
+ switch (version) {
+ case 1:
+ this.obfuscatedData = new V1ObfuscatorImpl().obfuscate(key, data);
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported version: " + version);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return obfuscatedData.toString();
+ }
+
+}
diff --git a/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/Unobfuscated.java b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/Unobfuscated.java
new file mode 100644
index 0000000..248cc05
--- /dev/null
+++ b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/Unobfuscated.java
@@ -0,0 +1,83 @@
+/*
+ * 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 java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Objects;
+import rs.in.zivanovic.obfuscator.impl.ObfuscatedData;
+import rs.in.zivanovic.obfuscator.impl.ObfuscatorException;
+import rs.in.zivanovic.obfuscator.impl.V1ObfuscatorImpl;
+
+/**
+ * Wrapper around obfuscated data that performs un-obfuscation and generates output in various formats. For the sake of
+ * security, you should zero your secret key data as soon as possible after constructing Unobfuscated object. Objects of
+ * this class only retain un-obfuscated data after being constructed. First call to {@link #asByteArray()} or
+ * {@link #asString()} methods will return copy of and clear the un-obfuscated data; further calls will throw
+ * {@link ObfuscatorException}.
+ */
+public class Unobfuscated {
+
+ private byte[] data;
+
+ /**
+ * Build new wrapper around obfuscated data.
+ *
+ * @param key master key to use for un-obfuscation
+ * @param obfuscatedData obfuscated data to wrap
+ */
+ public Unobfuscated(char[] key, String obfuscatedData) {
+ ObfuscatedData od = ObfuscatedData.fromString(obfuscatedData);
+ switch (od.getVersion()) {
+ case 1:
+ this.data = new V1ObfuscatorImpl().unObfuscate(key, od);
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported version: " + od.getVersion());
+ }
+ }
+
+ /**
+ * Return un-obfuscated data as byte array.
+ *
+ * @return un-obfuscated data
+ */
+ public byte[] asByteArray() {
+ Objects.requireNonNull(data);
+ byte[] ret = Arrays.copyOf(data, data.length);
+ Arrays.fill(data, (byte) 0);
+ data = null;
+ return ret;
+ }
+
+ /**
+ * Return un-obfuscated data as string.
+ *
+ * @return un-obfuscated data
+ */
+ public String asString() {
+ return new String(asByteArray(), StandardCharsets.UTF_8);
+ }
+
+}
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/Obfuscator.java b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/Obfuscator.java
index 5663e6f..0ed25a1 100644
--- a/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/Obfuscator.java
+++ b/jPasswordObfuscator-lib/src/main/java/rs/in/zivanovic/obfuscator/impl/Obfuscator.java
@@ -24,7 +24,7 @@
package rs.in.zivanovic.obfuscator.impl;
/**
- * Obfuscator/de-obfuscator interface.
+ * Obfuscator/un-obfuscator interface.
*/
public interface Obfuscator {
@@ -39,12 +39,12 @@ public interface Obfuscator {
ObfuscatedData obfuscate(char[] masterKey, byte[] data);
/**
- * De-obfuscate data using supplied master key.
+ * un-obfuscate data using supplied master key.
*
- * @param masterKey master key to use for data de-obfuscation; must match master key used for obfuscation
- * @param data string obfuscated with {@link #obfuscate} to de-obfuscate
+ * @param masterKey master key to use for data un-obfuscation; must match master key used for obfuscation
+ * @param data string obfuscated with {@link #obfuscate} to un-obfuscate
*
* @return
*/
- byte[] deObfuscate(char[] masterKey, ObfuscatedData data);
+ byte[] unObfuscate(char[] masterKey, ObfuscatedData data);
}
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 c8b5e5d..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;
@@ -60,7 +69,7 @@ public class PBEObfuscatorImpl implements Obfuscator {
}
@Override
- public byte[] deObfuscate(char[] masterKey, ObfuscatedData ob) {
+ public byte[] unObfuscate(char[] masterKey, ObfuscatedData ob) {
try {
return crypto(Cipher.DECRYPT_MODE, ob.getCipherText(), masterKey, ob.getSalt());
} catch (GeneralSecurityException ex) {
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/JPasswordObfuscatorTest.java b/jPasswordObfuscator-lib/src/test/java/rs/in/zivanovic/obfuscator/JPasswordObfuscatorTest.java
index d44d973..b0d2224 100644
--- a/jPasswordObfuscator-lib/src/test/java/rs/in/zivanovic/obfuscator/JPasswordObfuscatorTest.java
+++ b/jPasswordObfuscator-lib/src/test/java/rs/in/zivanovic/obfuscator/JPasswordObfuscatorTest.java
@@ -40,11 +40,11 @@ public class JPasswordObfuscatorTest {
private final JPasswordObfuscator engine = new JPasswordObfuscator();
@Test
- public void testObfuscateDeObfuscate() {
+ public void testObfuscateUnObfuscate() {
String ob = engine.obfuscate(masterKey, data);
System.out.println(ob);
- byte[] deob = engine.deObfuscate(masterKey, ob);
- assertArrayEquals(data, deob);
+ byte[] unob = engine.unObfuscate(masterKey, ob);
+ assertArrayEquals(data, unob);
}
@Test(expected = IllegalArgumentException.class)
@@ -53,10 +53,10 @@ public class JPasswordObfuscatorTest {
}
@Test(expected = RuntimeException.class)
- public void testObfuscateDeObfuscateWrongMasterKey() {
+ public void testObfuscateUnObfuscateWrongMasterKey() {
String ob = engine.obfuscate(masterKey1, data);
- byte[] deob = engine.deObfuscate(masterKey2, ob);
- assertThat(data, not(equalTo(deob)));
+ byte[] unob = engine.unObfuscate(masterKey2, ob);
+ assertThat(data, not(equalTo(unob)));
}
@Test
@@ -83,33 +83,33 @@ public class JPasswordObfuscatorTest {
}
@Test(expected = NullPointerException.class)
- public void testDeobfuscateNullData() {
- engine.deObfuscate(masterKey, null);
+ public void testUnobfuscateNullData() {
+ engine.unObfuscate(masterKey, null);
}
@Test(expected = RuntimeException.class)
- public void testDeobfuscateGarbageData() {
- engine.deObfuscate(masterKey, "23499999puchn-p23948hfrn-[8f2333331xd");
+ public void testUnobfuscateGarbageData() {
+ engine.unObfuscate(masterKey, "23499999puchn-p23948hfrn-[8f2333331xd");
}
@Test(expected = IllegalArgumentException.class)
- public void testDeobfuscateInvalidSignature() {
- engine.deObfuscate(masterKey, "$INV$1$v1hACmQULBk=$ggRxqVe1fUMvUnzpLA6CoQ==");
+ public void testUnobfuscateInvalidSignature() {
+ engine.unObfuscate(masterKey, "$INV$1$v1hACmQULBk=$ggRxqVe1fUMvUnzpLA6CoQ==");
}
@Test(expected = IllegalArgumentException.class)
- public void testDeobfuscateTruncated() {
- engine.deObfuscate(masterKey, "$rizobf$1$v1hACmQULBk=$");
+ public void testUnobfuscateTruncated() {
+ engine.unObfuscate(masterKey, "$rizobf$1$v1hACmQULBk=$");
}
@Test(expected = RuntimeException.class)
- public void testDeobfuscateInvalidData() {
- engine.deObfuscate(masterKey, "$rizobf$1$v1hACmQULBk=$ggRxqVe1fUMvUnzpLA6Coq");
+ public void testUnobfuscateInvalidData() {
+ engine.unObfuscate(masterKey, "$rizobf$1$v1hACmQULBk=$ggRxqVe1fUMvUnzpLA6Coq");
}
@Test(expected = IllegalArgumentException.class)
- public void testDeobfuscateInvalidVersion() {
- engine.deObfuscate(masterKey, "$rizobf$211$v1hACmQULBk=$ggRxqVe1fUMvUnzpLA6Coq");
+ public void testUnobfuscateInvalidVersion() {
+ engine.unObfuscate(masterKey, "$rizobf$211$v1hACmQULBk=$ggRxqVe1fUMvUnzpLA6Coq");
}
}
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
new file mode 100644
index 0000000..56406c0
--- /dev/null
+++ b/jPasswordObfuscator-lib/src/test/java/rs/in/zivanovic/obfuscator/NewApiTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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 java.nio.charset.StandardCharsets;
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+/**
+ * New API ({@link Obfuscated} and {@link Unobfuscated}) tests.
+ */
+public class NewApiTest {
+
+ private static final char[] key = "key".toCharArray();
+ private static final String dataS = "data";
+ private static final byte[] dataBA = dataS.getBytes(StandardCharsets.UTF_8);
+
+ @Test
+ public void testObfuscateUnobfuscateArrays() {
+ String o = new Obfuscated(key, dataBA).toString();
+ byte[] unob = new Unobfuscated(key, o).asByteArray();
+ assertThat(unob, equalTo(dataBA));
+ }
+
+ @Test
+ public void testObfuscateUnobfuscateStrings() {
+ String o = new Obfuscated(key, dataS).toString();
+ String unob = new Unobfuscated(key, o).asString();
+ 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();
+ Unobfuscated unob = new Unobfuscated(key, o);
+ unob.asByteArray();
+ 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();
+ }
+
+}