Add a few security checks when unpacking messages from server

Also delete MtProto 1.0 leftovers.
This commit is contained in:
Lonami Exo 2018-01-06 02:03:23 +01:00
parent 3eafe18d0b
commit 6f690945f1
2 changed files with 16 additions and 25 deletions

View File

@ -4,6 +4,7 @@ import struct
from hashlib import sha1, sha256 from hashlib import sha1, sha256
from telethon.crypto import AES from telethon.crypto import AES
from telethon.errors import SecurityError
from telethon.extensions import BinaryReader from telethon.extensions import BinaryReader
@ -39,7 +40,7 @@ def pack_message(session, message):
# "msg_key = substr (msg_key_large, 8, 16)" # "msg_key = substr (msg_key_large, 8, 16)"
msg_key = msg_key_large[8:24] msg_key = msg_key_large[8:24]
aes_key, aes_iv = calc_key_2(session.auth_key.key, msg_key, True) aes_key, aes_iv = calc_key(session.auth_key.key, msg_key, True)
key_id = struct.pack('<Q', session.auth_key.key_id) key_id = struct.pack('<Q', session.auth_key.key_id)
return key_id + msg_key + AES.encrypt_ige(data + padding, aes_key, aes_iv) return key_id + msg_key + AES.encrypt_ige(data + padding, aes_key, aes_iv)
@ -48,43 +49,32 @@ def pack_message(session, message):
def unpack_message(session, reader): def unpack_message(session, reader):
"""Unpacks a message following MtProto 2.0 guidelines""" """Unpacks a message following MtProto 2.0 guidelines"""
# See https://core.telegram.org/mtproto/description # See https://core.telegram.org/mtproto/description
reader.read_long(signed=False) # remote_auth_key_id if reader.read_long(signed=False) != session.auth_key.key_id:
raise SecurityError('Server replied with an invalid auth key')
msg_key = reader.read(16) msg_key = reader.read(16)
aes_key, aes_iv = calc_key_2(session.auth_key.key, msg_key, False) aes_key, aes_iv = calc_key(session.auth_key.key, msg_key, False)
data = BinaryReader(AES.decrypt_ige(reader.read(), aes_key, aes_iv)) data = BinaryReader(AES.decrypt_ige(reader.read(), aes_key, aes_iv))
data.read_long() # remote_salt data.read_long() # remote_salt
data.read_long() # remote_session_id if data.read_long() != session.id:
raise SecurityError('Server replied with a wrong session ID')
remote_msg_id = data.read_long() remote_msg_id = data.read_long()
remote_sequence = data.read_int() remote_sequence = data.read_int()
msg_len = data.read_int() msg_len = data.read_int()
message = data.read(msg_len) message = data.read(msg_len)
# https://core.telegram.org/mtproto/security_guidelines
# Sections "checking sha256 hash" and "message length"
if msg_key != sha256(
session.auth_key.key[96:96 + 32] + data.get_bytes()).digest()[8:24]:
raise SecurityError("Received msg_key doesn't match with expected one")
return message, remote_msg_id, remote_sequence return message, remote_msg_id, remote_sequence
def calc_key(shared_key, msg_key, client): def calc_key(auth_key, msg_key, client):
"""
Calculate the key based on Telegram guidelines,
specifying whether it's the client or not.
"""
x = 0 if client else 8
sha1a = sha1(msg_key + shared_key[x:x + 32]).digest()
sha1b = sha1(shared_key[x + 32:x + 48] + msg_key +
shared_key[x + 48:x + 64]).digest()
sha1c = sha1(shared_key[x + 64:x + 96] + msg_key).digest()
sha1d = sha1(msg_key + shared_key[x + 96:x + 128]).digest()
key = sha1a[0:8] + sha1b[8:20] + sha1c[4:16]
iv = sha1a[8:20] + sha1b[0:8] + sha1c[16:20] + sha1d[0:8]
return key, iv
def calc_key_2(auth_key, msg_key, client):
""" """
Calculate the key based on Telegram guidelines Calculate the key based on Telegram guidelines
for MtProto 2, specifying whether it's the client or not. for MtProto 2, specifying whether it's the client or not.

View File

@ -53,6 +53,7 @@ class CryptoTests(unittest.TestCase):
@staticmethod @staticmethod
def test_calc_key(): def test_calc_key():
# TODO Upgrade test for MtProto 2.0
shared_key = b'\xbc\xd2m\xb7\xcav\xf4][\x88\x83\' \xf3\x11\x8as\xd04\x941\xae' \ shared_key = b'\xbc\xd2m\xb7\xcav\xf4][\x88\x83\' \xf3\x11\x8as\xd04\x941\xae' \
b'*O\x03\x86\x9a/H#\x1a\x8c\xb5j\xe9$\xe0IvCm^\xe70\x1a5C\t\x16' \ b'*O\x03\x86\x9a/H#\x1a\x8c\xb5j\xe9$\xe0IvCm^\xe70\x1a5C\t\x16' \
b'\x03\xd2\x9d\xa9\x89\xd6\xce\x08P\x0fdr\xa0\xb3\xeb\xfecv\x1a' \ b'\x03\xd2\x9d\xa9\x89\xd6\xce\x08P\x0fdr\xa0\xb3\xeb\xfecv\x1a' \