package ru.denull.mtproto;
import static ru.denull.mtproto.CryptoUtils.*;
import java.nio.*;
import tl.TLObject;
public class EncryptedMessage extends Message {
public long auth_key_id;
public long server_salt;
public long session_id;
public int seq_no;
public boolean significant;
public EncryptedMessage(long message_id, TLObject payload, long session_id, long auth_key_id, long server_salt, int seq_no, boolean significant) {
super(message_id, payload);
this.auth_key_id = auth_key_id;
this.server_salt = server_salt;
this.session_id = session_id;
this.seq_no = seq_no;
this.significant = significant;
}
public EncryptedMessage(long message_id, TLObject payload, long session_id, long auth_key_id, long server_salt, int seq_no) {
super(message_id, payload);
this.auth_key_id = auth_key_id;
this.server_salt = server_salt;
this.session_id = session_id;
this.seq_no = seq_no;
}
public ByteBuffer encrypt(byte[] auth_key) throws Exception {
//System.out.println("sending " + payload);
if (error != 0) {
return ByteBuffer.allocateDirect(4).putInt(-error);
}
if (auth_key == null) {
throw new Exception("auth_key missing!");
}
int innerSize = payload.length(true);
int size = innerSize + 32;
while ((size % 16) != 0) size++; // TODO: fix
ByteBuffer buffer = ByteBuffer.allocateDirect(size + 24);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putLong(auth_key_id);
ByteBuffer innerBuffer = ByteBuffer.allocateDirect(size);
innerBuffer.order(ByteOrder.LITTLE_ENDIAN);
innerBuffer.putLong(server_salt);
innerBuffer.putLong(session_id);
innerBuffer.putLong(message_id);
innerBuffer.putInt(seq_no * 2 + (significant ? 1 : 0));
innerBuffer.putInt(innerSize);
payload.writeTo(innerBuffer);
byte[] msg_key = substr(SHA1(innerBuffer, 0, innerSize + 32), 4, 16);
buffer.put(msg_key);
int x = 0;
byte[] sha1_a = SHA1(concat(msg_key, substr(auth_key, x, 32)));
byte[] sha1_b = SHA1(concat(substr(auth_key, 32 + x, 16), msg_key, substr(auth_key, 48 + x, 16)));
byte[] sha1_c = SHA1(concat(substr(auth_key, 64 + x, 32), msg_key));
byte[] sha1_d = SHA1(concat(msg_key, substr(auth_key, 96 + x, 32)));
byte[] aes_key = concat(substr(sha1_a, 0, 8), substr(sha1_b, 8, 12), substr(sha1_c, 4, 12));
byte[] aes_iv = concat(substr(sha1_a, 8, 12), substr(sha1_b, 0, 8), substr(sha1_c, 16, 4), substr(sha1_d, 0, 8));
buffer.put(AESEncrypt(innerBuffer, 0, size, aes_key, aes_iv));
buffer.rewind();
return buffer;
}
}