diff --git a/Server/src/main/core/cache/Cache.java b/Server/src/main/core/cache/Cache.java index ce4ed3c25..3459d58b9 100644 --- a/Server/src/main/core/cache/Cache.java +++ b/Server/src/main/core/cache/Cache.java @@ -145,7 +145,7 @@ public final class Cache { buffer.putInt(0); continue; } - buffer.putInt(cacheFileManagers[index].getInformation().getInformationContainer().getCrc()); + buffer.putInt(cacheFileManagers[index].getInformation().informationContainer.getCrc()); buffer.putInt(cacheFileManagers[index].getInformation().getRevision()); } return buffer.array(); diff --git a/Server/src/main/core/cache/CacheFile.java b/Server/src/main/core/cache/CacheFile.java index a03642895..bd21a8a0d 100644 --- a/Server/src/main/core/cache/CacheFile.java +++ b/Server/src/main/core/cache/CacheFile.java @@ -66,7 +66,7 @@ public final class CacheFile { return null; } if (xteaKeys != null && (xteaKeys[0] != 0 || xteaKeys[1] != 0 || xteaKeys[2] != 0 || xteaKeys[3] != 0)) { - packedData = XTEACryption.decrypt(xteaKeys, ByteBuffer.wrap(packedData), 5, packedData.length).array(); + packedData = XTEACryption.Companion.decrypt(xteaKeys, ByteBuffer.wrap(packedData), 5, packedData.length).array(); } return ContainersInformation.unpackCacheContainer(packedData); } diff --git a/Server/src/main/core/cache/StoreFile.java b/Server/src/main/core/cache/StoreFile.java deleted file mode 100644 index 50e1728d0..000000000 --- a/Server/src/main/core/cache/StoreFile.java +++ /dev/null @@ -1,72 +0,0 @@ -package core.cache; - -import java.nio.ByteBuffer; - -/** - * Represents a file used in the server store. - * @author Emperor - */ -public final class StoreFile { - - /** - * If the data can change during server runtime. - */ - private boolean dynamic; - - /** - * The file data. - */ - private byte[] data; - - /** - * Constructs a new {@code StoreFile} {@code Object}. - */ - public StoreFile() { - /* - * empty. - */ - } - - /** - * Puts the data on the buffer. - * @param buffer The buffer. - */ - public void put(ByteBuffer buffer) { - byte[] data = new byte[buffer.remaining()]; - buffer.get(data); - this.data = data; - } - - /** - * Creates a byte buffer containing the file data. - * @return The buffer. - */ - public ByteBuffer data() { - return ByteBuffer.wrap(data); - } - - /** - * Sets the data. - * @param data The data. - */ - public void setData(byte[] data) { - this.data = data; - } - - /** - * Gets the dynamic. - * @return The dynamic. - */ - public boolean isDynamic() { - return dynamic; - } - - /** - * Sets the dynamic. - * @param dynamic The dynamic to set. - */ - public void setDynamic(boolean dynamic) { - this.dynamic = dynamic; - } - -} \ No newline at end of file diff --git a/Server/src/main/core/cache/crypto/ISAACCipher.java b/Server/src/main/core/cache/crypto/ISAACCipher.java deleted file mode 100644 index 16cd85b18..000000000 --- a/Server/src/main/core/cache/crypto/ISAACCipher.java +++ /dev/null @@ -1,271 +0,0 @@ -package core.cache.crypto; - -/** - *
An implementation of an ISAAC cipher. See - * http://en.wikipedia.org/wiki/ISAAC_(cipher) for more information.
- *This implementation is based on the one written by Bob Jenkins, which is - * available at - * http://www.burtleburtle.net/bob/java/rand/Rand.java.
- * @author Graham Edgecombe - */ -public class ISAACCipher { - - /** - * The golden ratio. - */ - public static final int RATIO = 0x9e3779b9; - - /** - * The log of the size of the results and memory arrays. - */ - public static final int SIZE_LOG = 8; - - /** - * The size of the results and memory arrays. - */ - public static final int SIZE = 1 << SIZE_LOG; - - /** - * For pseudorandom lookup. - */ - public static final int MASK = (SIZE - 1) << 2; - - /** - * The count through the results. - */ - private int count = 0; - - /** - * The results. - */ - private int results[] = new int[SIZE]; - - /** - * The internal memory state. - */ - private int memory[] = new int[SIZE]; - - /** - * The accumulator. - */ - private int a; - - /** - * The last result. - */ - private int b; - - /** - * The counter. - */ - private int c; - - /** - * Creates the ISAAC cipher. - * @param seed The seed. - */ - public ISAACCipher(int[] seed) { - for (int i = 0; i < seed.length; i++) { - results[i] = seed[i]; - } - init(true); - } - - /** - * Gets the next value. - * @return The next value. - */ - public int getNextValue() { - if (count-- == 0) { - isaac(); - count = SIZE - 1; - } - return 0;//results[count]; - } - - /** - * Generates 256 results. - */ - public void isaac() { - int i, j, x, y; - b += ++c; - for (i = 0, j = SIZE / 2; i < SIZE / 2;) { - x = memory[i]; - a ^= a << 13; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - - x = memory[i]; - a ^= a >>> 6; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - - x = memory[i]; - a ^= a << 2; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - - x = memory[i]; - a ^= a >>> 16; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - } - for (j = 0; j < SIZE / 2;) { - x = memory[i]; - a ^= a << 13; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - - x = memory[i]; - a ^= a >>> 6; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - - x = memory[i]; - a ^= a << 2; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - - x = memory[i]; - a ^= a >>> 16; - a += memory[j++]; - memory[i] = y = memory[(x & MASK) >> 2] + a + b; - results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x; - } - } - - /** - * Initialises the ISAAC. - * @param flag Flag indicating if we should perform a second pass. - */ - public void init(boolean flag) { - int i; - int a, b, c, d, e, f, g, h; - a = b = c = d = e = f = g = h = RATIO; - for (i = 0; i < 4; ++i) { - a ^= b << 11; - d += a; - b += c; - b ^= c >>> 2; - e += b; - c += d; - c ^= d << 8; - f += c; - d += e; - d ^= e >>> 16; - g += d; - e += f; - e ^= f << 10; - h += e; - f += g; - f ^= g >>> 4; - a += f; - g += h; - g ^= h << 8; - b += g; - h += a; - h ^= a >>> 9; - c += h; - a += b; - } - for (i = 0; i < SIZE; i += 8) { - if (flag) { - a += results[i]; - b += results[i + 1]; - c += results[i + 2]; - d += results[i + 3]; - e += results[i + 4]; - f += results[i + 5]; - g += results[i + 6]; - h += results[i + 7]; - } - a ^= b << 11; - d += a; - b += c; - b ^= c >>> 2; - e += b; - c += d; - c ^= d << 8; - f += c; - d += e; - d ^= e >>> 16; - g += d; - e += f; - e ^= f << 10; - h += e; - f += g; - f ^= g >>> 4; - a += f; - g += h; - g ^= h << 8; - b += g; - h += a; - h ^= a >>> 9; - c += h; - a += b; - memory[i] = a; - memory[i + 1] = b; - memory[i + 2] = c; - memory[i + 3] = d; - memory[i + 4] = e; - memory[i + 5] = f; - memory[i + 6] = g; - memory[i + 7] = h; - } - if (flag) { - for (i = 0; i < SIZE; i += 8) { - a += memory[i]; - b += memory[i + 1]; - c += memory[i + 2]; - d += memory[i + 3]; - e += memory[i + 4]; - f += memory[i + 5]; - g += memory[i + 6]; - h += memory[i + 7]; - a ^= b << 11; - d += a; - b += c; - b ^= c >>> 2; - e += b; - c += d; - c ^= d << 8; - f += c; - d += e; - d ^= e >>> 16; - g += d; - e += f; - e ^= f << 10; - h += e; - f += g; - f ^= g >>> 4; - a += f; - g += h; - g ^= h << 8; - b += g; - h += a; - h ^= a >>> 9; - c += h; - a += b; - memory[i] = a; - memory[i + 1] = b; - memory[i + 2] = c; - memory[i + 3] = d; - memory[i + 4] = e; - memory[i + 5] = f; - memory[i + 6] = g; - memory[i + 7] = h; - } - } - isaac(); - count = SIZE; - } - -} \ No newline at end of file diff --git a/Server/src/main/core/cache/crypto/ISAACCipher.kt b/Server/src/main/core/cache/crypto/ISAACCipher.kt new file mode 100644 index 000000000..d3fab467b --- /dev/null +++ b/Server/src/main/core/cache/crypto/ISAACCipher.kt @@ -0,0 +1,213 @@ +package core.cache.crypto + +/** + * An implementation of an ISAAC cipher. + * See [http://en.wikipedia.org/wiki/ISAAC_(cipher)](http://en.wikipedia.org/wiki/ISAAC_(cipher)) for more information. + * Based on the one written by Bob Jenkins, which is available at + * [http://www.burtleburtle.net/bob/java/rand/Rand.java](http://www.burtleburtle.net/bob/java/rand/Rand.java). + */ +class ISAACCipher(seed: IntArray) { + companion object { + /** Golden ratio in 32 bit unsigned int. */ + const val RATIO = -0x61c88647 + /** The base 2 log of the size of the results and memory arrays. */ + const val SIZE_LOG = 8 + /** The size of the results and memory arrays. */ + const val SIZE = 1 shl SIZE_LOG + /** For pseudorandom lookup. */ + const val MASK = SIZE - 1 shl 2 + } + /** The count through the results. */ + private var count = 0 + /** The results. */ + private val results = IntArray(SIZE) + /** The internal memory state. */ + private val memory = IntArray(SIZE) + /** The accumulator. */ + private var a = 0 + /** The last result. */ + private var b = 0 + /** The counter. */ + private var c = 0 + + /** + * Creates the ISAAC cipher. + * @param seed The seed. + */ + init { + for (i in seed.indices) { + results[i] = seed[i] + } + init(true) + } + + val nextValue: Int + /** + * Gets the next value. + * @return The next value. + */ + get() { + if (count-- == 0) { + isaac() + count = SIZE - 1 + } + return 0 //results[count]; + } + + /** + * Generates 256 results. + */ + fun isaac() { + var i: Int + var j: Int + var x: Int + var y: Int + b += ++c + i = 0 + j = SIZE / 2 + while (i < SIZE / 2) { + x = memory[i] + a = a xor (a shl 13) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + x = memory[i] + a = a xor (a ushr 6) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + x = memory[i] + a = a xor (a shl 2) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + x = memory[i] + a = a xor (a ushr 16) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + } + j = 0 + while (j < SIZE / 2) { + x = memory[i] + a = a xor (a shl 13) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + x = memory[i] + a = a xor (a ushr 6) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + x = memory[i] + a = a xor (a shl 2) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + x = memory[i] + a = a xor (a ushr 16) + a += memory[j++] + y = memory[x and MASK shr 2] + a + b + memory[i] = y + b = memory[y shr SIZE_LOG and MASK shr 2] + x + results[i++] = b + } + } + + /** + * Initialises the ISAAC. + * @param flag Flag indicating if we should perform a second pass. + */ + fun init(flag: Boolean) { + var a = RATIO + var b = a; var c = b; var d = c; var e = d; var f = e; var g = f; var h = g + var i = 0 + while (i < 4) { + a = a xor (b shl 11); d += a; b += c + b = b xor (c ushr 2); e += b; c += d + c = c xor (d shl 8); f += c; d += e + d = d xor (e ushr 16); g += d; e += f + e = e xor (f shl 10); h += e; f += g + f = f xor (g ushr 4); a += f; g += h + g = g xor (h shl 8); b += g; h += a + h = h xor (a ushr 9); c += h; a += b + ++i + } + i = 0 + while (i < SIZE) { + if (flag) { + a += results[i] + b += results[i + 1] + c += results[i + 2] + d += results[i + 3] + e += results[i + 4] + f += results[i + 5] + g += results[i + 6] + h += results[i + 7] + } + a = a xor (b shl 11); d += a; b += c + b = b xor (c ushr 2); e += b; c += d + c = c xor (d shl 8); f += c; d += e + d = d xor (e ushr 16); g += d; e += f + e = e xor (f shl 10); h += e; f += g + f = f xor (g ushr 4); a += f; g += h + g = g xor (h shl 8); b += g; h += a + h = h xor (a ushr 9); c += h; a += b + memory[i] = a + memory[i + 1] = b + memory[i + 2] = c + memory[i + 3] = d + memory[i + 4] = e + memory[i + 5] = f + memory[i + 6] = g + memory[i + 7] = h + i += 8 + } + if (flag) { + i = 0 + while (i < SIZE) { + a += memory[i] + b += memory[i + 1] + c += memory[i + 2] + d += memory[i + 3] + e += memory[i + 4] + f += memory[i + 5] + g += memory[i + 6] + h += memory[i + 7] + a = a xor (b shl 11); d += a; b += c + b = b xor (c ushr 2); e += b; c += d + c = c xor (d shl 8); f += c; d += e + d = d xor (e ushr 16); g += d; e += f + e = e xor (f shl 10); h += e; f += g + f = f xor (g ushr 4); a += f; g += h + g = g xor (h shl 8); b += g; h += a + h = h xor (a ushr 9); c += h; a += b + memory[i] = a + memory[i + 1] = b + memory[i + 2] = c + memory[i + 3] = d + memory[i + 4] = e + memory[i + 5] = f + memory[i + 6] = g + memory[i + 7] = h + i += 8 + } + } + isaac() + count = SIZE + } +} \ No newline at end of file diff --git a/Server/src/main/core/cache/crypto/ISAACPair.java b/Server/src/main/core/cache/crypto/ISAACPair.java deleted file mode 100644 index 83c4654b9..000000000 --- a/Server/src/main/core/cache/crypto/ISAACPair.java +++ /dev/null @@ -1,45 +0,0 @@ -package core.cache.crypto; - -/** - * Represents a ISAAC key pair, for both input and output. - * @author `Discardedx2 - */ -public final class ISAACPair { - - /** - * The input cipher. - */ - private ISAACCipher input; - - /** - * The output cipher. - */ - private ISAACCipher output; - - /** - * Constructs a new {@code ISAACPair} {@code Object}. - * @param input The input cipher. - * @param output The output cipher. - */ - public ISAACPair(ISAACCipher input, ISAACCipher output) { - this.input = input; - this.output = output; - } - - /** - * Gets the input cipher. - * @return The input cipher. - */ - public ISAACCipher getInput() { - return input; - } - - /** - * Gets the output cipher. - * @return The output cipher. - */ - public ISAACCipher getOutput() { - return output; - } - -} diff --git a/Server/src/main/core/cache/crypto/ISAACPair.kt b/Server/src/main/core/cache/crypto/ISAACPair.kt new file mode 100644 index 000000000..9056c7a9d --- /dev/null +++ b/Server/src/main/core/cache/crypto/ISAACPair.kt @@ -0,0 +1,9 @@ +package core.cache.crypto + +/** + * Represents a ISAAC key pair, for both input and output. + */ +class ISAACPair( + val input: ISAACCipher, + val output: ISAACCipher +) diff --git a/Server/src/main/core/cache/crypto/XTEACryption.java b/Server/src/main/core/cache/crypto/XTEACryption.java deleted file mode 100644 index 7ed799e58..000000000 --- a/Server/src/main/core/cache/crypto/XTEACryption.java +++ /dev/null @@ -1,124 +0,0 @@ -package core.cache.crypto; - -import java.nio.ByteBuffer; - -/** - * Holds XTEA cryption methods. - * @author ? - * @author Emperor - */ -public final class XTEACryption { - - /** - * The delta value - */ - private static final int DELTA = -1640531527; - - /** - * The sum. - */ - private static final int SUM = -957401312; - - /** - * The amount of "cryption cycles". - */ - private static final int NUM_ROUNDS = 32; - - /** - * Constructs a new {@code XTEACryption}. - */ - private XTEACryption() { - /* - * empty. - */ - } - - /** - * Decrypts the contents of the buffer. - * @param keys The cryption keys. - * @param buffer The buffer. - */ - public static ByteBuffer decrypt(int[] keys, ByteBuffer buffer) { - return decrypt(keys, buffer, buffer.position(), buffer.limit()); - } - - /** - * Decrypts the buffer data. - * @param keys The keys. - * @param buffer The buffer to decrypt. - * @param offset The offset of the data to decrypt. - * @param length The length. - * @return The decrypted data. - */ - public static ByteBuffer decrypt(int[] keys, ByteBuffer buffer, int offset, int length) { - int numBlocks = (length - offset) / 8; - int[] block = new int[2]; - for (int i = 0; i < numBlocks; i++) { - int index = i * 8 + offset; - block[0] = buffer.getInt(index); - block[1] = buffer.getInt(index + 4); - decipher(keys, block); - buffer.putInt(index, block[0]); - buffer.putInt(index + 4, block[1]); - } - return buffer; - } - - /** - * Deciphers the values. - * @param keys The cryption key. - * @param block The values to decipher. - */ - private static void decipher(int[] keys, int[] block) { - long sum = SUM; - for (int i = 0; i < NUM_ROUNDS; i++) { - block[1] -= (keys[(int) ((sum & 0x1933) >>> 11)] + sum ^ block[0] + (block[0] << 4 ^ block[0] >>> 5)); - sum -= DELTA; - block[0] -= ((block[1] << 4 ^ block[1] >>> 5) + block[1] ^ keys[(int) (sum & 0x3)] + sum); - } - } - - /** - * Encrypts the contents of the byte buffer. - * @param keys The cryption keys. - * @param buffer The buffer to encrypt. - */ - public static void encrypt(int[] keys, ByteBuffer buffer) { - encrypt(keys, buffer, buffer.position(), buffer.limit()); - } - - /** - * Encrypts the buffer data. - * @param keys The keys. - * @param buffer The buffer to encrypt. - * @param offset The offset of the data to encrypt. - * @param length The length. - * @return The encrypted data. - */ - public static void encrypt(int[] keys, ByteBuffer buffer, int offset, int length) { - int numBlocks = (length - offset) / 8; - int[] block = new int[2]; - for (int i = 0; i < numBlocks; i++) { - int index = i * 8 + offset; - block[0] = buffer.getInt(index); - block[1] = buffer.getInt(index + 4); - encipher(keys, block); - buffer.putInt(index, block[0]); - buffer.putInt(index + 4, block[1]); - } - } - - /** - * Enciphers the values of the block. - * @param keys The cryption keys. - * @param block The block to encipher. - */ - private static void encipher(int[] keys, int[] block) { - long sum = 0; - for (int i = 0; i < NUM_ROUNDS; i++) { - block[0] += ((block[1] << 4 ^ block[1] >>> 5) + block[1] ^ keys[(int) (sum & 0x3)] + sum); - sum += DELTA; - block[1] += (keys[(int) ((sum & 0x1933) >>> 11)] + sum ^ block[0] + (block[0] << 4 ^ block[0] >>> 5)); - } - } -} \ No newline at end of file diff --git a/Server/src/main/core/cache/crypto/XTEACryption.kt b/Server/src/main/core/cache/crypto/XTEACryption.kt new file mode 100644 index 000000000..f87477008 --- /dev/null +++ b/Server/src/main/core/cache/crypto/XTEACryption.kt @@ -0,0 +1,97 @@ +package core.cache.crypto + +import java.nio.ByteBuffer + +/** Holds XTEA(eXtended Tiny Encryption Algorithm) encryption/decryption methods. Usually used for RS Map decryption. */ +class XTEACryption { + companion object { + // Purely Static Class + // XTEA consts https://scispace.com/pdf/xtea-cryptography-implementation-in-android-chatting-app-3pg6ownewx.pdf + /** Fibonacci hashing. Math.pow(2,32) * Math.sqrt(5)-1)/2 => 32 bits(int) multiply by reciprocal of golden ratio. */ + private const val DELTA = -1640531527 // Formula cast to unsigned int. + /** DELTA << 5. Essentially multiply DELTA by NUM_ROUNDS or number of rounds. */ + private const val SUM = -957401312 // 0xC6EF3720 + /** The amount of "cryption cycles". */ + private const val NUM_ROUNDS = 32 + /** Constant to manipulate the key index in decipher/encrypt. This was a magic number randomly selected by RS. */ + private const val KEY_SCRAMBLE = 0x1933 + + /** + * Decrypts the buffer data. + * @param keys The keys. + * @param buffer The buffer to decrypt. + * @param offset The offset of the data to decrypt. + * @param length The length. + * @return The decrypted data. + */ + fun decrypt(keys: IntArray, buffer: ByteBuffer, offset: Int, length: Int): ByteBuffer { + val numBlocks = (length - offset) / 8 + val block = IntArray(2) + for (i in 0 until numBlocks) { + val index = i * 8 + offset + block[0] = buffer.getInt(index) + block[1] = buffer.getInt(index + 4) + decipher(keys, block) + buffer.putInt(index, block[0]) + buffer.putInt(index + 4, block[1]) + } + return buffer + } + + /** + * Deciphers the values of the block using the Tiny Encryption Algorithm (TEA). + * This algorithm relies on a Feistel network, using bitwise operations and + * modular subtraction to remove confusion(block[0] line) and diffusion(block[1] line). + * + * @param keys 128-bit key (4x32-bit int). + * @param block 64-bit data block (2x32-bit int) to be decrypted. + */ + private fun decipher(keys: IntArray, block: IntArray) { + var sum = + SUM.toLong() // Running decreasing sum to ensure different round constants - should become 0 at the end. + for (i in 0 until NUM_ROUNDS) { + block[1] -= (keys[(sum and KEY_SCRAMBLE.toLong() ushr 11).toInt()] + sum xor (block[0] + (block[0] shl 4 xor (block[0] ushr 5))).toLong()).toInt() + sum -= DELTA.toLong() + block[0] -= (((block[1] shl 4 xor (block[1] ushr 5)) + block[1]).toLong() xor keys[(sum and 0x3L).toInt()] + sum).toInt() + } + } + /** === Encryption functions below are not used unless you are modifying the cache. === */ + /** + * Encrypts the buffer data. + * @param keys The keys. + * @param buffer The buffer to encrypt. + * @param offset The offset of the data to encrypt. + * @param length The length. + * @return The encrypted data. + */ + fun encrypt(keys: IntArray, buffer: ByteBuffer, offset: Int, length: Int) { + val numBlocks = (length - offset) / 8 + val block = IntArray(2) + for (i in 0 until numBlocks) { + val index = i * 8 + offset + block[0] = buffer.getInt(index) + block[1] = buffer.getInt(index + 4) + encipher(keys, block) + buffer.putInt(index, block[0]) + buffer.putInt(index + 4, block[1]) + } + } + + /** + * Enciphers the values of the block using the Tiny Encryption Algorithm (TEA). + * This algorithm relies on a Feistel network, using bitwise operations and + * modular addition to provide confusion(block[0] line) and diffusion(block[1] line). + * + * @param keys 128-bit key (4x32-bit int). + * @param block 64-bit data block (2x32-bit int) to be encrypted. + */ + private fun encipher(keys: IntArray, block: IntArray) { + var sum: Long = 0 // Running sum to ensure different round constants - should match SUM at the end. + for (i in 0 until NUM_ROUNDS) { + block[0] += (((block[1] shl 4 xor (block[1] ushr 5)) + block[1]).toLong() xor keys[(sum and 0x3L).toInt()] + sum).toInt() + sum += DELTA.toLong() + block[1] += (keys[(sum and KEY_SCRAMBLE.toLong() ushr 11).toInt()] + sum xor (block[0] + (block[0] shl 4 xor (block[0] ushr 5))).toLong()).toInt() + } + } + } +} \ No newline at end of file diff --git a/Server/src/main/core/cache/misc/Container.java b/Server/src/main/core/cache/misc/Container.java deleted file mode 100644 index 9760845ff..000000000 --- a/Server/src/main/core/cache/misc/Container.java +++ /dev/null @@ -1,109 +0,0 @@ -package core.cache.misc; - -/** - * A container. - * @author Dragonkk - */ -public class Container { - - /** - * The version. - */ - private int version; - - /** - * The CRC. - */ - private int crc; - - /** - * The name hash. - */ - private int nameHash; - - /** - * If updated. - */ - private boolean updated; - - /** - * Construct a new container. - */ - public Container() { - nameHash = -1; - version = -1; - crc = -1; - } - - /** - * Set the version. - * @param version - */ - public void setVersion(int version) { - this.version = version; - } - - /** - * Update the version. - */ - public void updateVersion() { - version++; - updated = true; - } - - /** - * Get the version. - * @return The version. - */ - public int getVersion() { - return version; - } - - /** - * Get the next version. - * @return The next version. - */ - public int getNextVersion() { - return updated ? version : version + 1; - } - - /** - * Set the CRC. - * @param crc The cRC. - */ - public void setCrc(int crc) { - this.crc = crc; - } - - /** - * Get the CRC. - * @return The CRC. - */ - public int getCrc() { - return crc; - } - - /** - * Set the name hash. - * @param nameHash The name hash. - */ - public void setNameHash(int nameHash) { - this.nameHash = nameHash; - } - - /** - * Get the name hash. - * @return The name hash. - */ - public int getNameHash() { - return nameHash; - } - - /** - * If is updated. - * @return If is updated. - */ - public boolean isUpdated() { - return updated; - } -} diff --git a/Server/src/main/core/cache/misc/Container.kt b/Server/src/main/core/cache/misc/Container.kt new file mode 100644 index 000000000..3e1b481d6 --- /dev/null +++ b/Server/src/main/core/cache/misc/Container.kt @@ -0,0 +1,7 @@ +package core.cache.misc + +data class Container( + var version: Int = -1, + var crc: Int = -1, + var nameHash: Int = -1 +) \ No newline at end of file diff --git a/Server/src/main/core/cache/misc/ContainersInformation.java b/Server/src/main/core/cache/misc/ContainersInformation.java deleted file mode 100644 index f786c1d2f..000000000 --- a/Server/src/main/core/cache/misc/ContainersInformation.java +++ /dev/null @@ -1,228 +0,0 @@ -package core.cache.misc; - -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.zip.CRC32; - -import core.cache.bzip2.BZip2Decompressor; -import core.cache.gzip.GZipDecompressor; - -/** - * A class holding the containers information. - * @author Dragonkk - */ -public final class ContainersInformation { - - /** - * The information container. - */ - private Container informationContainer; - - /** - * The protocol. - */ - private int protocol; - - /** - * The revision. - */ - private int revision; - - /** - * The container indexes. - */ - private int[] containersIndexes; - - /** - * The containers. - */ - private FilesContainer[] containers; - - /** - * If files have to be named. - */ - private boolean filesNamed; - - /** - * If it has to be whirpool. - */ - private boolean whirpool; - - /** - * The data. - */ - private final byte[] data; - - /** - * Construct a new containers information. - * @param informationContainerPackedData The information container data - * packed. - */ - public ContainersInformation(byte[] informationContainerPackedData) { - this.data = Arrays.copyOf(informationContainerPackedData, informationContainerPackedData.length); - informationContainer = new Container(); - informationContainer.setVersion((informationContainerPackedData[informationContainerPackedData.length - 2] << 8 & 0xff00) + (informationContainerPackedData[-1 + informationContainerPackedData.length] & 0xff)); - CRC32 crc32 = new CRC32(); - crc32.update(informationContainerPackedData); - informationContainer.setCrc((int) crc32.getValue()); - decodeContainersInformation(unpackCacheContainer(informationContainerPackedData)); - } - - /** - * Unpacks a container. - * @param packedData The packed container data. - * @return The unpacked data. - */ - public static final byte[] unpackCacheContainer(byte[] packedData) { - ByteBuffer buffer = ByteBuffer.wrap(packedData); - int compression = buffer.get() & 0xFF; - int containerSize = buffer.getInt(); - if (containerSize < 0 || containerSize > 5000000) { - return null; - // throw new RuntimeException(); - } - if (compression == 0) { - byte unpacked[] = new byte[containerSize]; - buffer.get(unpacked, 0, containerSize); - return unpacked; - } - int decompressedSize = buffer.getInt(); - if (decompressedSize < 0 || decompressedSize > 20000000) { - return null; - // throw new RuntimeException(); - } - byte decompressedData[] = new byte[decompressedSize]; - if (compression == 1) { - BZip2Decompressor.decompress(decompressedData, packedData, containerSize, 9); - } else { - GZipDecompressor.decompress(buffer, decompressedData); - } - return decompressedData; - } - - /** - * Get the container indexes. - * @return The container indexes. - */ - public int[] getContainersIndexes() { - return containersIndexes; - } - - /** - * Get the containers. - * @return The containers. - */ - public FilesContainer[] getContainers() { - return containers; - } - - /** - * Get the information container. - * @return The information container. - */ - public Container getInformationContainer() { - return informationContainer; - } - - /** - * Get the revision. - * @return The revision. - */ - public int getRevision() { - return revision; - } - - /** - * Decode the containers information. - * @param data The data. - */ - public void decodeContainersInformation(byte[] data) { - ByteBuffer buffer = ByteBuffer.wrap(data); - protocol = buffer.get() & 0xFF; - if (protocol != 5 && protocol != 6) { - throw new RuntimeException(); - } - revision = protocol < 6 ? 0 : buffer.getInt(); - int nameHash = buffer.get() & 0xFF; - filesNamed = (0x1 & nameHash) != 0; - whirpool = (0x2 & nameHash) != 0; - containersIndexes = new int[buffer.getShort() & 0xFFFF]; - int lastIndex = -1; - for (int index = 0; index < containersIndexes.length; index++) { - containersIndexes[index] = (buffer.getShort() & 0xFFFF) + (index == 0 ? 0 : containersIndexes[index - 1]); - if (containersIndexes[index] > lastIndex) { - lastIndex = containersIndexes[index]; - } - } - containers = new FilesContainer[lastIndex + 1]; - for (int index = 0; index < containersIndexes.length; index++) { - containers[containersIndexes[index]] = new FilesContainer(); - } - if (filesNamed) { - for (int index = 0; index < containersIndexes.length; index++) { - containers[containersIndexes[index]].setNameHash(buffer.getInt()); - } - } - byte[][] filesHashes = null; - if (whirpool) { - filesHashes = new byte[containers.length][]; - for (int index = 0; index < containersIndexes.length; index++) { - filesHashes[containersIndexes[index]] = new byte[64]; - buffer.get(filesHashes[containersIndexes[index]], 0, 64); - } - } - for (int index = 0; index < containersIndexes.length; index++) { - containers[containersIndexes[index]].setCrc(buffer.getInt()); - } - for (int index = 0; index < containersIndexes.length; index++) { - containers[containersIndexes[index]].setVersion(buffer.getInt()); - } - for (int index = 0; index < containersIndexes.length; index++) { - containers[containersIndexes[index]].setFilesIndexes(new int[buffer.getShort() & 0xFFFF]); - } - for (int index = 0; index < containersIndexes.length; index++) { - int lastFileIndex = -1; - for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) { - containers[containersIndexes[index]].getFilesIndexes()[fileIndex] = (buffer.getShort() & 0xFFFF) + (fileIndex == 0 ? 0 : containers[containersIndexes[index]].getFilesIndexes()[fileIndex - 1]); - if (containers[containersIndexes[index]].getFilesIndexes()[fileIndex] > lastFileIndex) { - lastFileIndex = containers[containersIndexes[index]].getFilesIndexes()[fileIndex]; - } - } - containers[containersIndexes[index]].setFiles(new Container[lastFileIndex + 1]); - for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) { - containers[containersIndexes[index]].getFiles()[containers[containersIndexes[index]].getFilesIndexes()[fileIndex]] = new Container(); - } - } - if (whirpool) { - for (int index = 0; index < containersIndexes.length; index++) { - for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) { - containers[containersIndexes[index]].getFiles()[containers[containersIndexes[index]].getFilesIndexes()[fileIndex]].setVersion(filesHashes[containersIndexes[index]][containers[containersIndexes[index]].getFilesIndexes()[fileIndex]]); - } - } - } - if (filesNamed) { - for (int index = 0; index < containersIndexes.length; index++) { - for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) { - containers[containersIndexes[index]].getFiles()[containers[containersIndexes[index]].getFilesIndexes()[fileIndex]].setNameHash(buffer.getInt()); - } - } - } - } - - /** - * If is whirpool. - * @return If is whirpool {@code true}. - */ - public boolean isWhirpool() { - return whirpool; - } - - /** - * Gets the data. - * @return The data. - */ - public byte[] getData() { - return data; - } - -} diff --git a/Server/src/main/core/cache/misc/ContainersInformation.kt b/Server/src/main/core/cache/misc/ContainersInformation.kt new file mode 100644 index 000000000..831eb954b --- /dev/null +++ b/Server/src/main/core/cache/misc/ContainersInformation.kt @@ -0,0 +1,145 @@ +package core.cache.misc + +import core.cache.bzip2.BZip2Decompressor +import core.cache.gzip.GZipDecompressor +import java.nio.ByteBuffer +import java.util.* +import java.util.zip.CRC32 + +class ContainersInformation(informationContainerPackedData: ByteArray) { + @JvmField + val informationContainer: Container + private var protocol = 0 + var revision = 0 + var containersIndexes: IntArray = intArrayOf() + var containers: Array