runelite-proxy: subtree split into separate repository

This commit is contained in:
Adam
2017-12-29 18:06:10 -05:00
parent 3d463a7c9d
commit 4ac2696130
9 changed files with 0 additions and 860 deletions

View File

@@ -118,7 +118,6 @@
<module>runelite-plugin-archetype</module>
<module>http-api</module>
<module>http-service</module>
<module>runelite-proxy</module>
<module>protocol-api</module>
<module>protocol</module>
</modules>

View File

@@ -1,68 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2017, Adam <Adam@sigterm.info>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<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>
<parent>
<groupId>net.runelite</groupId>
<artifactId>runelite-parent</artifactId>
<version>1.2.11-SNAPSHOT</version>
</parent>
<groupId>net.runelite</groupId>
<artifactId>proxy</artifactId>
<name>Runelite Proxy</name>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.0.Final</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,64 +0,0 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.proxy;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class IOCopy extends Thread
{
private static final Logger logger = LoggerFactory.getLogger(IOCopy.class);
private final DataInputStream in;
private final DataOutputStream out;
public IOCopy(String name, DataInputStream in, DataOutputStream out)
{
super(name);
this.in = in;
this.out = out;
}
@Override
public void run()
{
try
{
int i;
while ((i = in.read()) != -1)
{
out.write(i);
}
}
catch (IOException ex)
{
logger.error(null, ex);
}
}
}

View File

@@ -1,112 +0,0 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.proxy;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PacketCopy extends Thread
{
private static final Logger logger = LoggerFactory.getLogger(PacketCopy.class);
private final DataInputStream in;
private final DataOutputStream out;
private final RLISAACCipher inCipher;
private final RLISAACCipher outCipher;
public PacketCopy(String name, DataInputStream in, DataOutputStream out, RLISAACCipher inCipher, RLISAACCipher outCipher)
{
super(name);
this.in = in;
this.out = out;
this.inCipher = inCipher;
this.outCipher = outCipher;
}
@Override
public void run()
{
try
{
for (;;)
{
int packetOpcode = ProxyRunner.readOpcode(inCipher, in);
int packetLength = Proxy.PACKET_LENGHTS[packetOpcode];
if (packetLength == -1)
{
packetLength = in.read() & 0xff;
}
if (packetLength == -2)
{
packetLength = in.readShort() & 0xffff;
}
byte[] b = new byte[packetLength];
int read = 0;
while (read < packetLength)
{
int r = in.read(b, read, packetLength - read);
if (r <= 0)
{
throw new IOException();
}
read += r;
}
String hexdump = ByteBufUtil.prettyHexDump(Unpooled.wrappedBuffer(b));
logger.info("Read packet opcode {} length {}\n{}", packetOpcode, packetLength, hexdump);
// Write out
ProxyRunner.writeOpcode(outCipher, out, packetOpcode);
switch (Proxy.PACKET_LENGHTS[packetOpcode])
{
case -1:
assert packetLength >= 0 && packetLength < 256;
out.write(packetLength);
break;
case -2:
out.writeShort(packetLength);
break;
}
out.write(b);
}
}
catch (IOException ex)
{
logger.error(null, ex);
}
}
}

View File

@@ -1,63 +0,0 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.proxy;
import java.io.IOException;
import java.math.BigInteger;
import java.net.ServerSocket;
import java.net.Socket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Proxy
{
private static final Logger logger = LoggerFactory.getLogger(Proxy.class);
public static final int REVISION = 140;
// For revision 140
public static final BigInteger SERVER_RSA_KEY_MODULUS = new BigInteger("9cb954af0865fabe3fcee77d0a91524f62b18e71b550fa614215edb36424cc57718697e30a7f074ed8bf30c15bb2fca615790d6b322606e48445c2b3393680f56874e5ae8a9f89cd7bbab8c2dd8d2b233b3731f5bb00e9ddb3eddc7a46db157ba848e3ba5fe1e71edde7e36d0976b7ba8dd2ad6c9712ccc9c788212347c3a517", 16);
public static final BigInteger SERVER_RSA_KEY_EXPONENT = new BigInteger("10001", 16);
public static final int[] PACKET_LENGHTS = new int[]
{
4, 0, -1, 0, 6, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 6, 4, 28, 0, 0, 0, -2, 7, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 6, 0, 0, 0, 5, 0, 0, 4, -2, 0, 0, 2, 1, 2, 5, 0, 0, 0, 0, 6, -1, 0, 0, 0, 0, -2, -2, 0, 0, 4, 0, -2, 0, -2, 0, -2, -2, 4, 6, 0, -2, 0, 0, 0, 0, 4, 5, 7, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 8, 5, 0, 0, 15, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, -2, 0, 0, 4, 0, 3, 0, 0, 2, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, -2, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 6, 6, -1, 1, 0, 0, -2, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 12, 0, 6, 8, -2, 0, 5, 0, 0, -2, 0, 6, 10, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 10, 14, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 6, -2, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0
};
public static final RSA myRsa = new RSA();
public static final RSA rsRsa = new RSA(SERVER_RSA_KEY_MODULUS, null);
public static void main(String[] args) throws IOException
{
ServerSocket socket = new ServerSocket(43594);
logger.info("Running with RSA modulus {}", myRsa.getN().toString(16));
Socket s;
while ((s = socket.accept()) != null)
{
new ProxyRunner(s).start();
}
}
}

