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:
@@ -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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -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());
|
||||
|
||||
+3
@@ -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);
|
||||
|
||||
|
||||
+43
-21
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user