package javastory.cryptography; import static com.google.common.base.Preconditions.checkNotNull; /** * Provides methods for the custom encryption routines of the game. */ public class CustomEncryption { private CustomEncryption() { } /** * Encrypts a byte array. The specified array will be modified. * * @param data * the array to encrypt * * @throws NullPointerException * if 'data' is null. */ public static void encrypt(final byte[] data) { checkNotNull(data); final int length = data.length; final byte truncatedLength = (byte) length; for (int j = 0; j < 6; j++) { if ((j & 1) != 0) { oddEncryptTransform(data, length, truncatedLength); } else { evenEncryptTransform(data, length, truncatedLength); } } } private static void oddEncryptTransform(final byte[] data, final int length, byte lengthByte) { byte remember = 0; for (int i = length - 1; i >= 0; i--) { byte current = rollLeft(data[i], 4); current += lengthByte; current ^= remember; remember = current; current ^= 0x13; current = rollRight(current, 3); data[i] = current; lengthByte--; } } private static void evenEncryptTransform(final byte[] data, final int length, byte lengthByte) { byte remember = 0; for (int i = 0; i < length; i++) { byte current = rollLeft(data[i], 3); current += lengthByte; current ^= remember; remember = current; current = rollRight(current, lengthByte); current = (byte) ~current; current += 0x48; data[i] = current; lengthByte--; } } /** * Decrypts a byte array. The specified array will be modified. * * @param data * the array to decrypt * * @throws NullPointerException * if 'data' is null. */ public static void decrypt(final byte[] data) { checkNotNull(data); final int length = data.length; final byte truncatedLength = (byte) length; for (int j = 1; j <= 6; j++) { if ((j & 1) != 0) { oddDecryptTransform(data, length, truncatedLength); } else { evenDecryptTransform(data, length, truncatedLength); } } } private static void oddDecryptTransform(final byte[] data, final int length, byte lengthByte) { byte remember = 0; for (int i = length - 1; i >= 0; i--) { byte current = rollLeft(data[i], 3); current ^= 0x13; final byte tmp = current; current ^= remember; remember = tmp; current -= lengthByte; data[i] = rollRight(current, 4); lengthByte--; } } private static void evenDecryptTransform(final byte[] data, final int length, byte lengthByte) { byte remember = 0; for (int i = 0; i < length; i++) { byte current = data[i]; current -= 0x48; current = (byte) ~current; current = rollLeft(current, lengthByte); final byte tmp = current; current ^= remember; remember = tmp; current -= lengthByte; data[i] = rollRight(current, 3); lengthByte--; } } private static byte rollLeft(final byte b, final int count) { final int tmp = b << (count & 7); return (byte) (tmp | tmp >>> 8); } private static byte rollRight(final byte b, final int count) { final int tmp = b << 8 - (count & 7); return (byte) (tmp | tmp >>> 8); } }