View File

@@ -1,234 +0,0 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.proxy;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.ByteBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ProxyRunner extends Thread
{
private static final Logger logger = LoggerFactory.getLogger(ProxyRunner.class);
private final Socket client;
private final Socket server;
private RLISAACCipher clientInCipher;
private RLISAACCipher clientOutCipher;
private RLISAACCipher serverInCipher;
private RLISAACCipher serverOutCipher;
public ProxyRunner(Socket client) throws IOException
{
this.client = client;
this.server = new Socket("oldschool84.runescape.com", 43594);
}
@Override
public void run()
{
try
{
go();
}
catch (IOException ex)
{
logger.error(null, ex);
}
}
private void go() throws IOException
{
DataInputStream in = new DataInputStream(client.getInputStream());
DataOutputStream out = new DataOutputStream(client.getOutputStream());
DataInputStream serverIn = new DataInputStream(server.getInputStream());
DataOutputStream serverOut = new DataOutputStream(server.getOutputStream());
int handshakeType = in.read();
logger.info("Handshake from client: {}", handshakeType);
// Forward to server
serverOut.write(handshakeType);
if (handshakeType != 14) // 14 = login, 15 = ondemand
{
new IOCopy("OnDemand C2S", in, serverOut).start();
new IOCopy("OnDemand S2C", serverIn, out).start();
return;
}
int handshakeResponse = serverIn.read();
logger.info("Handshake response from server: {}", handshakeResponse);
// Forward to client
out.write(handshakeResponse);
byte[] b = new byte[8];
int len = serverIn.read(b);
assert len == 8;
logger.info("Nonce from server: {}", Longs.fromByteArray(b));
// Forward to client
out.write(b);
// Now the client sends the login packet, some of it is rsa encrypted with a rsa key
// that is hardcoded into the client. In this data is the xtea key which is used later
// for the isaac cipher seeding and for encrypting the rest of the packet.
int gameState = in.read(); // 18 or 16 depending on some game state
int length = in.readShort(); // length of remaining packet
int revision = in.readInt(); // client revision
logger.info("Client game state: {}, revision: {}", gameState, revision);
if (revision != Proxy.REVISION)
{
client.close();
server.close();
return;
}
int encrypedDataLength = in.readShort();
byte[] rsaData = new byte[encrypedDataLength];
len = in.read(rsaData);
assert len == encrypedDataLength;
rsaData = Proxy.myRsa.decrypt(rsaData);
// Reencrypt data
byte[] reencrypted = Proxy.rsRsa.encrypt(rsaData);
// Extract xtea key
b = rsaData;
assert b[0] == 1;
int key1 = Ints.fromBytes(b[2], b[3], b[4], b[5]);
int key2 = Ints.fromBytes(b[6], b[7], b[8], b[9]);
int key3 = Ints.fromBytes(b[10], b[11], b[12], b[13]);
int key4 = Ints.fromBytes(b[14], b[15], b[16], b[17]);
int[] keys = new int[]
{
key1, key2, key3, key4
};
logger.info("Xtea key is {} {} {} {}", key1, key2, key3, key4);
clientInCipher = new RLISAACCipher(keys);
serverOutCipher = new RLISAACCipher(keys);
for (int i = 0; i < 4; i++)
{
keys[i] += 50;
}
clientOutCipher = new RLISAACCipher(keys);
serverInCipher = new RLISAACCipher(keys);
// Following this is xtea encrypted data
int xteaDataLength = length - 4 - encrypedDataLength - 2; // total length - revision - rsa encrypted data - rsa encrypted data length
byte[] xteaData = new byte[xteaDataLength];
len = in.read(xteaData);
assert len == xteaDataLength;
ByteBuffer buffer = ByteBuffer.allocate(4096);
buffer.put((byte) gameState);
buffer.putShort((short) 0); // length
buffer.putInt(revision);
buffer.putShort((short) reencrypted.length);
buffer.put(reencrypted);
buffer.put(xteaData);
len = buffer.position();
buffer.putShort(1, (short) (len - 3));
serverOut.write(buffer.array(), 0, len);
handshakeResponse = serverIn.read();
logger.info("Handshake response: {}", handshakeResponse);
out.write(handshakeResponse);
if (handshakeResponse != 2)
{
client.close();
server.close();
return;
}
int isTrusted = serverIn.read();
int trustedValue = serverIn.readInt();
logger.info("is trusted value: {}", isTrusted);
assert isTrusted != 1; // if == 1 trustedValue is decrypted using the cipher
out.write(isTrusted);
out.writeInt(trustedValue);
int permission = serverIn.read();//0 = player, 1 = player_mod, 2 = jagex_mod
int byte2 = serverIn.read();//some boolean, pushed onto intStack in script opcode 3323
int interactingIndex = serverIn.readShort() & 0xffff;//index of player in server array
int worldType = serverIn.read();//0 = f2p, 1 = p2p, only used for checking friends/ignores list size
logger.info("permission/B2/interactingIndex/worldType: {}/{}/{}/{}", permission, byte2, interactingIndex, worldType);
out.write(permission);
out.write(byte2);
out.writeShort(interactingIndex);
out.write(worldType);
int staticMapOpcode = readOpcode(serverInCipher, serverIn);
int packetLength = serverIn.readShort() & 0xffff;
logger.info("staticMap opcode: {}", staticMapOpcode);
writeOpcode(clientOutCipher, out, staticMapOpcode);
out.writeShort(packetLength);
byte[] packetData = new byte[packetLength];
len = serverIn.read(packetData);
assert len == packetData.length;
out.write(packetData);
new IOCopy("Game C2S", in, serverOut).start();
new PacketCopy("Game S2C", serverIn, out, serverInCipher, clientOutCipher).start();
}
public static int readOpcode(RLISAACCipher cipher, InputStream in) throws IOException
{
return (in.read() - cipher.nextInt()) & 0xff;
}
public static void writeOpcode(RLISAACCipher cipher, OutputStream out, int opcode) throws IOException
{
byte encrytpedOpcode = (byte) (opcode + cipher.nextInt());
out.write(encrytpedOpcode & 0xff);
}
}

