More tests; I identified two issues. First, the temp key generation was wrong and the clientek would have been wrong. Second, the clientek packet ID is incorrect. It needs to start at 1.

This commit is contained in:
Manevolent
2018-07-27 09:54:01 -04:00
parent 5cdedba51c
commit 2c9a6505c0
11 changed files with 82 additions and 51 deletions
@@ -1065,6 +1065,19 @@ public class GroupOperations
FieldOperations.fe_mul(x, h.X, recip);
FieldOperations.fe_mul(y, h.Y, recip);
FieldOperations.fe_tobytes(s, offset, y);
//s[offset + 31] ^= (byte) (FieldOperations.fe_isnegative(x) << 7);
}
public static void ge_p3_tobytes_negate(byte[] s, int offset, GroupElementP3 h)
{
FieldElement recip = new FieldElement();
FieldElement x = new FieldElement();
FieldElement y = new FieldElement();
FieldOperations.fe_invert(recip, h.Z);
FieldOperations.fe_mul(x, h.X, recip);
FieldOperations.fe_mul(y, h.Y, recip);
FieldOperations.fe_tobytes(s, offset, y);
s[offset + 31] ^= (byte) (FieldOperations.fe_isnegative(x) << 7);
}
}
@@ -115,7 +115,6 @@ public class Identity {
return getLeadingZeroBits(outHash);
}
// GOOD
private static int getLeadingZeroBits(byte[] data) {
int curr = 0;
int i ;
@@ -219,8 +219,6 @@ public class License {
byte[] final_ = new byte[32];
GroupOperations.ge_p3_tobytes(final_, 0, r2);
//final_[1] ^= 0x80;
return final_;
}
@@ -20,6 +20,13 @@ public final class Packet {
this.role = role;
}
public Packet(ProtocolRole role, PacketHeader header) {
if (role == null) throw new NullPointerException("role");
this.role = role;
this.header = header;
}
public ProtocolRole getRole() {
return role;
}
@@ -19,12 +19,6 @@ public class PacketBody8Init1 extends PacketBody {
super(INIT1, role);
}
@Override
public void setHeaderValues(PacketHeader header) {
header.setPacketFlag(HeaderFlag.UNENCRYPTED, true);
header.setPacketId((short)101);
}
public byte[] getVersion() {
return version;
}
@@ -91,7 +91,7 @@ public class LocalClientHandlerConnecting extends LocalClientHandler {
// CITE: https://github.com/Splamy/TS3AudioBot/blob/master/TS3Client/Full/Ts3Crypt.cs
// Prepare solution
if (serverReplyStep3.getLevel() < 0 || serverReplyStep3.getLevel() > 1_000_000)
throw new IllegalArgumentException("RSA challange level is not within an acceptable range");
throw new IllegalArgumentException("RSA challenge level is not within an acceptable range");
BigInteger x = new BigInteger(1, serverReplyStep3.getX());
BigInteger n = new BigInteger(1, serverReplyStep3.getN());
@@ -104,6 +104,9 @@ public class PacketTransformation {
ByteBuffer outputBuffer = ByteBuffer.allocate(MAC_LEN + headerWithoutMac.length + (len - MAC_LEN));
// Copy the mac to the packet header
System.arraycopy(result, len - MAC_LEN, packet.getHeader().getMac(), 0, MAC_LEN);
// MAC
outputBuffer.put(result, len - MAC_LEN, MAC_LEN);
@@ -10,15 +10,13 @@ import com.github.manevolent.ts3j.protocol.client.ClientConnectionState;
import com.github.manevolent.ts3j.protocol.header.ClientPacketHeader;
import com.github.manevolent.ts3j.protocol.header.HeaderFlag;
import com.github.manevolent.ts3j.protocol.header.PacketHeader;
import com.github.manevolent.ts3j.protocol.packet.PacketBody;
import com.github.manevolent.ts3j.protocol.packet.PacketBody6Ack;
import com.github.manevolent.ts3j.protocol.packet.PacketBodyFragment;
import com.github.manevolent.ts3j.protocol.packet.PacketBodyType;
import com.github.manevolent.ts3j.protocol.packet.*;
import com.github.manevolent.ts3j.protocol.packet.handler.PacketHandler;
import com.github.manevolent.ts3j.protocol.packet.handler.local.LocalClientHandler;
import com.github.manevolent.ts3j.protocol.packet.transformation.DefaultPacketTransformation;
import com.github.manevolent.ts3j.protocol.packet.transformation.PacketTransformation;
import com.github.manevolent.ts3j.protocol.socket.AbstractTeamspeakSocket;
import com.github.manevolent.ts3j.util.QuickLZ;
import com.github.manevolent.ts3j.util.Ts3Crypt;
import com.github.manevolent.ts3j.util.Ts3Debugging;
@@ -213,7 +211,7 @@ public abstract class AbstractTeamspeakClientSocket
// Set header values
packet.getBody().setHeaderValues(packet.getHeader());
if (packet.getHeader().getType() != PacketBodyType.INIT1) {
if (packet.getHeader().getType() != PacketBodyType.INIT1 && packet.getHeader().getType() != PacketBodyType.ACK) {
packetId++;
packetId = packetId & 0x0000FFFF;
@@ -226,20 +224,35 @@ public abstract class AbstractTeamspeakClientSocket
packet.getHeader().setPacketId(packetId);
}
if (packet.getHeader().getType() == PacketBodyType.COMMAND ||
packet.getHeader().getType() == PacketBodyType.COMMAND_LOW)
switch (packet.getHeader().getType()) {
case INIT1:
packet.getHeader().setPacketFlag(HeaderFlag.UNENCRYPTED, true);
packet.getHeader().setPacketId((short)101);
break;
case COMMAND:
case COMMAND_LOW:
packet.getHeader().setPacketFlag(HeaderFlag.NEW_PROTOCOL, true);
break;
}
if (packet.getSize() > 500) {
if (!packet.getHeader().getType().isSplittable())
throw new IllegalArgumentException("packet too large: " + packet.getSize());
// Split
int totalSize = packet.getBody().getSize();
ByteBuffer outputBuffer = ByteBuffer.allocate(totalSize);
packet.getBody().write(outputBuffer);
byte[] compressed = QuickLZ.compress(outputBuffer.array(), 1);
packet.getHeader().setPacketFlag(HeaderFlag.COMPRESSED, true);
packet.setBody(new PacketBodyCompressed(packet.getHeader().getType(), packet.getRole(), compressed));
if (packet.getSize() <= 500) {
writePacketIntl(packet);
return;
}
if (!packet.getHeader().getType().isSplittable())
throw new IllegalArgumentException("packet too large: " + packet.getSize());
for (int offs = 0; offs < totalSize;) {
int flush = Math.min(500 - packet.getHeader().getSize(), totalSize - offs);
boolean first = offs == 0;
@@ -391,22 +404,31 @@ public abstract class AbstractTeamspeakClientSocket
if (fragment) {
Ts3Debugging.debug("[PROTOCOL] READ " + networkPacket.getHeader().getType().name() + " fragment");
packet.setBody(
new PacketBodyFragment(
networkPacket.getHeader().getType(),
getRole().getIn()
)
);
packet.setBody(new PacketBodyFragment(networkPacket.getHeader().getType(), getRole().getIn()));
} else {
if (packet.getHeader().getPacketFlag(HeaderFlag.COMPRESSED))
packet.setBody(new PacketBodyCompressed(networkPacket.getHeader().getType(), getRole().getIn()));
Ts3Debugging.debug("[PROTOCOL] READ " + networkPacket.getHeader().getType().name());
}
// Compression?
// TODO
// Read packet body
// Read raw packet body
packet.readBody(packetBuffer);
// Finally, handle compressed bodies
if (packet.getBody() instanceof PacketBodyCompressed) {
byte[] decompressed = QuickLZ.decompress(((PacketBodyCompressed) packet.getBody()).getCompressed());
packetBuffer = ByteBuffer.wrap(decompressed);
packet = new Packet(packet.getRole(), packet.getHeader());
packet.readBody(packetBuffer);
Ts3Debugging.debug("[PROTOCOL] DECOMPRESS " + networkPacket.getHeader().getType().name());
}
// Return to parent handler
return packet;
}
@@ -217,17 +217,17 @@ public final class Ts3Crypt {
public static Pair<byte[], byte[]> generateKeypair() {
byte[] privateKey = new byte[32];
new SecureRandom().nextBytes(privateKey);
return generateKeypair(privateKey);
}
public static Pair<byte[], byte[]> generateKeypair(byte[] privateKey) {
ScalarOperations.sc_clamp(privateKey, 0);
GroupElementP3 A = new GroupElementP3();
GroupOperations.ge_scalarmult_base(A, privateKey, 0);
byte[] publicKey = new byte[32];
GroupOperations.ge_p3_tobytes(publicKey, 0, A);
Ts3Debugging.debug(publicKey);
Ts3Debugging.debug(privateKey);
GroupOperations.ge_p3_tobytes_negate(publicKey, 0, A);
return new Pair<>(publicKey, privateKey);
}
@@ -13,6 +13,7 @@ import javafx.util.Pair;
import junit.framework.TestCase;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.Base64;
public class EncryptionTest extends TestCase {
@@ -51,8 +52,7 @@ public class EncryptionTest extends TestCase {
packet.setBody(new PacketBody2Command(ProtocolRole.CLIENT, "clientinit client_nickname=TestClient client_version=3.1.8\\s[Build:\\s1516614607] client_platform=Windows client_input_hardware=1 client_output_hardware=1 client_default_channel= client_default_channel_password= client_server_password=QL0AFWMIX8NRZTKeof9cXsvbvu8= client_meta_data= client_version_sign=gDEgQf\\/BiOQZdAheKccM1XWcMUj2OUQqt75oFuvF2c0MQMXyv88cZQdUuckKbcBRp7RpmLInto4PIgd7mPO7BQ== client_key_offset=6199 client_nickname_phonetic= client_default_token= hwid=+LyYqbDqOvJJpN5pdAbF8\\/v5kZ0="));
byte[] packetBytes = transformation.encrypt(packet).array();
Ts3Debugging.debug(Base64.getEncoder().encode(packetBytes));
transformation.decrypt(header, ByteBuffer.wrap(packetBytes), packet.getBody().getSize());
}
}
@@ -10,20 +10,19 @@ import java.math.BigInteger;
import java.net.InetSocketAddress;
import java.util.Base64;
public class ServerConnectionTest extends TestCase {
public ServerConnectionTest() {
super("ServerConnectionTest");
}
import static org.junit.Assert.assertEquals;
public void testParser() throws Exception {
public class ServerConnectionTest {
public static void main(String[] args) throws Exception {
try {
LocalIdentity localIdentity = LocalIdentity.load(
/**LocalIdentity localIdentity = LocalIdentity.load(
Ts3Crypt.decodePublicKey(Base64.getDecoder()
.decode("MEsDAgcAAgEgAiBpPRbTliVt9KxtIz8saYdwcnNgcwaKLbKYSpDNO87u9gIgSWWPKcSJ9P6VZKJfRdpWwcfMdJv+NA9/hXUtz1uwRVI=")),
new BigInteger(Base64.getDecoder().decode("Tj6YXM3qyRv8n25L2pH+OEJnRUl4auQf8+znjYrOmWU=")),
2294,
2295
);
);**/
LocalIdentity localIdentity = LocalIdentity.generateNew(10);
LocalTeamspeakClientSocket client = new LocalTeamspeakClientSocket();
@@ -41,8 +40,4 @@ public class ServerConnectionTest extends TestCase {
ex.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
new ServerConnectionTest().testParser();
}
}