From 2a07702fba827bc382d2998991bebd6cd82e70b6 Mon Sep 17 00:00:00 2001
From: Jon Chambers
Date: Sun, 1 Jul 2018 12:56:22 -0400
Subject: [PATCH] Created separate int/long versions of all of the major
pieces.
---
README.md | 63 ++++++-------
.../idobfuscator/AlphabetCodec.java | 51 +++++++---
.../BitRotationIntegerTransformer.java | 16 ++--
.../BitRotationLongTransformer.java | 57 +++++++++++
.../eatthepath/idobfuscator/IntegerCodec.java | 22 ++---
.../IntegerObfuscationPipeline.java | 13 ++-
.../idobfuscator/IntegerTransformer.java | 6 +-
.../eatthepath/idobfuscator/LongCodec.java | 32 +++++++
.../idobfuscator/LongObfuscationPipeline.java | 75 +++++++++++++++
.../idobfuscator/LongTransformer.java | 30 ++++++
...ltiplicativeInverseIntegerTransformer.java | 42 ++++-----
.../MultiplicativeInverseLongTransformer.java | 94 +++++++++++++++++++
.../OffsetIntegerTransformer.java | 8 +-
.../idobfuscator/OffsetLongTransformer.java | 45 +++++++++
.../idobfuscator/XorIntegerTransformer.java | 15 +--
.../idobfuscator/XorLongTransformer.java | 49 ++++++++++
.../idobfuscator/AlphabetCodecTest.java | 31 ++++--
.../BitRotationIntegerTransformerTest.java | 9 +-
.../BitRotationLongTransformerTest.java | 33 +++++++
.../eatthepath/idobfuscator/ExampleApp.java | 13 ++-
.../idobfuscator/IntegerCodecTest.java | 39 --------
.../IntegerObfuscationPipelineTest.java | 27 +-----
.../idobfuscator/IntegerTransformerTest.java | 8 +-
.../LongObfuscationPipelineTest.java | 39 ++++++++
.../idobfuscator/LongTransformerTest.java | 39 ++++++++
...licativeInverseIntegerTransformerTest.java | 2 +-
...tiplicativeInverseLongTransformerTest.java | 33 +++++++
.../OffsetIntegerTransformerTest.java | 2 +-
.../OffsetLongTransformerTest.java | 16 ++++
.../XorIntegerTransformerTest.java | 2 +-
.../idobfuscator/XorLongTransformerTest.java | 16 ++++
31 files changed, 731 insertions(+), 196 deletions(-)
create mode 100644 src/main/java/com/eatthepath/idobfuscator/BitRotationLongTransformer.java
create mode 100644 src/main/java/com/eatthepath/idobfuscator/LongCodec.java
create mode 100644 src/main/java/com/eatthepath/idobfuscator/LongObfuscationPipeline.java
create mode 100644 src/main/java/com/eatthepath/idobfuscator/LongTransformer.java
create mode 100644 src/main/java/com/eatthepath/idobfuscator/MultiplicativeInverseLongTransformer.java
create mode 100644 src/main/java/com/eatthepath/idobfuscator/OffsetLongTransformer.java
create mode 100644 src/main/java/com/eatthepath/idobfuscator/XorLongTransformer.java
create mode 100644 src/test/java/com/eatthepath/idobfuscator/BitRotationLongTransformerTest.java
delete mode 100644 src/test/java/com/eatthepath/idobfuscator/IntegerCodecTest.java
create mode 100644 src/test/java/com/eatthepath/idobfuscator/LongObfuscationPipelineTest.java
create mode 100644 src/test/java/com/eatthepath/idobfuscator/LongTransformerTest.java
create mode 100644 src/test/java/com/eatthepath/idobfuscator/MultiplicativeInverseLongTransformerTest.java
create mode 100644 src/test/java/com/eatthepath/idobfuscator/OffsetLongTransformerTest.java
create mode 100644 src/test/java/com/eatthepath/idobfuscator/XorLongTransformerTest.java
diff --git a/README.md b/README.md
index adfab63..47cb7df 100644
--- a/README.md
+++ b/README.md
@@ -34,39 +34,38 @@ final AlphabetCodec codec = new AlphabetCodec(new AlphabetBuilder()
.build());
final MultiplicativeInverseIntegerTransformer inverse =
- new MultiplicativeInverseIntegerTransformer(0x1909719a5ee544adL);
+ new MultiplicativeInverseIntegerTransformer(0x5ee544ad);
final BitRotationIntegerTransformer rotate = new BitRotationIntegerTransformer(22);
-final OffsetIntegerTransformer offset = new OffsetIntegerTransformer(0xe45c2f833b2f0474L);
-final XorIntegerTransformer xor = new XorIntegerTransformer(0xe41c643d0593242L);
-
+final OffsetIntegerTransformer offset = new OffsetIntegerTransformer(0x3b2f0474);
+final XorIntegerTransformer xor = new XorIntegerTransformer(0xd0593242);
final IntegerObfuscationPipeline pipeline =
new IntegerObfuscationPipeline(codec, inverse, rotate, offset, xor);
-System.out.println("| ID | Obfuscated ID |");
-System.out.println("|----|----------------|");
+System.out.println("| ID | Obfuscated ID |");
+System.out.println("|----|---------------|");
for (int id = 0; id < 10; id++) {
- System.out.format("| %d | %-14s |\n", id, pipeline.obfuscate(id));
+ System.out.format("| %d | %-13s |\n", id, pipeline.obfuscate(id));
assert id == pipeline.deobfuscate(pipeline.obfuscate(id));
}
```
The example produces the following output:
-| ID | Obfuscated ID |
-|----|----------------|
-| 0 | LWNKM28KZD449J |
-| 1 | VWB2HZQ3CLVPBQ |
-| 2 | XHQ9QD9M7NZYZC |
-| 3 | B7BCPMZB4JFP9X |
-| 4 | 2L3878VCZ3NQXM |
-| 5 | LXZMVQXBFZ3XYT |
-| 6 | VX28X98HFPQ98N |
-| 7 | XV2NQYJNV2349F |
-| 8 | BV2CKWTDBZKFJC |
-| 9 | 29K87FNQLCY9XC |
+| ID | Obfuscated ID |
+|----|---------------|
+| 0 | RZCNV8L |
+| 1 | 93ZWMWW |
+| 2 | Z93438Y |
+| 3 | FLMYVD7 |
+| 4 | VQWMNT2 |
+| 5 | CLM3NN9 |
+| 6 | R44WR9B |
+| 7 | 9TB44NX |
+| 8 | ZKD3888 |
+| 9 | BVJXQL8 |
In the above example, there are three major pieces of the puzzle: transformers, codecs, and a pipeline. We'll discuss each in turn.
@@ -74,18 +73,18 @@ In the above example, there are three major pieces of the puzzle: transformers,
The main point of interaction with ID Obfuscator is the `ObfuscationPipeline`. The pipeline combines a number of transformers and exactly one codec into a coherent tool for obfuscating and deobfuscating numbers. The type, number, and configuration of the transformers and the type and configuration codec all control the behavior of the pipeline. As an example, let's change the order of the transformers in the demo above to `offset, rotate, xor, inverse` (i.e. we swap the positions of `offset` and `rotate`). Now the output looks like this:
-| ID | Obfuscated ID |
-|----|----------------|
-| 0 | LCXJYW72K4QPDN |
-| 1 | VC4YV7MKXHXX43 |
-| 2 | FDJNDP4KCFPTF4 |
-| 3 | BF4QWWQTMHY7HC |
-| 4 | 2RYDTDV874Q2RL |
-| 5 | L3CJQTYM3M8D4D |
-| 6 | VXPNPYN3MMMRFV |
-| 7 | FPF77MXDLKCT3Y |
-| 8 | BW8H3J9H7W9V8F |
-| 9 | 2CF4RWFCFYLNCT |
+| ID | Obfuscated ID |
+|----|---------------|
+| 0 | F8C88BC |
+| 1 | ZRHBHMQ |
+| 2 | C3VPHKD |
+| 3 | 43QZY42 |
+| 4 | BDYTNP4 |
+| 5 | RCLW873 |
+| 6 | FQCYMLP |
+| 7 | ZDHXXV7 |
+| 8 | CTZ7XZV |
+| 9 | 4TQCNTL |
This is, obviously, very different from the original output. We could achieve similar output changes by changing the value of the offset passed to the `OffsetIntegerTransformer`, for example, or changing the random seed passed to the codec. This has two very important consequences:
@@ -125,4 +124,4 @@ ID Obfuscator comes with `AlphabetCodec`, which uses an alphabet you provide to
## The details
-ID Obfuscator is just that: an obfuscator. It makes it difficult for malicious users to figure out how to turn an obfuscated ID into a "real" ID, but not impossible. Under no circumstances should it be used to encode sensitive information like credit card numbers, PINs, or phone numbers. Caveat emptor.
\ No newline at end of file
+ID Obfuscator is just that: an obfuscator. It makes it difficult for malicious users to figure out how to turn an obfuscated ID into a "real" ID, but not impossible. Under no circumstances should it be used to encode sensitive information like credit card numbers, PINs, or phone numbers. Caveat emptor.
diff --git a/src/main/java/com/eatthepath/idobfuscator/AlphabetCodec.java b/src/main/java/com/eatthepath/idobfuscator/AlphabetCodec.java
index 604a8aa..324bb8b 100644
--- a/src/main/java/com/eatthepath/idobfuscator/AlphabetCodec.java
+++ b/src/main/java/com/eatthepath/idobfuscator/AlphabetCodec.java
@@ -13,13 +13,14 @@
*
* @author Jon Chambers
*/
-public class AlphabetCodec implements IntegerCodec {
+public class AlphabetCodec implements IntegerCodec, LongCodec {
private final char[] alphabet;
private final transient int[] characterValues;
- private final transient int maximumStringLength;
+ private final transient int maximumStringLengthForInt;
+ private final transient int maximumStringLengthForLong;
private final transient long[] placeValues;
/**
@@ -74,9 +75,10 @@ public AlphabetCodec(final char... alphabet) {
// string needed to represent any integer value with the given alphabet. With that, we can both perform some
// low-cost error-checking when we try to decode strings and also pre-calculate place values to avoid repeating
// work when decoding.
- this.maximumStringLength = (int) Math.ceil(Math.log(Math.pow(2, Long.SIZE)) / Math.log(this.alphabet.length));
+ this.maximumStringLengthForInt = (int) Math.ceil(Math.log(Math.pow(2, Integer.SIZE)) / Math.log(this.alphabet.length));
+ this.maximumStringLengthForLong = (int) Math.ceil(Math.log(Math.pow(2, Long.SIZE)) / Math.log(this.alphabet.length));
- this.placeValues = new long[this.maximumStringLength];
+ this.placeValues = new long[this.maximumStringLengthForLong];
this.placeValues[0] = 1;
for (int i = 1; i < this.placeValues.length; i++) {
@@ -84,20 +86,34 @@ public AlphabetCodec(final char... alphabet) {
}
}
+ @Override
+ public String encodeIntegerAsString(final int i) {
+ long workingCopy = i & 0xffffffffL;
+
+ final char[] encodedCharacters = new char[this.maximumStringLengthForInt];
+
+ for (int j = encodedCharacters.length - 1; j >= 0; j--) {
+ encodedCharacters[j] = this.alphabet[(int) (workingCopy % this.alphabet.length)];
+ workingCopy /= this.alphabet.length;
+ }
+
+ return new String(encodedCharacters);
+ }
+
/**
* Encodes the given integer as a string using this codec's alphabet.
*
- * @param i the integer to encode
+ * @param l the integer to encode
*
* @return a string representation of the given integer
*
* @throws IllegalArgumentException if the given integer cannot be expressed with {@code nBits} bits
*/
@Override
- public String encodeIntegerAsString(final long i) {
- long workingCopy = i;
+ public String encodeLongAsString(final long l) {
+ long workingCopy = l;
- final char[] encodedCharacters = new char[this.maximumStringLength];
+ final char[] encodedCharacters = new char[this.maximumStringLengthForLong];
for (int j = encodedCharacters.length - 1; j >= 0; j--) {
encodedCharacters[j] = this.alphabet[(int) Long.remainderUnsigned(workingCopy, this.alphabet.length)];
@@ -107,6 +123,15 @@ public String encodeIntegerAsString(final long i) {
return new String(encodedCharacters);
}
+ @Override
+ public int decodeStringAsInteger(final String string) {
+ final long decoded = this.decodeStringAsLong(string, this.maximumStringLengthForInt);
+
+ assert (decoded & 0xffffffff00000000L) == 0;
+
+ return (int) decoded;
+ }
+
/**
* Decodes the given string as an integer.
*
@@ -118,10 +143,14 @@ public String encodeIntegerAsString(final long i) {
* alphabet, or if the given string contains characters not in this codec's alphabet
*/
@Override
- public long decodeStringAsInteger(final String string) {
- if (string.length() > this.maximumStringLength) {
+ public long decodeStringAsLong(final String string) {
+ return this.decodeStringAsLong(string, this.maximumStringLengthForLong);
+ }
+
+ private long decodeStringAsLong(final String string, final int maximumStringLength) {
+ if (string.length() > maximumStringLength) {
throw new IllegalArgumentException(
- String.format("String \"%s\" is too long to represent a valid 64-bit integer in this codec's alphabet.", string));
+ String.format("String \"%s\" is too long to represent a valid integer in this codec's alphabet.", string));
}
final char[] chars = string.toCharArray();
diff --git a/src/main/java/com/eatthepath/idobfuscator/BitRotationIntegerTransformer.java b/src/main/java/com/eatthepath/idobfuscator/BitRotationIntegerTransformer.java
index 98b270e..bd0521b 100644
--- a/src/main/java/com/eatthepath/idobfuscator/BitRotationIntegerTransformer.java
+++ b/src/main/java/com/eatthepath/idobfuscator/BitRotationIntegerTransformer.java
@@ -15,11 +15,11 @@ public class BitRotationIntegerTransformer implements IntegerTransformer {
*
* @param distance the number of places by which to rotate integers
*/
- public BitRotationIntegerTransformer(final long distance) {
+ public BitRotationIntegerTransformer(final int distance) {
this.originalDistance = distance;
- // Normalize the rotation distance to the range of [0, 64).
- this.effectiveDistance = (int) ((distance % Long.SIZE) + (distance < 0 ? Long.SIZE : 0));
+ // Normalize the rotation distance to the range of [0, 32).
+ this.effectiveDistance = (int) ((distance % Integer.SIZE) + (distance < 0 ? Integer.SIZE : 0));
}
int getEffectiveDistance() {
@@ -27,15 +27,15 @@ int getEffectiveDistance() {
}
/**
- * Transforms the given number by rotating its bits to the left by a prescribed distance.
+ * Transforms the given integer by rotating its bits to the left by a prescribed distance.
*
* @param i the integer to transform
*
* @return the rotated integer
*/
@Override
- public long transformInteger(final long i) {
- return (i << this.effectiveDistance) | (i >>> (Long.SIZE - this.effectiveDistance));
+ public int transformInteger(final int i) {
+ return (i << this.effectiveDistance) | (i >>> (Integer.SIZE - this.effectiveDistance));
}
/**
@@ -46,8 +46,8 @@ public long transformInteger(final long i) {
* @return the original integer
*/
@Override
- public long reverseTransformInteger(final long i) {
- return (i >>> this.effectiveDistance) | (i << (Long.SIZE -this.effectiveDistance));
+ public int reverseTransformInteger(final int i) {
+ return (i >>> this.effectiveDistance) | (i << (Integer.SIZE - this.effectiveDistance));
}
@Override
diff --git a/src/main/java/com/eatthepath/idobfuscator/BitRotationLongTransformer.java b/src/main/java/com/eatthepath/idobfuscator/BitRotationLongTransformer.java
new file mode 100644
index 0000000..64bc073
--- /dev/null
+++ b/src/main/java/com/eatthepath/idobfuscator/BitRotationLongTransformer.java
@@ -0,0 +1,57 @@
+package com.eatthepath.idobfuscator;
+
+/**
+ * Transforms long integers by performing a circular bit shift.
+ *
+ * @author Jon Chambers
+ */
+public class BitRotationLongTransformer implements LongTransformer {
+
+ private final long originalDistance;
+ private transient final int effectiveDistance;
+
+ /**
+ * Constructs a new bit rotation transformer that performs a circular rotation of bits by the given distance.
+ *
+ * @param distance the number of places by which to rotate integers
+ */
+ public BitRotationLongTransformer(final int distance) {
+ this.originalDistance = distance;
+
+ // Normalize the rotation distance to the range of [0, 64).
+ this.effectiveDistance = (int) ((distance % Long.SIZE) + (distance < 0 ? Long.SIZE : 0));
+ }
+
+ int getEffectiveDistance() {
+ return this.effectiveDistance;
+ }
+
+ /**
+ * Transforms the given long integer by rotating its bits to the left by a prescribed distance.
+ *
+ * @param l the long integer to transform
+ *
+ * @return the rotated long integer
+ */
+ @Override
+ public long transformLong(final long l) {
+ return (l << this.effectiveDistance) | (l >>> (Long.SIZE - this.effectiveDistance));
+ }
+
+ /**
+ * Reverses a bit rotation by shifting its bits to the right by a prescribed distance.
+ *
+ * @param l the long integer to un-rotate
+ *
+ * @return the original long integer
+ */
+ @Override
+ public long reverseTransformLong(final long l) {
+ return (l >>> this.effectiveDistance) | (l << (Long.SIZE - this.effectiveDistance));
+ }
+
+ @Override
+ public String toString() {
+ return String.format("BitRotationIntegerTransformer [distance=%d]", this.originalDistance);
+ }
+}
diff --git a/src/main/java/com/eatthepath/idobfuscator/IntegerCodec.java b/src/main/java/com/eatthepath/idobfuscator/IntegerCodec.java
index 6b43dcd..c3a5d5d 100644
--- a/src/main/java/com/eatthepath/idobfuscator/IntegerCodec.java
+++ b/src/main/java/com/eatthepath/idobfuscator/IntegerCodec.java
@@ -2,7 +2,7 @@
/**
* Reversibly transforms integers into strings and vice versa. This is usually the last (and sometimes only) step of an
- * obfuscation process.
+ * obfuscation pipeline.
*
* @author Jon Chambers
*
@@ -14,23 +14,19 @@ public interface IntegerCodec {
* Encodes the given integer as a string. Encoding must be reversible, and it must be true for all values of
* {@code i} that {@code i == decodeStringAsInteger(encodeIntegerAsString(i))}.
*
- * @param i the integer to represent as a string
+ * @param i the {@code int} to represent as a string
*
- * @return a string representation of the given integer
+ * @return a string representation of the given {@code int}
*/
- String encodeIntegerAsString(long i);
+ String encodeIntegerAsString(int i);
/**
- * Decodes the given string as an integer. Decoding must reverse the encoding process, and it must be true for
- * all values of {@code i} that {@code i == decodeStringAsInteger(encodeIntegerAsString(i))}.
+ * Decodes the given string as an integer. Decoding must reverse the encoding process, and it must be true
+ * for all values of {@code i} that {@code i == decodeStringAsInteger(encodeIntegerAsString(i))}.
*
- * Implementations of this method must throw an {@link IllegalArgumentException} if the decoded value cannot be
- * expressed with {@code nBits} bits (i.e. it is larger than the maximum value for the given number of bits or is
- * smaller than the minimum value).
+ * @param string the string to decode as an {@code int}
*
- * @param string the string to decode as an integer
- *
- * @return the integer represented by the given encoded string
+ * @return the {@code int} represented by the given encoded string
*/
- long decodeStringAsInteger(String string);
+ int decodeStringAsInteger(String string);
}
diff --git a/src/main/java/com/eatthepath/idobfuscator/IntegerObfuscationPipeline.java b/src/main/java/com/eatthepath/idobfuscator/IntegerObfuscationPipeline.java
index 712c6da..d17ccf8 100644
--- a/src/main/java/com/eatthepath/idobfuscator/IntegerObfuscationPipeline.java
+++ b/src/main/java/com/eatthepath/idobfuscator/IntegerObfuscationPipeline.java
@@ -4,7 +4,7 @@
/**
* An integer obfuscation pipeline combines any number of {@link IntegerTransformer} instances and exactly one
- * {@link IntegerCodec} to obfuscate and deobfuscate integers.
+ * {@link LongCodec} to obfuscate and deobfuscate integers.
*
* The output of an obfuscation pipeline is determined by the kind, number, order, and configuration of its
* transformers and by the kind and configuration of its codec. Changing the order of transformers, for example may
@@ -13,6 +13,7 @@
* @author Jon Chambers
*/
public class IntegerObfuscationPipeline {
+
private final IntegerTransformer[] transformers;
private final IntegerCodec codec;
@@ -23,8 +24,6 @@ public class IntegerObfuscationPipeline {
* {@code null}
* @param transformers any number of transformers to be applied to integers to be obfuscated or deobfuscated; may be
* empty or {@code null}
- *
- * @throws IllegalArgumentException if {@code nBits} does not fall between 1 and 64, inclusive
*/
public IntegerObfuscationPipeline(final IntegerCodec codec, final IntegerTransformer... transformers) {
Objects.requireNonNull(codec, "Codec must not be null");
@@ -45,8 +44,8 @@ public IntegerObfuscationPipeline(final IntegerCodec codec, final IntegerTransfo
*
* @throws IllegalArgumentException if the given integer cannot be expressed with this pipeline's bit size
*/
- public String obfuscate(final long i) {
- long encodedInteger = i;
+ public String obfuscate(final int i) {
+ int encodedInteger = i;
for (final IntegerTransformer obfuscator : this.transformers) {
encodedInteger = obfuscator.transformInteger(encodedInteger);
@@ -63,8 +62,8 @@ public String obfuscate(final long i) {
*
* @return the deobfuscated integer represented by the given string
*/
- public long deobfuscate(final String string) {
- long decodedInteger = this.codec.decodeStringAsInteger(string);
+ public int deobfuscate(final String string) {
+ int decodedInteger = this.codec.decodeStringAsInteger(string);
for (int i = this.transformers.length - 1; i >= 0; i--) {
decodedInteger = this.transformers[i].reverseTransformInteger(decodedInteger);
diff --git a/src/main/java/com/eatthepath/idobfuscator/IntegerTransformer.java b/src/main/java/com/eatthepath/idobfuscator/IntegerTransformer.java
index 090cf4c..2d0065d 100644
--- a/src/main/java/com/eatthepath/idobfuscator/IntegerTransformer.java
+++ b/src/main/java/com/eatthepath/idobfuscator/IntegerTransformer.java
@@ -17,14 +17,14 @@ public interface IntegerTransformer {
*
* @return the transformed integer
*/
- long transformInteger(long i);
+ int transformInteger(int i);
/**
- * Reverses the transformation applied by the {@link #transformInteger(long)} method.
+ * Reverses the transformation applied by the {@link #transformInteger(int)} method.
*
* @param i the transformed integer for which to reverse transformation
*
* @return the original integer
*/
- long reverseTransformInteger(long i);
+ int reverseTransformInteger(int i);
}
diff --git a/src/main/java/com/eatthepath/idobfuscator/LongCodec.java b/src/main/java/com/eatthepath/idobfuscator/LongCodec.java
new file mode 100644
index 0000000..ddc60ec
--- /dev/null
+++ b/src/main/java/com/eatthepath/idobfuscator/LongCodec.java
@@ -0,0 +1,32 @@
+package com.eatthepath.idobfuscator;
+
+/**
+ * Reversibly transforms long integers into strings and vice versa. This is usually the last (and sometimes only) step
+ * of an obfuscation pipeline.
+ *
+ * @author Jon Chambers
+ *
+ * @see LongObfuscationPipeline
+ */
+public interface LongCodec {
+
+ /**
+ * Encodes the given long integer as a string. Encoding must be reversible, and it must be true for all values of
+ * {@code l} that {@code l == decodeStringAsLong(encodeLongAsString(l))}.
+ *
+ * @param l the {@code long} to represent as a string
+ *
+ * @return a string representation of the given {@code long}
+ */
+ String encodeLongAsString(long l);
+
+ /**
+ *
Decodes the given string as a long integer. Decoding must reverse the encoding process, and it must be true
+ * for all values of {@code l} that {@code l == decodeStringAsLong(encodeLongAsString(l))}.
+ *
+ * @param string the string to decode as a {@code long}
+ *
+ * @return the {@code long} represented by the given encoded string
+ */
+ long decodeStringAsLong(String string);
+}
diff --git a/src/main/java/com/eatthepath/idobfuscator/LongObfuscationPipeline.java b/src/main/java/com/eatthepath/idobfuscator/LongObfuscationPipeline.java
new file mode 100644
index 0000000..1046a59
--- /dev/null
+++ b/src/main/java/com/eatthepath/idobfuscator/LongObfuscationPipeline.java
@@ -0,0 +1,75 @@
+package com.eatthepath.idobfuscator;
+
+import java.util.Objects;
+
+/**
+ * An integer obfuscation pipeline combines any number of {@link IntegerTransformer} instances and exactly one
+ * {@link LongCodec} to obfuscate and deobfuscate integers.
+ *
+ * The output of an obfuscation pipeline is determined by the kind, number, order, and configuration of its
+ * transformers and by the kind and configuration of its codec. Changing the order of transformers, for example may
+ * dramatically alter the output of the pipeline.
+ *
+ * @author Jon Chambers
+ */
+public class LongObfuscationPipeline {
+ private final LongTransformer[] transformers;
+ private final LongCodec codec;
+
+ /**
+ * Constructs a new obfuscation pipeline with the given codec and transformers.
+ *
+ * @param codec the codec to be used to convert potentially-obfuscated integers to and from strings; must not be
+ * {@code null}
+ * @param transformers any number of transformers to be applied to integers to be obfuscated or deobfuscated; may be
+ * empty or {@code null}
+ *
+ * @throws IllegalArgumentException if {@code nBits} does not fall between 1 and 64, inclusive
+ */
+ public LongObfuscationPipeline(final LongCodec codec, final LongTransformer... transformers) {
+ Objects.requireNonNull(codec, "Codec must not be null");
+
+ this.transformers = transformers;
+ this.codec = codec;
+ }
+
+ /**
+ * Reversibly obfuscates an integer. The pipeline obfuscates the given integer by applying each of this pipeline's
+ * transformers in sequence, and then converting the integer to a string with this pipeline's integer-to-string
+ * codec. If the given integer cannot be expressed with the number of bits provided at this pipeline's construction
+ * time, this methods will throw an {@link IllegalArgumentException}.
+ *
+ * @param i the integer to obfuscate
+ *
+ * @return a string representation of the obfuscated integer
+ *
+ * @throws IllegalArgumentException if the given integer cannot be expressed with this pipeline's bit size
+ */
+ public String obfuscate(final long i) {
+ long encodedInteger = i;
+
+ for (final LongTransformer obfuscator : this.transformers) {
+ encodedInteger = obfuscator.transformLong(encodedInteger);
+ }
+
+ return this.codec.encodeLongAsString(encodedInteger);
+ }
+
+ /**
+ * Deobfuscates an integer represented by the given string. The pipeline deobfuscates the integer by first decoding
+ * the string with this pipeline's codec, then applying each of the pipeline's transformers in reverse order,
+ *
+ * @param string the string to decode and deobfuscate
+ *
+ * @return the deobfuscated integer represented by the given string
+ */
+ public long deobfuscate(final String string) {
+ long decodedInteger = this.codec.decodeStringAsLong(string);
+
+ for (int i = this.transformers.length - 1; i >= 0; i--) {
+ decodedInteger = this.transformers[i].reverseTransformLong(decodedInteger);
+ }
+
+ return decodedInteger;
+ }
+}
diff --git a/src/main/java/com/eatthepath/idobfuscator/LongTransformer.java b/src/main/java/com/eatthepath/idobfuscator/LongTransformer.java
new file mode 100644
index 0000000..8bc8b26
--- /dev/null
+++ b/src/main/java/com/eatthepath/idobfuscator/LongTransformer.java
@@ -0,0 +1,30 @@
+package com.eatthepath.idobfuscator;
+
+/**
+ * Reversibly transforms a long integer it to a (presumably) different integer. Transformers are generally arranged into
+ * an {@link LongObfuscationPipeline}, which also couples the transformers with a {@link LongCodec}.
+ *
+ * @author Jon Chambers
+ *
+ * @see LongObfuscationPipeline
+ */
+public interface LongTransformer {
+
+ /**
+ * Transforms the given long integer into another integer.
+ *
+ * @param l the long integer to transform
+ *
+ * @return the transformed long integer
+ */
+ long transformLong(long l);
+
+ /**
+ * Reverses the transformation applied by the {@link #transformLong(long)} method.
+ *
+ * @param l the transformed long integer for which to reverse transformation
+ *
+ * @return the original long integer
+ */
+ long reverseTransformLong(long l);
+}
diff --git a/src/main/java/com/eatthepath/idobfuscator/MultiplicativeInverseIntegerTransformer.java b/src/main/java/com/eatthepath/idobfuscator/MultiplicativeInverseIntegerTransformer.java
index 33ee1b8..e29335e 100644
--- a/src/main/java/com/eatthepath/idobfuscator/MultiplicativeInverseIntegerTransformer.java
+++ b/src/main/java/com/eatthepath/idobfuscator/MultiplicativeInverseIntegerTransformer.java
@@ -1,7 +1,5 @@
package com.eatthepath.idobfuscator;
-import java.math.BigInteger;
-
/**
* Transforms integers by multiplying them by a "secret" multiplier and reverses transformations by multiplying by the
* secret's multiplicative inverse.
@@ -10,8 +8,8 @@
*/
public class MultiplicativeInverseIntegerTransformer implements IntegerTransformer {
- private final long multiplier;
- private final transient long inverse;
+ private final int multiplier;
+ private final transient int inverse;
/**
* Constructs a new multiplicative inverse transformer with the given multiplier. Multipliers must be positive and
@@ -20,7 +18,7 @@ public class MultiplicativeInverseIntegerTransformer implements IntegerTransform
*
* @param multiplier the multiplier to use when transforming integers
*/
- public MultiplicativeInverseIntegerTransformer(final long multiplier) {
+ public MultiplicativeInverseIntegerTransformer(final int multiplier) {
if (multiplier <= 0) {
throw new IllegalArgumentException("Multiplier must be positive");
} else if (multiplier % 2 == 0) {
@@ -40,51 +38,51 @@ public MultiplicativeInverseIntegerTransformer(final long multiplier) {
* @return the integer multiplied by this transformer's "secret" multiplier
*/
@Override
- public long transformInteger(final long i) {
+ public int transformInteger(final int i) {
return i * this.multiplier;
}
/**
- * Reverses a multiplication transformation by multiplying the given integer by the multiplicative inverse of this
- * transformer's "secret" multiplier.
+ * Reverses a multiplication transformation by multiplying the given integer by the multiplicative inverse of
+ * this transformer's "secret" multiplier.
*
* @param i the integer for which to reverse a multiplication transformation
*
* @return the original integer
*/
@Override
- public long reverseTransformInteger(final long i) {
+ public int reverseTransformInteger(final int i) {
return i * this.inverse;
}
- private static long getMultiplicativeInverse(final long multiplier) {
- BigInteger s = BigInteger.ZERO, previousS = BigInteger.ONE;
- BigInteger t = BigInteger.ONE, previousT = BigInteger.ZERO;
- BigInteger r = BigInteger.valueOf(multiplier), previousR = BigInteger.ONE.shiftLeft(Long.SIZE);
+ private static int getMultiplicativeInverse(final int multiplier) {
+ long s = 0, previousS = 1;
+ long t = 1, previousT = 0;
+ long r = multiplier, previousR = 1L << Integer.SIZE;
- while (!BigInteger.ZERO.equals(r)) {
- final BigInteger q = previousR.divide(r);
+ while (r != 0) {
+ final long q = previousR / r;
{
- final BigInteger tempR = r;
- r = previousR.subtract(q.multiply(r));
+ final long tempR = r;
+ r = previousR - (q * r);
previousR = tempR;
}
{
- final BigInteger tempS = s;
- s = previousS.subtract(q.multiply(s));
+ final long tempS = s;
+ s = previousS - (q * s);
previousS = tempS;
}
{
- final BigInteger tempT = t;
- t = previousT.subtract(q.multiply(t));
+ final long tempT = t;
+ t = previousT - (q * t);
previousT = tempT;
}
}
- return previousT.longValue();
+ return (int) previousT;
}
@Override
diff --git a/src/main/java/com/eatthepath/idobfuscator/MultiplicativeInverseLongTransformer.java b/src/main/java/com/eatthepath/idobfuscator/MultiplicativeInverseLongTransformer.java
new file mode 100644
index 0000000..adb09e2
--- /dev/null
+++ b/src/main/java/com/eatthepath/idobfuscator/MultiplicativeInverseLongTransformer.java
@@ -0,0 +1,94 @@
+package com.eatthepath.idobfuscator;
+
+import java.math.BigInteger;
+
+/**
+ * Transforms integers by multiplying them by a "secret" multiplier and reverses transformations by multiplying by the
+ * secret's multiplicative inverse.
+ *
+ * @author Jon Chambers
+ */
+public class MultiplicativeInverseLongTransformer implements LongTransformer {
+
+ private final long multiplier;
+ private final transient long inverse;
+
+ /**
+ * Constructs a new multiplicative inverse transformer with the given multiplier. Multipliers must be positive and
+ * coprime with the size of the number space (which, in this case, just means "must not be divisible by 2"). The
+ * multiplicative inverse of the given multiplier is derived automatically.
+ *
+ * @param multiplier the multiplier to use when transforming integers
+ */
+ public MultiplicativeInverseLongTransformer(final long multiplier) {
+ if (multiplier <= 0) {
+ throw new IllegalArgumentException("Multiplier must be positive");
+ } else if (multiplier % 2 == 0) {
+ throw new IllegalArgumentException("Multiplier must not be divisible by 2");
+ }
+
+ this.multiplier = multiplier;
+
+ this.inverse = getMultiplicativeInverse(this.multiplier);
+ }
+
+ /**
+ * Transforms the given long integer by multiplying it by this transformer's "secret" multiplier.
+ *
+ * @param l the long integer to transform
+ *
+ * @return the long integer multiplied by this transformer's "secret" multiplier
+ */
+ @Override
+ public long transformLong(final long l) {
+ return l * this.multiplier;
+ }
+
+ /**
+ * Reverses a multiplication transformation by multiplying the given long integer by the multiplicative inverse of
+ * this transformer's "secret" multiplier.
+ *
+ * @param l the long integer for which to reverse a multiplication transformation
+ *
+ * @return the original long integer
+ */
+ @Override
+ public long reverseTransformLong(final long l) {
+ return l * this.inverse;
+ }
+
+ private static long getMultiplicativeInverse(final long multiplier) {
+ BigInteger s = BigInteger.ZERO, previousS = BigInteger.ONE;
+ BigInteger t = BigInteger.ONE, previousT = BigInteger.ZERO;
+ BigInteger r = BigInteger.valueOf(multiplier), previousR = BigInteger.ONE.shiftLeft(Long.SIZE);
+
+ while (!BigInteger.ZERO.equals(r)) {
+ final BigInteger q = previousR.divide(r);
+
+ {
+ final BigInteger tempR = r;
+ r = previousR.subtract(q.multiply(r));
+ previousR = tempR;
+ }
+
+ {
+ final BigInteger tempS = s;
+ s = previousS.subtract(q.multiply(s));
+ previousS = tempS;
+ }
+
+ {
+ final BigInteger tempT = t;
+ t = previousT.subtract(q.multiply(t));
+ previousT = tempT;
+ }
+ }
+
+ return previousT.longValue();
+ }
+
+ @Override
+ public String toString() {
+ return String.format("MultiplicativeInverseLongTransformer [multiplier=%d]", this.multiplier);
+ }
+}
diff --git a/src/main/java/com/eatthepath/idobfuscator/OffsetIntegerTransformer.java b/src/main/java/com/eatthepath/idobfuscator/OffsetIntegerTransformer.java
index dac70ac..67f709d 100644
--- a/src/main/java/com/eatthepath/idobfuscator/OffsetIntegerTransformer.java
+++ b/src/main/java/com/eatthepath/idobfuscator/OffsetIntegerTransformer.java
@@ -7,7 +7,7 @@
*/
public class OffsetIntegerTransformer implements IntegerTransformer {
- private final long offset;
+ private final int offset;
/**
* Constructs a new offset transformer with the given offset. Offsets should be non-zero (otherwise the
@@ -15,7 +15,7 @@ public class OffsetIntegerTransformer implements IntegerTransformer {
*
* @param offset the offset to apply when transforming numbers
*/
- public OffsetIntegerTransformer(final long offset) {
+ public OffsetIntegerTransformer(final int offset) {
this.offset = offset;
}
@@ -27,7 +27,7 @@ public OffsetIntegerTransformer(final long offset) {
* @return the transformed integer
*/
@Override
- public long transformInteger(final long i) {
+ public int transformInteger(final int i) {
return i + this.offset;
}
@@ -39,7 +39,7 @@ public long transformInteger(final long i) {
* @return the original integer
*/
@Override
- public long reverseTransformInteger(final long i) {
+ public int reverseTransformInteger(final int i) {
return i - this.offset;
}
diff --git a/src/main/java/com/eatthepath/idobfuscator/OffsetLongTransformer.java b/src/main/java/com/eatthepath/idobfuscator/OffsetLongTransformer.java
new file mode 100644
index 0000000..2465e05
--- /dev/null
+++ b/src/main/java/com/eatthepath/idobfuscator/OffsetLongTransformer.java
@@ -0,0 +1,45 @@
+package com.eatthepath.idobfuscator;
+
+public class OffsetLongTransformer implements LongTransformer {
+
+ private final long offset;
+
+ /**
+ * Constructs a new offset transformer with the given offset. Offsets should be non-zero (otherwise the
+ * transformation would be a no-op), but zero offsets are technically allowed.
+ *
+ * @param offset the offset to apply when transforming numbers
+ */
+ public OffsetLongTransformer(final long offset) {
+ this.offset = offset;
+ }
+
+ /**
+ * Transforms the given integer by adding this transformer's offset to that integer.
+ *
+ * @param i the integer to offset
+ *
+ * @return the transformed integer
+ */
+ @Override
+ public long transformLong(final long i) {
+ return i + this.offset;
+ }
+
+ /**
+ * Reverses an offset transformation by subtracting this transformer's offset from the given integer.
+ *
+ * @param i the integer for which to reverse an offset transformation
+ *
+ * @return the original integer
+ */
+ @Override
+ public long reverseTransformLong(final long i) {
+ return i - this.offset;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("OffsetLongTransformer [offset=%d]", this.offset);
+ }
+}
diff --git a/src/main/java/com/eatthepath/idobfuscator/XorIntegerTransformer.java b/src/main/java/com/eatthepath/idobfuscator/XorIntegerTransformer.java
index 630f66a..effae98 100644
--- a/src/main/java/com/eatthepath/idobfuscator/XorIntegerTransformer.java
+++ b/src/main/java/com/eatthepath/idobfuscator/XorIntegerTransformer.java
@@ -1,20 +1,15 @@
package com.eatthepath.idobfuscator;
-/**
- * Transforms integers by performing a bitwise XOR operation with a given "secret" mask.
- *
- * @author Jon Chambers
- */
public class XorIntegerTransformer implements IntegerTransformer {
- private final long mask;
+ private final int mask;
/**
* Creates a new XOR transformer with the given "secret" mask.
*
* @param mask the mask to be applied when transforming numbers
*/
- public XorIntegerTransformer(final long mask) {
+ public XorIntegerTransformer(final int mask) {
this.mask = mask;
}
@@ -26,7 +21,7 @@ public XorIntegerTransformer(final long mask) {
* @return the transformed integer
*/
@Override
- public long transformInteger(final long i) {
+ public int transformInteger(final int i) {
return i ^ this.mask;
}
@@ -38,12 +33,12 @@ public long transformInteger(final long i) {
* @return the original integer
*/
@Override
- public long reverseTransformInteger(final long i) {
+ public int reverseTransformInteger(final int i) {
return i ^ this.mask;
}
@Override
public String toString() {
- return String.format("XorIntegerTransformer [mask=%x]", this.mask);
+ return String.format("XorLongTransformer [mask=%x]", this.mask);
}
}
diff --git a/src/main/java/com/eatthepath/idobfuscator/XorLongTransformer.java b/src/main/java/com/eatthepath/idobfuscator/XorLongTransformer.java
new file mode 100644
index 0000000..e10d89a
--- /dev/null
+++ b/src/main/java/com/eatthepath/idobfuscator/XorLongTransformer.java
@@ -0,0 +1,49 @@
+package com.eatthepath.idobfuscator;
+
+/**
+ * Transforms integers by performing a bitwise XOR operation with a given "secret" mask.
+ *
+ * @author Jon Chambers
+ */
+public class XorLongTransformer implements LongTransformer {
+
+ private final long mask;
+
+ /**
+ * Creates a new XOR transformer with the given "secret" mask.
+ *
+ * @param mask the mask to be applied when transforming numbers
+ */
+ public XorLongTransformer(final long mask) {
+ this.mask = mask;
+ }
+
+ /**
+ * Transforms the given integer by XOR-ing it with this transformer's "secret" mask.
+ *
+ * @param i the integer to transform
+ *
+ * @return the transformed integer
+ */
+ @Override
+ public long transformLong(final long i) {
+ return i ^ this.mask;
+ }
+
+ /**
+ * Reverses an XOR transformation by repeating the original XOR operation.
+ *
+ * @param i the integer for which to reverse an XOR transformation
+ *
+ * @return the original integer
+ */
+ @Override
+ public long reverseTransformLong(final long i) {
+ return i ^ this.mask;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("XorLongTransformer [mask=%x]", this.mask);
+ }
+}
diff --git a/src/test/java/com/eatthepath/idobfuscator/AlphabetCodecTest.java b/src/test/java/com/eatthepath/idobfuscator/AlphabetCodecTest.java
index 3ee1ba4..0dfb780 100644
--- a/src/test/java/com/eatthepath/idobfuscator/AlphabetCodecTest.java
+++ b/src/test/java/com/eatthepath/idobfuscator/AlphabetCodecTest.java
@@ -1,13 +1,30 @@
package com.eatthepath.idobfuscator;
-import org.junit.Test;
import com.eatthepath.idobfuscator.util.AlphabetBuilder;
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(JUnitParamsRunner.class)
+public class AlphabetCodecTest {
+
+ @Test
+ @Parameters({ "0", "1", "-1", "2147483647", "-2147483648"})
+ public void testEncodeDecodeInteger(final int i) {
+ final AlphabetCodec codec = new AlphabetCodec(new AlphabetBuilder().includeLowercaseLatinLetters().build());
+
+ assertEquals(i, codec.decodeStringAsInteger(codec.encodeIntegerAsString(i)));
+ }
-public class AlphabetCodecTest extends IntegerCodecTest {
+ @Test
+ @Parameters({ "0", "1", "-1", "9223372036854775807", "-9223372036854775808"})
+ public void testEncodeDecodeLong(final long l) {
+ final AlphabetCodec codec = new AlphabetCodec(new AlphabetBuilder().includeLowercaseLatinLetters().build());
- @Override
- protected IntegerCodec[] getCodecs() {
- return new AlphabetCodec[] { new AlphabetCodec(new AlphabetBuilder().includeLowercaseLatinLetters().build()) };
+ assertEquals(l, codec.decodeStringAsLong(codec.encodeLongAsString(l)));
}
@Test(expected = NullPointerException.class)
@@ -32,7 +49,7 @@ public void testAlphabetCodecRepeatedCharacters() {
@Test(expected = IllegalArgumentException.class)
public void testDecodeUnexpectedCharacter() {
- new AlphabetCodec('a', 'b', 'c', 'd').decodeStringAsInteger("x");
+ new AlphabetCodec('a', 'b', 'c', 'd').decodeStringAsLong("x");
}
@Test(expected = IllegalArgumentException.class)
@@ -43,7 +60,7 @@ public void testDecodeLongString() {
.includeAdditionalCharacters(' ', ',', '.')
.build();
- new AlphabetCodec(alphabet).decodeStringAsInteger(
+ new AlphabetCodec(alphabet).decodeStringAsLong(
"Even though this string contains legal characters, it is too long to represent a valid integer.");
}
}
diff --git a/src/test/java/com/eatthepath/idobfuscator/BitRotationIntegerTransformerTest.java b/src/test/java/com/eatthepath/idobfuscator/BitRotationIntegerTransformerTest.java
index f868d11..2657ecf 100644
--- a/src/test/java/com/eatthepath/idobfuscator/BitRotationIntegerTransformerTest.java
+++ b/src/test/java/com/eatthepath/idobfuscator/BitRotationIntegerTransformerTest.java
@@ -8,15 +8,15 @@ public class BitRotationIntegerTransformerTest extends IntegerTransformerTest {
@Test
public void testBitRotationIntegerTransformer() {
- for (int i = 0; i < Long.SIZE - 1; i++) {
+ for (int i = 0; i < Integer.SIZE - 1; i++) {
assertEquals(i, new BitRotationIntegerTransformer(i).getEffectiveDistance());
}
- for (int i = -1; i > -Long.SIZE; i--) {
- assertEquals(i + Long.SIZE, new BitRotationIntegerTransformer(i).getEffectiveDistance());
+ for (int i = -1; i > -Integer.SIZE; i--) {
+ assertEquals(i + Integer.SIZE, new BitRotationIntegerTransformer(i).getEffectiveDistance());
}
- assertEquals(3, new BitRotationIntegerTransformer(Long.SIZE + 3).getEffectiveDistance());
+ assertEquals(3, new BitRotationIntegerTransformer(Integer.SIZE + 3).getEffectiveDistance());
}
@Override
@@ -25,6 +25,7 @@ public IntegerTransformer[] getTransformers() {
new BitRotationIntegerTransformer(17),
new BitRotationIntegerTransformer(-17),
new BitRotationIntegerTransformer(0),
+ new BitRotationIntegerTransformer(31),
new BitRotationIntegerTransformer(32),
new BitRotationIntegerTransformer(65)
};
diff --git a/src/test/java/com/eatthepath/idobfuscator/BitRotationLongTransformerTest.java b/src/test/java/com/eatthepath/idobfuscator/BitRotationLongTransformerTest.java
new file mode 100644
index 0000000..bcb599b
--- /dev/null
+++ b/src/test/java/com/eatthepath/idobfuscator/BitRotationLongTransformerTest.java
@@ -0,0 +1,33 @@
+package com.eatthepath.idobfuscator;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class BitRotationLongTransformerTest extends LongTransformerTest {
+
+ @Test
+ public void testBitRotationLongTransformer() {
+ for (int i = 0; i < Long.SIZE - 1; i++) {
+ assertEquals(i, new BitRotationLongTransformer(i).getEffectiveDistance());
+ }
+
+ for (int i = -1; i > -Long.SIZE; i--) {
+ assertEquals(i + Long.SIZE, new BitRotationLongTransformer(i).getEffectiveDistance());
+ }
+
+ assertEquals(3, new BitRotationLongTransformer(Long.SIZE + 3).getEffectiveDistance());
+ }
+
+ @Override
+ public LongTransformer[] getTransformers() {
+ return new BitRotationLongTransformer[] {
+ new BitRotationLongTransformer(17),
+ new BitRotationLongTransformer(-17),
+ new BitRotationLongTransformer(0),
+ new BitRotationLongTransformer(31),
+ new BitRotationLongTransformer(32),
+ new BitRotationLongTransformer(65)
+ };
+ }
+}
diff --git a/src/test/java/com/eatthepath/idobfuscator/ExampleApp.java b/src/test/java/com/eatthepath/idobfuscator/ExampleApp.java
index 91a93ac..54bb423 100644
--- a/src/test/java/com/eatthepath/idobfuscator/ExampleApp.java
+++ b/src/test/java/com/eatthepath/idobfuscator/ExampleApp.java
@@ -14,21 +14,20 @@ public static void main(final String[] args) {
.build());
final MultiplicativeInverseIntegerTransformer inverse =
- new MultiplicativeInverseIntegerTransformer(0x1909719a5ee544adL);
+ new MultiplicativeInverseIntegerTransformer(0x5ee544ad);
final BitRotationIntegerTransformer rotate = new BitRotationIntegerTransformer(22);
- final OffsetIntegerTransformer offset = new OffsetIntegerTransformer(0xe45c2f833b2f0474L);
- final XorIntegerTransformer xor = new XorIntegerTransformer(0xe41c643d0593242L);
-
+ final OffsetIntegerTransformer offset = new OffsetIntegerTransformer(0x3b2f0474);
+ final XorIntegerTransformer xor = new XorIntegerTransformer(0xd0593242);
final IntegerObfuscationPipeline pipeline =
new IntegerObfuscationPipeline(codec, inverse, rotate, offset, xor);
- System.out.println("| ID | Obfuscated ID |");
- System.out.println("|----|----------------|");
+ System.out.println("| ID | Obfuscated ID |");
+ System.out.println("|----|---------------|");
for (int id = 0; id < 10; id++) {
- System.out.format("| %d | %-14s |\n", id, pipeline.obfuscate(id));
+ System.out.format("| %d | %-13s |\n", id, pipeline.obfuscate(id));
assert id == pipeline.deobfuscate(pipeline.obfuscate(id));
}
}
diff --git a/src/test/java/com/eatthepath/idobfuscator/IntegerCodecTest.java b/src/test/java/com/eatthepath/idobfuscator/IntegerCodecTest.java
deleted file mode 100644
index 22ba40f..0000000
--- a/src/test/java/com/eatthepath/idobfuscator/IntegerCodecTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.eatthepath.idobfuscator;
-
-import junitparams.JUnitParamsRunner;
-import junitparams.Parameters;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
-@RunWith(JUnitParamsRunner.class)
-public abstract class IntegerCodecTest {
-
- protected abstract IntegerCodec[] getCodecs();
-
- @Test
- @Parameters(method = "getParametersForEncodeDecode")
- public void testEncodeDecode(final IntegerCodec codec, final long l) {
- assertEquals(l, codec.decodeStringAsInteger(codec.encodeIntegerAsString(l)));
- }
-
- @SuppressWarnings("unused")
- private List> getParametersForEncodeDecode() {
- final List> parameters = new ArrayList<>();
-
- for (final IntegerCodec codec : this.getCodecs()) {
- parameters.add(Arrays.asList(codec, 0));
- parameters.add(Arrays.asList(codec, 1));
- parameters.add(Arrays.asList(codec, -1));
- parameters.add(Arrays.asList(codec, Long.MAX_VALUE));
- parameters.add(Arrays.asList(codec, Long.MIN_VALUE));
- }
-
- return parameters;
- }
-}
diff --git a/src/test/java/com/eatthepath/idobfuscator/IntegerObfuscationPipelineTest.java b/src/test/java/com/eatthepath/idobfuscator/IntegerObfuscationPipelineTest.java
index f557460..46ba8e7 100644
--- a/src/test/java/com/eatthepath/idobfuscator/IntegerObfuscationPipelineTest.java
+++ b/src/test/java/com/eatthepath/idobfuscator/IntegerObfuscationPipelineTest.java
@@ -5,15 +5,11 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
import static org.junit.Assert.assertEquals;
@RunWith(JUnitParamsRunner.class)
public class IntegerObfuscationPipelineTest {
-
+
private final AlphabetCodec codec = new AlphabetCodec('1', '2', '3', '4', '5', '6', 'a', 'b', 'c', 'd', 'e', 'f');
private final XorIntegerTransformer xorObfuscator = new XorIntegerTransformer(3455555);
private final MultiplicativeInverseIntegerTransformer multiplicativeInverseObfuscator =
@@ -25,8 +21,8 @@ public void testIntegerObfuscationPipelineNullCodec() {
}
@Test
- @Parameters(method = "getParameters")
- public void testObfuscateDeobfuscate(final long l) {
+ @Parameters({ "0", "1", "-1", "2147483647", "-2147483648"})
+ public void testObfuscateDeobfuscate(final int l) {
final IntegerObfuscationPipeline pipeline =
new IntegerObfuscationPipeline(this.codec, this.xorObfuscator, this.multiplicativeInverseObfuscator);
@@ -34,23 +30,10 @@ public void testObfuscateDeobfuscate(final long l) {
}
@Test
- @Parameters(method = "getParameters")
- public void testObfuscateDeobfuscateCodecOnly(final long l) {
+ @Parameters({ "0", "1", "-1", "2147483647", "-2147483648"})
+ public void testObfuscateDeobfuscateCodecOnly(final int l) {
final IntegerObfuscationPipeline pipeline = new IntegerObfuscationPipeline(this.codec);
assertEquals(l, pipeline.deobfuscate(pipeline.obfuscate(l)));
}
-
- @SuppressWarnings("unused")
- private List> getParameters() {
- final List> parameters = new ArrayList<>();
-
- parameters.add(Collections.singletonList(0));
- parameters.add(Collections.singletonList(1));
- parameters.add(Collections.singletonList(-1));
- parameters.add(Collections.singletonList(Long.MAX_VALUE));
- parameters.add(Collections.singletonList(Long.MIN_VALUE));
-
- return parameters;
- }
}
diff --git a/src/test/java/com/eatthepath/idobfuscator/IntegerTransformerTest.java b/src/test/java/com/eatthepath/idobfuscator/IntegerTransformerTest.java
index fb7a0b1..e2c7606 100644
--- a/src/test/java/com/eatthepath/idobfuscator/IntegerTransformerTest.java
+++ b/src/test/java/com/eatthepath/idobfuscator/IntegerTransformerTest.java
@@ -18,8 +18,8 @@ public abstract class IntegerTransformerTest {
@Test
@Parameters(method = "getParametersForTransformInteger")
- public void testTransformReverseTransform(final IntegerTransformer transformer, final long l) {
- assertEquals(l, transformer.reverseTransformInteger(transformer.transformInteger(l)));
+ public void testTransformReverseTransform(final IntegerTransformer transformer, final int i) {
+ assertEquals(i, transformer.reverseTransformInteger(transformer.transformInteger(i)));
}
@SuppressWarnings("unused")
@@ -30,8 +30,8 @@ private List> getParametersForTransformInteger() {
parameters.add(Arrays.asList(transformer, 0));
parameters.add(Arrays.asList(transformer, 1));
parameters.add(Arrays.asList(transformer, -1));
- parameters.add(Arrays.asList(transformer, Long.MAX_VALUE));
- parameters.add(Arrays.asList(transformer, Long.MIN_VALUE));
+ parameters.add(Arrays.asList(transformer, Integer.MAX_VALUE));
+ parameters.add(Arrays.asList(transformer, Integer.MIN_VALUE));
}
return parameters;
diff --git a/src/test/java/com/eatthepath/idobfuscator/LongObfuscationPipelineTest.java b/src/test/java/com/eatthepath/idobfuscator/LongObfuscationPipelineTest.java
new file mode 100644
index 0000000..10ae8d4
--- /dev/null
+++ b/src/test/java/com/eatthepath/idobfuscator/LongObfuscationPipelineTest.java
@@ -0,0 +1,39 @@
+package com.eatthepath.idobfuscator;
+
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(JUnitParamsRunner.class)
+public class LongObfuscationPipelineTest {
+
+ private final AlphabetCodec codec = new AlphabetCodec('1', '2', '3', '4', '5', '6', 'a', 'b', 'c', 'd', 'e', 'f');
+ private final XorLongTransformer xorObfuscator = new XorLongTransformer(3455555);
+ private final MultiplicativeInverseLongTransformer multiplicativeInverseObfuscator =
+ new MultiplicativeInverseLongTransformer(873795);
+
+ @Test(expected = NullPointerException.class)
+ public void testIntegerObfuscationPipelineNullCodec() {
+ new LongObfuscationPipeline(null);
+ }
+
+ @Test
+ @Parameters({ "0", "1", "-1", "9223372036854775807", "-9223372036854775808"})
+ public void testObfuscateDeobfuscate(final long l) {
+ final LongObfuscationPipeline pipeline =
+ new LongObfuscationPipeline(this.codec, this.xorObfuscator, this.multiplicativeInverseObfuscator);
+
+ assertEquals(l, pipeline.deobfuscate(pipeline.obfuscate(l)));
+ }
+
+ @Test
+ @Parameters({ "0", "1", "-1", "9223372036854775807", "-9223372036854775808"})
+ public void testObfuscateDeobfuscateCodecOnly(final long l) {
+ final LongObfuscationPipeline pipeline = new LongObfuscationPipeline(this.codec);
+
+ assertEquals(l, pipeline.deobfuscate(pipeline.obfuscate(l)));
+ }
+}
diff --git a/src/test/java/com/eatthepath/idobfuscator/LongTransformerTest.java b/src/test/java/com/eatthepath/idobfuscator/LongTransformerTest.java
new file mode 100644
index 0000000..58925e7
--- /dev/null
+++ b/src/test/java/com/eatthepath/idobfuscator/LongTransformerTest.java
@@ -0,0 +1,39 @@
+package com.eatthepath.idobfuscator;
+
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(JUnitParamsRunner.class)
+public abstract class LongTransformerTest {
+
+ protected abstract LongTransformer[] getTransformers();
+
+ @Test
+ @Parameters(method = "getParametersForTransformLong")
+ public void testTransformReverseTransform(final LongTransformer transformer, final long l) {
+ assertEquals(l, transformer.reverseTransformLong(transformer.transformLong(l)));
+ }
+
+ @SuppressWarnings("unused")
+ private List> getParametersForTransformLong() {
+ final List> parameters = new ArrayList<>();
+
+ for (final LongTransformer transformer : this.getTransformers()) {
+ parameters.add(Arrays.asList(transformer, 0));
+ parameters.add(Arrays.asList(transformer, 1));
+ parameters.add(Arrays.asList(transformer, -1));
+ parameters.add(Arrays.asList(transformer, Long.MAX_VALUE));
+ parameters.add(Arrays.asList(transformer, Long.MIN_VALUE));
+ }
+
+ return parameters;
+ }
+}
diff --git a/src/test/java/com/eatthepath/idobfuscator/MultiplicativeInverseIntegerTransformerTest.java b/src/test/java/com/eatthepath/idobfuscator/MultiplicativeInverseIntegerTransformerTest.java
index ce9f55a..091be7f 100644
--- a/src/test/java/com/eatthepath/idobfuscator/MultiplicativeInverseIntegerTransformerTest.java
+++ b/src/test/java/com/eatthepath/idobfuscator/MultiplicativeInverseIntegerTransformerTest.java
@@ -21,7 +21,7 @@ public void testMultiplicativeInverseIntegerTransformerEvenMultiplier() {
@Override
public IntegerTransformer[] getTransformers() {
- final long[] multipliers = new long[] { 77, Integer.MAX_VALUE };
+ final int[] multipliers = new int[] { 77, Integer.MAX_VALUE };
final IntegerTransformer[] transformers = new MultiplicativeInverseIntegerTransformer[multipliers.length];
for (int i = 0; i < multipliers.length; i++) {
diff --git a/src/test/java/com/eatthepath/idobfuscator/MultiplicativeInverseLongTransformerTest.java b/src/test/java/com/eatthepath/idobfuscator/MultiplicativeInverseLongTransformerTest.java
new file mode 100644
index 0000000..33e03fc
--- /dev/null
+++ b/src/test/java/com/eatthepath/idobfuscator/MultiplicativeInverseLongTransformerTest.java
@@ -0,0 +1,33 @@
+package com.eatthepath.idobfuscator;
+
+import org.junit.Test;
+
+public class MultiplicativeInverseLongTransformerTest extends LongTransformerTest {
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testMultiplicativeInverseLongTransformerZeroMultiplier() {
+ new MultiplicativeInverseLongTransformer(0);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testMultiplicativeInverseLongTransformerNegativeMultiplier() {
+ new MultiplicativeInverseLongTransformer(-77);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testMultiplicativeInverseLongTransformerEvenMultiplier() {
+ new MultiplicativeInverseLongTransformer(862983572);
+ }
+
+ @Override
+ public LongTransformer[] getTransformers() {
+ final long[] multipliers = new long[] { 77, Long.MAX_VALUE };
+ final LongTransformer[] transformers = new MultiplicativeInverseLongTransformer[multipliers.length];
+
+ for (int i = 0; i < multipliers.length; i++) {
+ transformers[i] = new MultiplicativeInverseLongTransformer(multipliers[i]);
+ }
+
+ return transformers;
+ }
+}
diff --git a/src/test/java/com/eatthepath/idobfuscator/OffsetIntegerTransformerTest.java b/src/test/java/com/eatthepath/idobfuscator/OffsetIntegerTransformerTest.java
index 068fb80..932ad87 100644
--- a/src/test/java/com/eatthepath/idobfuscator/OffsetIntegerTransformerTest.java
+++ b/src/test/java/com/eatthepath/idobfuscator/OffsetIntegerTransformerTest.java
@@ -4,7 +4,7 @@ public class OffsetIntegerTransformerTest extends IntegerTransformerTest {
@Override
public IntegerTransformer[] getTransformers() {
- final long[] offsets = new long[] { 1, 17, -876, Long.MAX_VALUE, Long.MIN_VALUE };
+ final int[] offsets = new int[] { 1, 17, -876, Integer.MAX_VALUE, Integer.MIN_VALUE };
final IntegerTransformer[] transformers = new IntegerTransformer[offsets.length];
for (int i = 0; i < offsets.length; i++) {
diff --git a/src/test/java/com/eatthepath/idobfuscator/OffsetLongTransformerTest.java b/src/test/java/com/eatthepath/idobfuscator/OffsetLongTransformerTest.java
new file mode 100644
index 0000000..0521efd
--- /dev/null
+++ b/src/test/java/com/eatthepath/idobfuscator/OffsetLongTransformerTest.java
@@ -0,0 +1,16 @@
+package com.eatthepath.idobfuscator;
+
+public class OffsetLongTransformerTest extends LongTransformerTest {
+
+ @Override
+ public LongTransformer[] getTransformers() {
+ final long[] offsets = new long[] { 1, 17, -876, Long.MAX_VALUE, Long.MIN_VALUE };
+ final LongTransformer[] transformers = new LongTransformer[offsets.length];
+
+ for (int i = 0; i < offsets.length; i++) {
+ transformers[i] = new OffsetLongTransformer(offsets[i]);
+ }
+
+ return transformers;
+ }
+}
diff --git a/src/test/java/com/eatthepath/idobfuscator/XorIntegerTransformerTest.java b/src/test/java/com/eatthepath/idobfuscator/XorIntegerTransformerTest.java
index a1d87c6..e7b7a0e 100644
--- a/src/test/java/com/eatthepath/idobfuscator/XorIntegerTransformerTest.java
+++ b/src/test/java/com/eatthepath/idobfuscator/XorIntegerTransformerTest.java
@@ -4,7 +4,7 @@ public class XorIntegerTransformerTest extends IntegerTransformerTest {
@Override
public IntegerTransformer[] getTransformers() {
- final long[] masks = new long[] { 0, 1, -7, 77, Long.MAX_VALUE, Long.MIN_VALUE };
+ final int[] masks = new int[] { 0, 1, -7, 77, Integer.MAX_VALUE, Integer.MIN_VALUE };
final IntegerTransformer[] transformers = new IntegerTransformer[masks.length];
for (int i = 0; i < masks.length; i++) {
diff --git a/src/test/java/com/eatthepath/idobfuscator/XorLongTransformerTest.java b/src/test/java/com/eatthepath/idobfuscator/XorLongTransformerTest.java
new file mode 100644
index 0000000..9f833bc
--- /dev/null
+++ b/src/test/java/com/eatthepath/idobfuscator/XorLongTransformerTest.java
@@ -0,0 +1,16 @@
+package com.eatthepath.idobfuscator;
+
+public class XorLongTransformerTest extends LongTransformerTest {
+
+ @Override
+ public LongTransformer[] getTransformers() {
+ final long[] masks = new long[] { 0, 1, -7, 77, Long.MAX_VALUE, Long.MIN_VALUE };
+ final LongTransformer[] transformers = new LongTransformer[masks.length];
+
+ for (int i = 0; i < masks.length; i++) {
+ transformers[i] = new XorLongTransformer(masks[i]);
+ }
+
+ return transformers;
+ }
+}