View File

@@ -1,174 +0,0 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.proxy;
import java.util.Arrays;
/**
* Based off of the implementation from
* https://rosettacode.org/wiki/The_ISAAC_Cipher#Java Modified to not extend
* java.util.Random, and return results in reverse order
*
* @author Adam
*/
public class RLISAACCipher
{
private final int[] randResult = new int[256]; // output of last generation
private int valuesLeft; // the number of values already left in randResult
// internal generator state
private final int[] mm = new int[256];
private int aa, bb, cc;
public RLISAACCipher(int[] key)
{
init(key);
}
private void generateMoreResults()
{
cc++;
bb += cc;
for (int i = 0; i < 256; i++)
{
int x = mm[i];
switch (i & 3)
{
case 0:
aa = aa ^ (aa << 13);
break;
case 1:
aa = aa ^ (aa >>> 6);
break;
case 2:
aa = aa ^ (aa << 2);
break;
case 3:
aa = aa ^ (aa >>> 16);
break;
}
aa = mm[i ^ 128] + aa;
int y = mm[i] = mm[(x >>> 2) & 0xFF] + aa + bb;
randResult[i] = bb = mm[(y >>> 10) & 0xFF] + x;
}
valuesLeft = 256;
}
private static void mix(int[] s)
{
s[0] ^= s[1] << 11;
s[3] += s[0];
s[1] += s[2];
s[1] ^= s[2] >>> 2;
s[4] += s[1];
s[2] += s[3];
s[2] ^= s[3] << 8;
s[5] += s[2];
s[3] += s[4];
s[3] ^= s[4] >>> 16;
s[6] += s[3];
s[4] += s[5];
s[4] ^= s[5] << 10;
s[7] += s[4];
s[5] += s[6];
s[5] ^= s[6] >>> 4;
s[0] += s[5];
s[6] += s[7];
s[6] ^= s[7] << 8;
s[1] += s[6];
s[7] += s[0];
s[7] ^= s[0] >>> 9;
s[2] += s[7];
s[0] += s[1];
}
private void init(int[] seed)
{
if (seed != null && seed.length != 256)
{
seed = Arrays.copyOf(seed, 256);
}
aa = bb = cc = 0;
int[] initState = new int[8];
Arrays.fill(initState, 0x9e3779b9); // the golden ratio
for (int i = 0; i < 4; i++)
{
mix(initState);
}
for (int i = 0; i < 256; i += 8)
{
if (seed != null)
{
for (int j = 0; j < 8; j++)
{
initState[j] += seed[i + j];
}
}
mix(initState);
for (int j = 0; j < 8; j++)
{
mm[i + j] = initState[j];
}
}
if (seed != null)
{
for (int i = 0; i < 256; i += 8)
{
for (int j = 0; j < 8; j++)
{
initState[j] += mm[i + j];
}
mix(initState);
for (int j = 0; j < 8; j++)
{
mm[i + j] = initState[j];
}
}
}
valuesLeft = 0; // Make sure generateMoreResults() will be called by the next nextInt() call.
}
public int nextInt()
{
if (valuesLeft == 0)
{
generateMoreResults();
assert valuesLeft == 256;
}
int value = randResult[--valuesLeft];
return value;
}
}

