cache: use own Xtea implmentation instead of bouncycastle's

This commit is contained in:
Adam
2017-12-15 23:10:02 -05:00
parent 0049b8d34e
commit a94ccedbf0
3 changed files with 49 additions and 89 deletions

5
cache/pom.xml vendored
View File

@@ -74,11 +74,6 @@
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
<version>2.4</version> <version>2.4</version>
</dependency> </dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-ext-jdk14</artifactId>
<version>1.54</version>
</dependency>
<dependency> <dependency>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
<artifactId>netty-all</artifactId> <artifactId>netty-all</artifactId>

View File

@@ -30,11 +30,6 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import net.runelite.cache.util.BZip2; import net.runelite.cache.util.BZip2;
import net.runelite.cache.io.InputStream; import net.runelite.cache.io.InputStream;
import net.runelite.cache.io.OutputStream; import net.runelite.cache.io.OutputStream;
@@ -432,16 +427,8 @@ public class DataFile implements Closeable
return data; return data;
} }
try Xtea xtea = new Xtea(keys);
{ return xtea.decrypt(data, length);
Xtea xtea = new Xtea(keys);
return xtea.decrypt(data, length);
}
catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException ex)
{
logger.warn("unable to xtea decrypt", ex);
return null;
}
} }
private static byte[] encrypt(byte[] data, int length, int[] keys) private static byte[] encrypt(byte[] data, int length, int[] keys)
@@ -451,15 +438,7 @@ public class DataFile implements Closeable
return data; return data;
} }
try Xtea xtea = new Xtea(keys);
{ return xtea.encrypt(data, length);
Xtea xtea = new Xtea(keys);
return xtea.encrypt(data, length);
}
catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException ex)
{
logger.warn("unable to xtea encrypt", ex);
return null;
}
} }
} }

View File

@@ -22,81 +22,67 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package net.runelite.cache.util; package net.runelite.cache.util;
import java.nio.ByteBuffer; import io.netty.buffer.ByteBuf;
import java.security.InvalidKeyException; import io.netty.buffer.Unpooled;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Arrays;
public class Xtea public class Xtea
{ {
static private static final int GOLDEN_RATIO = 0x9E3779B9;
private static final int ROUNDS = 32;
private final int[] key;
public Xtea(int[] key)
{ {
Security.addProvider(new BouncyCastleProvider()); this.key = key;
} }
private final Cipher cipher; public byte[] encrypt(byte[] data, int len)
private final int[] keys;
public Xtea(int[] keys) throws NoSuchAlgorithmException, NoSuchPaddingException
{ {
this.cipher = Cipher.getInstance("XTEA/ECB/NoPadding"); ByteBuf buf = Unpooled.wrappedBuffer(data, 0, len);
this.keys = keys; ByteBuf out = Unpooled.buffer(len);
} int numBlocks = len / 8;
for (int block = 0; block < numBlocks; ++block)
private static byte[] packKey(int[] key)
{
ByteBuffer buffer = ByteBuffer.allocate(4 * key.length);
for (int i : key)
buffer.putInt(i);
return buffer.array();
}
public byte[] encrypt(byte[] data, int len) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException
{
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(packKey(keys), cipher.getAlgorithm()));
byte[] out = cipher.update(data, 0, len - (len % cipher.getBlockSize()));
cipher.doFinal();
// add remaining data, which is not encrypted
if (out.length != len)
{ {
assert len > out.length; int v0 = buf.readInt();
int v1 = buf.readInt();
byte[] padded = Arrays.copyOf(out, len); int sum = 0;
System.arraycopy(data, out.length, padded, out.length, len - out.length); for (int i = 0; i < ROUNDS; ++i)
{
out = padded; v0 += (((v1 << 4) ^ (v1 >>> 5)) + v1) ^ (sum + key[sum & 3]);
sum += GOLDEN_RATIO;
v1 += (((v0 << 4) ^ (v0 >>> 5)) + v0) ^ (sum + key[(sum >>> 11) & 3]);
}
out.writeInt(v0);
out.writeInt(v1);
} }
out.writeBytes(buf);
return out; return out.array();
} }
public byte[] decrypt(byte[] data, int len) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException public byte[] decrypt(byte[] data, int len)
{ {
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(packKey(keys), cipher.getAlgorithm())); ByteBuf buf = Unpooled.wrappedBuffer(data, 0, len);
byte[] out = cipher.update(data, 0, len - (len % cipher.getBlockSize())); ByteBuf out = Unpooled.buffer(len);
cipher.doFinal(); int numBlocks = len / 8;
for (int block = 0; block < numBlocks; ++block)
if (out.length != len)
{ {
assert len > out.length; int v0 = buf.readInt();
int v1 = buf.readInt();
byte[] padded = Arrays.copyOf(out, len); int sum = GOLDEN_RATIO * ROUNDS;
System.arraycopy(data, out.length, padded, out.length, len - out.length); for (int i = 0; i < ROUNDS; ++i)
{
out = padded; v1 -= (((v0 << 4) ^ (v0 >>> 5)) + v0) ^ (sum + key[(sum >>> 11) & 3]);
sum -= GOLDEN_RATIO;
v0 -= (((v1 << 4) ^ (v1 >>> 5)) + v1) ^ (sum + key[sum & 3]);
}
out.writeInt(v0);
out.writeInt(v1);
} }
out.writeBytes(buf);
return out; return out.array();
} }
} }