Complete sending and receiving encrypted functions

master
Lonami Exo 2018-07-25 18:48:13 +02:00
parent a08966d8ec
commit 21eb87781e
9 changed files with 115 additions and 50 deletions

View File

@ -14,7 +14,7 @@ public class Overgram {
final MTProtoSender sender = new MTProtoSender(new MTProtoState(), new TcpFull());
try {
sender.connect("149.154.167.91", 443);
final Future result = sender.send(new Functions.help.GetConfig());
final Future result = sender.send(new Functions.Ping());
System.out.println(result.get());
} finally {
sender.disconnect();

View File

@ -169,6 +169,7 @@ public class MTProtoSender {
doDisconnect();
return;
}
pendingAck.clear();
}
final TLMessage message;
@ -186,7 +187,9 @@ public class MTProtoSender {
while (!message.future.isCancelled()) {
try {
connection.send(body);
break;
} catch (IOException ignored) {
// TODO e.g. on timeout retry (loop; not done yet)
try {
Thread.sleep(1000);
doReconnect();
@ -228,7 +231,7 @@ public class MTProtoSender {
private void processMessage(final TLMessage message) throws InterruptedException {
pendingAck.add(message.id);
if (message.object instanceof RpcResult) {
if (message.object instanceof RPCResult) {
handleRpcResult(message);
} else if (message.object instanceof MessageContainer) {
handleContainer(message);
@ -262,11 +265,15 @@ public class MTProtoSender {
}
private void handleRpcResult(final TLMessage message) {
final RpcResult result = (RpcResult) message.object;
final TLMessage replyMessage = pendingMessages.remove(result.reqMsgId());
final RPCResult result = (RPCResult) message.object;
final TLMessage replyMessage = pendingMessages.remove(result.reqMsgId);
// TODO RPC error
final BinaryReader reader = new BinaryReader(ByteBuffer.wrap(result.result()));
if (result.error != null) {
replyMessage.future.completeExceptionally(new RPCError(result.error));
return;
}
final BinaryReader reader = new BinaryReader(ByteBuffer.wrap(result.result));
try {
replyMessage.future.complete(((TLRequest) replyMessage.object).readResult(reader));
} catch (ClassNotFoundException e) {
@ -276,7 +283,7 @@ public class MTProtoSender {
public void handleContainer(final TLMessage message) throws InterruptedException {
final MessageContainer result = (MessageContainer) message.object;
for (final TLMessage innerMessage : result.messages()) {
for (final TLMessage innerMessage : result.messages) {
processMessage(innerMessage);
}
}

View File

@ -101,7 +101,9 @@ public class MTProtoState {
final Pair<byte[], byte[]> keyIv = calcKey(msgKey, false);
final byte[] plainText = AES.decryptIge(reader.read(), keyIv.getKey(), keyIv.getValue());
final byte[] ourKey = Utils.sha256digest(ByteBuffer.wrap(authKey.key, 96, 32).array(), body);
final byte[] ourKey = Arrays.copyOfRange(Utils.sha256digest(
Arrays.copyOfRange(authKey.key, 96, 128), plainText), 8, 24);
if (!Arrays.equals(msgKey, ourKey)) {
throw new SecurityException("Received message key doesn't match with expected one");
}
@ -112,11 +114,11 @@ public class MTProtoState {
throw new SecurityException("Server replied with a wrong session ID");
}
final long remoteMsgId = reader.readLong();
final int remoteSeq = reader.readInt();
reader.readInt(); // inner message length
final long remoteMsgId = tlReader.readLong();
final int remoteSeq = tlReader.readInt();
tlReader.readInt(); // inner message length
final TLObject object = reader.readTl();
final TLObject object = tlReader.readTl();
return new TLMessage(remoteMsgId, remoteSeq, object);
}

View File

@ -7,16 +7,20 @@ public class GzipPacked extends TLObject {
public static final int CONSTRUCTOR_ID = 812830625;
@Override
public void serialize(BinaryWriter writer) {
public void serialize(final BinaryWriter writer) {
throw new UnsupportedOperationException();
}
@Override
public void deserialize(BinaryReader reader) throws ClassNotFoundException {
public void deserialize(final BinaryReader reader) throws ClassNotFoundException {
throw new UnsupportedOperationException();
}
public TLObject packedObject() {
throw new UnsupportedOperationException();
}
public static byte[] unzip(final BinaryReader reader) {
throw new UnsupportedOperationException();
}
}

View File

@ -3,22 +3,31 @@ package io.github.lonamiwebs.overgram.tl;
import io.github.lonamiwebs.overgram.utils.BinaryReader;
import io.github.lonamiwebs.overgram.utils.BinaryWriter;
import java.util.ArrayList;
import java.util.List;
public class MessageContainer extends TLObject {
public static final int CONSTRUCTOR_ID = 1945237724;
final public List<TLMessage> messages = new ArrayList<>();
@Override
public void serialize(BinaryWriter writer) {
public void serialize(final BinaryWriter writer) {
throw new UnsupportedOperationException();
}
@Override
public void deserialize(BinaryReader reader) throws ClassNotFoundException {
throw new UnsupportedOperationException();
}
public List<TLMessage> messages() {
throw new UnsupportedOperationException();
public void deserialize(final BinaryReader reader) throws ClassNotFoundException {
messages.clear();
final int count = reader.readInt();
for (int i = 0; i < count; ++i) {
final long msgId = reader.readLong();
final int seqNo = reader.readInt();
final int length = reader.readInt();
final int before = reader.tell();
final TLObject object = reader.readTl();
reader.set(before + length);
messages.add(new TLMessage(msgId, seqNo, object));
}
}
}

View File

@ -0,0 +1,14 @@
package io.github.lonamiwebs.overgram.tl;
import java.rmi.RemoteException;
public class RPCError extends RemoteException {
public final int code;
public final String value;
public RPCError(final Types.RpcError from) {
super(String.format("RPC error %d: %s", from.errorCode(), from.errorMessage()));
code = from.errorCode();
value = from.errorMessage();
}
}

View File

@ -0,0 +1,33 @@
package io.github.lonamiwebs.overgram.tl;
import io.github.lonamiwebs.overgram.utils.BinaryReader;
import io.github.lonamiwebs.overgram.utils.BinaryWriter;
import java.util.Arrays;
public class RPCResult extends TLObject {
public static final int CONSTRUCTOR_ID = -212046591;
public long reqMsgId;
public Types.RpcError error;
public byte[] result;
@Override
public void serialize(final BinaryWriter writer) {
throw new UnsupportedOperationException();
}
@Override
public void deserialize(final BinaryReader reader) throws ClassNotFoundException {
reqMsgId = reader.readLong();
final int code = reader.readInt();
if (code == Types.RpcError.CONSTRUCTOR_ID) {
error = new Types.RpcError();
error.deserialize(reader);
} else if (code == GzipPacked.CONSTRUCTOR_ID) {
result = GzipPacked.unzip(reader);
} else {
result = reader.read();
}
}
}

View File

@ -1,26 +0,0 @@
package io.github.lonamiwebs.overgram.tl;
import io.github.lonamiwebs.overgram.utils.BinaryReader;
import io.github.lonamiwebs.overgram.utils.BinaryWriter;
public class RpcResult extends TLObject {
public static final int CONSTRUCTOR_ID = -212046591;
@Override
public void serialize(BinaryWriter writer) {
throw new UnsupportedOperationException();
}
@Override
public void deserialize(BinaryReader reader) throws ClassNotFoundException {
throw new UnsupportedOperationException();
}
public long reqMsgId() {
throw new UnsupportedOperationException();
}
public byte[] result() {
throw new UnsupportedOperationException();
}
}

View File

@ -1,7 +1,6 @@
package io.github.lonamiwebs.overgram.utils;
import io.github.lonamiwebs.overgram.tl.TLObject;
import io.github.lonamiwebs.overgram.tl.Types;
import io.github.lonamiwebs.overgram.tl.*;
import java.math.BigInteger;
import java.nio.ByteBuffer;
@ -111,7 +110,22 @@ public class BinaryReader {
}
public TLObject readTl() throws ClassNotFoundException {
final TLObject object = Types.getFromId(readInt());
final int id = readInt();
final TLObject object;
switch (id) {
case RPCResult.CONSTRUCTOR_ID:
object = new RPCResult();
break;
case GzipPacked.CONSTRUCTOR_ID:
object = new GzipPacked();
break;
case MessageContainer.CONSTRUCTOR_ID:
object = new MessageContainer();
break;
default:
object = Types.getFromId(id);
break;
}
object.deserialize(this);
return object;
}
@ -126,10 +140,18 @@ public class BinaryReader {
return result;
}
public int tell() {
return buffer.position();
}
public void seek(final int delta) {
buffer.position(buffer.position() + delta);
}
public void set(final int position) {
buffer.position(position);
}
public byte[] read(final int size) {
final byte[] result = new byte[size];
buffer.get(result);