View File

@@ -1,99 +0,0 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.proxy;
import java.math.BigInteger;
import java.util.Random;
public class RSA
{
private final BigInteger e = Proxy.SERVER_RSA_KEY_EXPONENT; // Use same exponent as server
private final BigInteger n;
private final BigInteger d;
public RSA()
{
// This taken from http://stackoverflow.com/a/24547249
int keySize = Proxy.SERVER_RSA_KEY_MODULUS.bitLength(); // pick same key size as server
//SecureRandom random = new SecureRandom();
Random random = new Random(42); // Hack to make the modulus always the same
// Choose two distinct prime numbers p and q.
BigInteger p = BigInteger.probablePrime(keySize / 2, random);
BigInteger q = BigInteger.probablePrime(keySize / 2, random);
// Compute n = pq (modulus)
n = p.multiply(q);
// Compute φ(n) = φ(p)φ(q) = (p 1)(q 1) = n - (p + q -1), where φ is Euler's totient function.
// and choose an integer e such that 1 < e < φ(n) and gcd(e, φ(n)) = 1; i.e., e and φ(n) are coprime.
BigInteger m = (p.subtract(BigInteger.ONE)).multiply(q.subtract(BigInteger.ONE));
assert m.gcd(e).equals(BigInteger.ONE); // We always pick SERVER_RSA_KEY_EXPONENT instead
// Determine d as d ≡ e1 (mod φ(n)); i.e., d is the multiplicative inverse of e (modulo φ(n)).
d = e.modInverse(m);
}
public RSA(BigInteger n, BigInteger d)
{
this.n = n;
this.d = d;
}
public BigInteger encrypt(BigInteger value)
{
// C = P**e % n
return value.modPow(e, n);
}
public BigInteger decrypt(BigInteger value)
{
// P = C**d % n
return value.modPow(d, n);
}
public byte[] encrypt(byte[] value)
{
return encrypt(new BigInteger(value)).toByteArray();
}
public byte[] decrypt(byte[] value)
{
return decrypt(new BigInteger(value)).toByteArray();
}
public BigInteger getE()
{
return e;
}
public BigInteger getN()
{
return n;
}
public BigInteger getD()
{
return d;
}
}

View File

@@ -1,45 +0,0 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.proxy;
import java.math.BigInteger;
import org.junit.Assert;
import org.junit.Test;
public class RSATest
{
@Test
public void testSomeMethod()
{
RSA rsa = new RSA();
BigInteger C = rsa.encrypt(BigInteger.valueOf(42));
int value = rsa.decrypt(C).intValue();
Assert.assertEquals(42, value);
}
}