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()); final MTProtoSender sender = new MTProtoSender(new MTProtoState(), new TcpFull());
try { try {
sender.connect("149.154.167.91", 443); 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()); System.out.println(result.get());
} finally { } finally {
sender.disconnect(); sender.disconnect();

View File

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

View File

@ -101,7 +101,9 @@ public class MTProtoState {
final Pair<byte[], byte[]> keyIv = calcKey(msgKey, false); final Pair<byte[], byte[]> keyIv = calcKey(msgKey, false);
final byte[] plainText = AES.decryptIge(reader.read(), keyIv.getKey(), keyIv.getValue()); 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)) { if (!Arrays.equals(msgKey, ourKey)) {
throw new SecurityException("Received message key doesn't match with expected one"); 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"); throw new SecurityException("Server replied with a wrong session ID");
} }
final long remoteMsgId = reader.readLong(); final long remoteMsgId = tlReader.readLong();
final int remoteSeq = reader.readInt(); final int remoteSeq = tlReader.readInt();
reader.readInt(); // inner message length tlReader.readInt(); // inner message length
final TLObject object = reader.readTl(); final TLObject object = tlReader.readTl();
return new TLMessage(remoteMsgId, remoteSeq, object); return new TLMessage(remoteMsgId, remoteSeq, object);
} }

View File

@ -7,16 +7,20 @@ public class GzipPacked extends TLObject {
public static final int CONSTRUCTOR_ID = 812830625; public static final int CONSTRUCTOR_ID = 812830625;
@Override @Override
public void serialize(BinaryWriter writer) { public void serialize(final BinaryWriter writer) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
public void deserialize(BinaryReader reader) throws ClassNotFoundException { public void deserialize(final BinaryReader reader) throws ClassNotFoundException {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public TLObject packedObject() { public TLObject packedObject() {
throw new UnsupportedOperationException(); 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.BinaryReader;
import io.github.lonamiwebs.overgram.utils.BinaryWriter; import io.github.lonamiwebs.overgram.utils.BinaryWriter;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class MessageContainer extends TLObject { public class MessageContainer extends TLObject {
public static final int CONSTRUCTOR_ID = 1945237724; public static final int CONSTRUCTOR_ID = 1945237724;
final public List<TLMessage> messages = new ArrayList<>();
@Override @Override
public void serialize(BinaryWriter writer) { public void serialize(final BinaryWriter writer) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
public void deserialize(BinaryReader reader) throws ClassNotFoundException { public void deserialize(final BinaryReader reader) throws ClassNotFoundException {
throw new UnsupportedOperationException(); messages.clear();
} final int count = reader.readInt();
for (int i = 0; i < count; ++i) {
public List<TLMessage> messages() { final long msgId = reader.readLong();
throw new UnsupportedOperationException(); 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; package io.github.lonamiwebs.overgram.utils;
import io.github.lonamiwebs.overgram.tl.TLObject; import io.github.lonamiwebs.overgram.tl.*;
import io.github.lonamiwebs.overgram.tl.Types;
import java.math.BigInteger; import java.math.BigInteger;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -111,7 +110,22 @@ public class BinaryReader {
} }
public TLObject readTl() throws ClassNotFoundException { 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); object.deserialize(this);
return object; return object;
} }
@ -126,10 +140,18 @@ public class BinaryReader {
return result; return result;
} }
public int tell() {
return buffer.position();
}
public void seek(final int delta) { public void seek(final int delta) {
buffer.position(buffer.position() + delta); buffer.position(buffer.position() + delta);
} }
public void set(final int position) {
buffer.position(position);
}
public byte[] read(final int size) { public byte[] read(final int size) {
final byte[] result = new byte[size]; final byte[] result = new byte[size];
buffer.get(result); buffer.get(result);