forked from jchambers/id-obfuscator
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit fd51ec1
Showing
13 changed files
with
342 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Maven output directories | ||
target | ||
|
||
# macOS detritus | ||
.DS_Store | ||
|
||
# Eclipse project files | ||
.classpath | ||
.project | ||
.settings | ||
|
||
# Things that might appear in the gh-pages branch | ||
_site | ||
|
||
# IntelliJ project files | ||
*.iml | ||
.idea/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<groupId>com.eatthepath</groupId> | ||
<artifactId>id-obfuscator</artifactId> | ||
<version>0.0.1-SNAPSHOT</version> | ||
<name>ID Obfuscator</name> | ||
<description>A Java library for obfuscating numerical identifiers</description> | ||
<dependencies> | ||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<version>4.12</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
</project> |
70 changes: 70 additions & 0 deletions
70
src/main/java/com/eatthepath/idobfuscator/AlphabetCodec.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package com.eatthepath.idobfuscator; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
|
||
public class AlphabetCodec implements IntegerCodec { | ||
|
||
private final char[] alphabet; | ||
private final Map<Character, Integer> charactersToValues = new HashMap<>(); | ||
|
||
public AlphabetCodec(final char... alphabet) { | ||
Objects.requireNonNull(alphabet, "Alphabet must not be null."); | ||
|
||
if (alphabet.length < 2) { | ||
throw new IllegalArgumentException("Alphabet must contain at least two characters"); | ||
} | ||
|
||
this.alphabet = alphabet; | ||
|
||
for (int i = 0; i < alphabet.length; i++) { | ||
this.charactersToValues.put(alphabet[i], i); | ||
} | ||
} | ||
|
||
@Override | ||
public String encodeIntegerAsString(final int i) { | ||
final String encodedString; | ||
|
||
if (i == 0) { | ||
encodedString = new String(new char[] { this.alphabet[0] }); | ||
} else { | ||
long workingCopy = i & 0xffffffffL; | ||
final StringBuilder builder = new StringBuilder(); | ||
|
||
while (workingCopy != 0) { | ||
builder.insert(0, this.alphabet[(int) (workingCopy % this.alphabet.length)]); | ||
workingCopy /= this.alphabet.length; | ||
} | ||
|
||
encodedString = builder.toString(); | ||
} | ||
|
||
return encodedString; | ||
} | ||
|
||
@Override | ||
public int decodeStringAsInteger(final String string) { | ||
final char[] chars = string.toCharArray(); | ||
long decoded = 0; | ||
int exponent = chars.length - 1; | ||
|
||
for (final char c : chars) { | ||
final int x = this.charactersToValues.get(c); | ||
decoded += x * exponentiate(this.alphabet.length, exponent--); | ||
} | ||
|
||
return (int) decoded; | ||
} | ||
|
||
static long exponentiate(final int x, final int exponent) { | ||
long exponentiated = 1; | ||
|
||
for (int i = 0; i < exponent; i++) { | ||
exponentiated *= x; | ||
} | ||
|
||
return exponentiated; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.eatthepath.idobfuscator; | ||
|
||
public interface IntegerCodec { | ||
String encodeIntegerAsString(int i); | ||
|
||
int decodeStringAsInteger(String string); | ||
} |
31 changes: 31 additions & 0 deletions
31
src/main/java/com/eatthepath/idobfuscator/IntegerObfuscationPipeline.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.eatthepath.idobfuscator; | ||
|
||
public class IntegerObfuscationPipeline { | ||
private final IntegerObfuscator[] obfuscators; | ||
private final IntegerCodec codec; | ||
|
||
public IntegerObfuscationPipeline(final IntegerCodec codec, final IntegerObfuscator... obfuscators) { | ||
this.obfuscators = obfuscators; | ||
this.codec = codec; | ||
} | ||
|
||
public String obuscate(final int i) { | ||
int encodedInteger = i; | ||
|
||
for (final IntegerObfuscator obfuscator : this.obfuscators) { | ||
encodedInteger = obfuscator.obfuscate(encodedInteger); | ||
} | ||
|
||
return this.codec.encodeIntegerAsString(encodedInteger); | ||
} | ||
|
||
public int deobfuscate(final String string) { | ||
int decodedInteger = this.codec.decodeStringAsInteger(string); | ||
|
||
for (int i = this.obfuscators.length - 1; i >= 0; i--) { | ||
decodedInteger = this.obfuscators[i].deobfuscate(decodedInteger); | ||
} | ||
|
||
return decodedInteger; | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
src/main/java/com/eatthepath/idobfuscator/IntegerObfuscator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.eatthepath.idobfuscator; | ||
|
||
public interface IntegerObfuscator { | ||
int obfuscate(int i); | ||
|
||
int deobfuscate(int i); | ||
} |
54 changes: 54 additions & 0 deletions
54
src/main/java/com/eatthepath/idobfuscator/MultiplicativeInverseIntegerObfuscator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.eatthepath.idobfuscator; | ||
|
||
public class MultiplicativeInverseIntegerObfuscator implements IntegerObfuscator { | ||
|
||
final int multiplier; | ||
final int inverse; | ||
|
||
public MultiplicativeInverseIntegerObfuscator(final int multiplier) { | ||
if (multiplier <= 0) { | ||
throw new IllegalArgumentException("Multiplier must be positive"); | ||
} | ||
|
||
this.multiplier = multiplier; | ||
this.inverse = this.getMultiplicativeInverse(multiplier); | ||
} | ||
|
||
public int obfuscate(final int i) { | ||
return i * this.multiplier; | ||
} | ||
|
||
public int deobfuscate(final int i) { | ||
return i * this.inverse; | ||
} | ||
|
||
private int getMultiplicativeInverse(final int multiplier) { | ||
long s = 0, previousS = 1; | ||
long t = 1, previousT = 0; | ||
long r = multiplier, previousR = (1L << Integer.SIZE); | ||
|
||
while (r != 0) { | ||
final long q = previousR / r; | ||
|
||
{ | ||
final long tempR = r; | ||
r = previousR - (q * r); | ||
previousR = tempR; | ||
} | ||
|
||
{ | ||
final long tempS = s; | ||
s = previousS - (q * s); | ||
previousS = tempS; | ||
} | ||
|
||
{ | ||
final long tempT = t; | ||
t = previousT - (q * t); | ||
previousT = tempT; | ||
} | ||
} | ||
|
||
return (int) previousT; | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
src/main/java/com/eatthepath/idobfuscator/XorIntegerObfuscator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.eatthepath.idobfuscator; | ||
|
||
public class XorIntegerObfuscator implements IntegerObfuscator { | ||
|
||
private final int mask; | ||
|
||
public XorIntegerObfuscator(final int mask) { | ||
this.mask = mask; | ||
} | ||
|
||
@Override | ||
public int obfuscate(final int i) { | ||
return i ^ this.mask; | ||
} | ||
|
||
@Override | ||
public int deobfuscate(final int i) { | ||
return i ^ this.mask; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
/** | ||
* @author <a href="https://github.com/jchambers">Jon Chambers</a> | ||
* | ||
*/ | ||
package com.eatthepath.idobfuscator; |
41 changes: 41 additions & 0 deletions
41
src/test/java/com/eatthepath/idobfuscator/AlphabetCodecTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package com.eatthepath.idobfuscator; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
import org.junit.Test; | ||
|
||
public class AlphabetCodecTest { | ||
|
||
@Test(expected = NullPointerException.class) | ||
public void testAlphabetCodecNullAlphabet() { | ||
new AlphabetCodec(null); | ||
} | ||
|
||
@Test(expected = IllegalArgumentException.class) | ||
public void testAlphabetCodecEmptyAlphabet() { | ||
new AlphabetCodec(); | ||
} | ||
|
||
@Test(expected = IllegalArgumentException.class) | ||
public void testAlphabetCodecShortAlphabet() { | ||
new AlphabetCodec('a'); | ||
} | ||
|
||
@Test | ||
public void testEncodeDecodeInteger() { | ||
final AlphabetCodec codec = new AlphabetCodec('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', | ||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'); | ||
final int[] ids = { 0, 1, 2, 7, 86753, Integer.MAX_VALUE, -77, Integer.MIN_VALUE }; | ||
|
||
for (final int id : ids) { | ||
assertEquals(id, codec.decodeStringAsInteger(codec.encodeIntegerAsString(id))); | ||
} | ||
} | ||
|
||
@Test | ||
public void testExponentiate() { | ||
assertEquals(1, AlphabetCodec.exponentiate(17, 0)); | ||
assertEquals(17, AlphabetCodec.exponentiate(17, 1)); | ||
assertEquals(289, AlphabetCodec.exponentiate(17, 2)); | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
src/test/java/com/eatthepath/idobfuscator/IntegerObfuscationPipelineTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.eatthepath.idobfuscator; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
import org.junit.Test; | ||
|
||
public class IntegerObfuscationPipelineTest { | ||
|
||
private final AlphabetCodec codec = new AlphabetCodec('1', '2', '3', '4', '5', '6', 'a', 'b', 'c', 'd', 'e', 'f'); | ||
private final XorIntegerObfuscator xorObfuscator = new XorIntegerObfuscator(3455555); | ||
private final MultiplicativeInverseIntegerObfuscator multiplicativeInverseObfuscator = | ||
new MultiplicativeInverseIntegerObfuscator(873795); | ||
|
||
@Test | ||
public void testObfuscateDeobfuscate() { | ||
final IntegerObfuscationPipeline pipeline = new IntegerObfuscationPipeline(this.codec, this.xorObfuscator, this.multiplicativeInverseObfuscator); | ||
|
||
for (final int id : new int[] {0, 1, 77, -77, Integer.MAX_VALUE, Integer.MIN_VALUE }) { | ||
assertEquals(id, pipeline.deobfuscate(pipeline.obuscate(id))); | ||
} | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
src/test/java/com/eatthepath/idobfuscator/MultiplicativeInverseIntegerObfuscatorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.eatthepath.idobfuscator; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
import org.junit.Test; | ||
|
||
public class MultiplicativeInverseIntegerObfuscatorTest { | ||
|
||
@Test(expected = IllegalArgumentException.class) | ||
public void testMultiplicativeInverseIntegerObfuscatorZeroMultiplier() { | ||
new MultiplicativeInverseIntegerObfuscator(0); | ||
} | ||
|
||
@Test(expected = IllegalArgumentException.class) | ||
public void testMultiplicativeInverseIntegerObfuscatorNegativeMultiplier() { | ||
new MultiplicativeInverseIntegerObfuscator(-77); | ||
} | ||
|
||
@Test | ||
public void testObfuscateDeobfuscate() { | ||
final int[] multipliers = { 77, Integer.MAX_VALUE }; | ||
final int[] ids = { 7890, -7458392, Integer.MAX_VALUE, Integer.MIN_VALUE }; | ||
|
||
for (final int multiplier : multipliers) { | ||
for (final int id : ids) { | ||
final MultiplicativeInverseIntegerObfuscator obfuscator = | ||
new MultiplicativeInverseIntegerObfuscator(multiplier); | ||
|
||
assertEquals(id, obfuscator.deobfuscate(obfuscator.obfuscate(id))); | ||
} | ||
} | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/test/java/com/eatthepath/idobfuscator/XorIntegerObfuscatorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.eatthepath.idobfuscator; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
import org.junit.Test; | ||
|
||
public class XorIntegerObfuscatorTest { | ||
|
||
@Test | ||
public void test() { | ||
for (final int mask : new int[] { 0, 1, -7, 77, Integer.MAX_VALUE, Integer.MIN_VALUE }) { | ||
final XorIntegerObfuscator obfuscator = new XorIntegerObfuscator(mask); | ||
|
||
for (final int id : new int[] { 0, 1, -7, 77, Integer.MAX_VALUE, Integer.MIN_VALUE }) { | ||
assertEquals(id, obfuscator.deobfuscate(obfuscator.deobfuscate(id))); | ||
} | ||
} | ||
} | ||
} |