Beispiel #1
0
def prepare_key_to_read(auth_key: bytes, msg_key: bytes):
    sha1_a = sha1(msg_key + auth_key[8:40])
    sha1_b = sha1(auth_key[40:56] + msg_key + auth_key[56:72])
    sha1_c = sha1(auth_key[72:104] + msg_key)
    sha1_d = sha1(msg_key + auth_key[104:136])
    aes_key = sha1_a[:8] + sha1_b[8:20] + sha1_c[4:16]
    aes_iv = sha1_a[8:20] + sha1_b[:8] + sha1_c[16:20] + sha1_d[:8]
    aes = AesIge(aes_key, aes_iv)
    return aes
Beispiel #2
0
def prepare_key_to_write(auth_key: bytes, msg_key: bytes):
    sha1_a = sha1(msg_key + auth_key[:32])
    sha1_b = sha1(auth_key[32:48] + msg_key + auth_key[48:64])
    sha1_c = sha1(auth_key[64:96] + msg_key)
    sha1_d = sha1(msg_key + auth_key[96:128])
    aes_key = sha1_a[:8] + sha1_b[8:20] + sha1_c[4:16]
    aes_iv = sha1_a[8:20] + sha1_b[:8] + sha1_c[16:20] + sha1_d[:8]
    aes = AesIge(aes_key, aes_iv)
    return aes
Beispiel #3
0
def prepare_key_to_read(auth_key: bytes, msg_key: bytes):
    sha1_a = sha1(msg_key + auth_key[8:40])
    sha1_b = sha1(auth_key[40:56] + msg_key + auth_key[56:72])
    sha1_c = sha1(auth_key[72:104] + msg_key)
    sha1_d = sha1(msg_key + auth_key[104:136])
    aes_key = sha1_a[:8] + sha1_b[8:20] + sha1_c[4:16]
    aes_iv = sha1_a[8:20] + sha1_b[:8] + sha1_c[16:20] + sha1_d[:8]
    aes = AesIge(aes_key, aes_iv)
    return aes
Beispiel #4
0
def prepare_key_to_write(auth_key: bytes, msg_key: bytes):
    sha1_a = sha1(msg_key + auth_key[:32])
    sha1_b = sha1(auth_key[32:48] + msg_key + auth_key[48:64])
    sha1_c = sha1(auth_key[64:96] + msg_key)
    sha1_d = sha1(msg_key + auth_key[96:128])
    aes_key = sha1_a[:8] + sha1_b[8:20] + sha1_c[4:16]
    aes_iv = sha1_a[8:20] + sha1_b[:8] + sha1_c[16:20] + sha1_d[:8]
    aes = AesIge(aes_key, aes_iv)
    return aes
Beispiel #5
0
    async def _create_auth_key(self):
        generate_b = self._loop.create_task(
            self._in_thread(secrets.randbits, 2048))
        nonce = await self._in_thread(secrets.token_bytes, 16)

        await self._write_unencrypted_message(_cons='req_pq', nonce=nonce)

        respq = (await self._read_unencrypted_message()).body

        # check if we have got the right public key
        if self._public_rsa_key.fingerprint not in respq.server_public_key_fingerprints:
            raise ValueError("Our certificate is not supported by the server")

        server_nonce = respq.server_nonce
        pq = int.from_bytes(respq.pq, 'big', signed=False)

        new_nonce, (p, q) = await asyncio.gather(
            self._in_thread(secrets.token_bytes, 32),
            self._in_thread(primes.factorize, pq))

        p_string = to_bytes(p)
        q_string = to_bytes(q)

        # request Diffie–Hellman parameters
        p_q_inner_data = self._scheme.boxed(
            _cons='p_q_inner_data',
            pq=respq.pq,
            p=p_string,
            q=q_string,
            nonce=nonce,
            server_nonce=server_nonce,
            new_nonce=new_nonce).get_flat_bytes()

        await self._write_unencrypted_message(
            _cons='req_DH_params',
            nonce=nonce,
            server_nonce=server_nonce,
            p=p_string,
            q=q_string,
            public_key_fingerprint=self._public_rsa_key.fingerprint,
            encrypted_data=self._public_rsa_key.encrypt_with_hash(
                p_q_inner_data))
        params = (await self._read_unencrypted_message()).body

        if params != 'server_DH_params_ok' or params.nonce != nonce or params.server_nonce != server_nonce:
            raise RuntimeError("Diffie–Hellman exchange failed: `%r`", params)

        # https://core.telegram.org/mtproto/auth_key#presenting-proof-of-work-server-authentication
        tmp_aes_key = sha1(new_nonce + server_nonce) + sha1(server_nonce +
                                                            new_nonce)[:12]
        tmp_aes_iv = sha1(server_nonce +
                          new_nonce)[12:] + sha1(new_nonce +
                                                 new_nonce) + new_nonce[:4]

        tmp_aes = encryption.AesIge(tmp_aes_key, tmp_aes_iv)
        answer, b = await asyncio.gather(
            self._in_thread(tmp_aes.decrypt_with_hash,
                            params.encrypted_answer), generate_b)

        params2 = await self._scheme.read_from_string(answer)

        # FIXME! save server_time
        # print(params2.server_time)
        # print(time.time())

        if params2 != 'server_DH_inner_data':
            raise RuntimeError("Diffie–Hellman exchange failed: `%r`", params2)

        dh_prime = int.from_bytes(params2.dh_prime, 'big')
        g = params2.g
        g_a = int.from_bytes(params2.g_a, 'big')
        if (params2.nonce != nonce or params2.server_nonce != server_nonce
                or not primes.is_safe_dh_prime(g, dh_prime)):
            raise RuntimeError("Diffie–Hellman exchange failed: `%r`", params2)

        g_b, self._auth_key = map(
            to_bytes, await
            asyncio.gather(self._in_thread(pow, g, b, dh_prime),
                           self._in_thread(pow, g_a, b, dh_prime)))
        self._set_auth_key_id()
        self._server_salt = int.from_bytes(xor(new_nonce[:8],
                                               server_nonce[:8]),
                                           'little',
                                           signed=True)

        client_DH_inner_data = self._scheme.boxed(_cons='client_DH_inner_data',
                                                  nonce=nonce,
                                                  server_nonce=server_nonce,
                                                  retry_id=0,
                                                  g_b=g_b).get_flat_bytes()

        tmp_aes = encryption.AesIge(tmp_aes_key, tmp_aes_iv)
        await self._write_unencrypted_message(_cons='set_client_DH_params',
                                              nonce=nonce,
                                              server_nonce=server_nonce,
                                              encrypted_data=await
                                              self._in_thread(
                                                  tmp_aes.encrypt_with_hash,
                                                  client_DH_inner_data))

        params3 = (await self._read_unencrypted_message()).body

        if params3 != 'dh_gen_ok':
            raise RuntimeError("Diffie–Hellman exchange failed: `%r`", params3)
Beispiel #6
0
 def _set_auth_key_id(self):
     self._auth_key_id = sha1(self._auth_key)[-8:]
Beispiel #7
0
 def encrypt_with_hash(self, plain: bytes) -> bytes:
     return self.encrypt(sha1(plain) + plain)
Beispiel #8
0
 def encrypt_with_hash(self, plain: bytes) -> bytes:
     return self.encrypt(sha1(plain) + plain)