Документація telegram створення ключа авторизації
При описі формату запитів використовується двійкова сериализация даних і мова TL. Всі великі числа передаються як рядки (string), що містять потрібну послідовність байтів в порядку big-endian. Хеш-функції на кшталт SHA1 повертають рядки (з 20 байтів), які також можуть бути проінтерпретовані як big-endian числа. Маленькі числа (int. Long. Int128. Int256) зазвичай little-endian; однак якщо вони являють собою частину SHA1, то байти не переставляти. Таким чином, якщо long x є молодші 64 біта від SHA1 від рядка s. то беруться останні 8 байтів 20-байтной рядки SHA1 (s). і інтерпретуються як 64-бітове ціле.
Послідовність дій
обчислення nonce
Клієнт шле серверу запит:
Значення nonce вибирається клієнтом довільно (випадкове число); воно ідентифікує клієнта в рамках даного обміну. Після цього кроку воно відомо всім.
відповідь сервера
Сервер відправляє відповідь у вигляді:
Тут «рядок» pq є записом натурального числа (в двійковій системі в форматі big-endian). Це число є твором двох різних непарних простих чисел. Зазвичай pq не перевищує 2 ^ 63-1. Значення server_nonce вибирається сервером довільно; після цього кроку він відомий всім.
server_public_key_fingerprints - це список відбитків публічних RSA-ключів (молодші 64 біта SHA1 (server_public_key); при цьому публічний ключ представляється як голий тип rsa_public_key n: string e: string = RSAPublicKey (bare type; детальніше про типи см. в статті «сериализация бінарних даних »), де, як правило, n і е - числа в форматі big-endian, серіалізовані як рядки байтів, після чого і обчислюється SHA1), прийнятих сервером.
Відзначимо, що всі наступні повідомлення містять пару (nonce. Server_nonce) і у відкритій, і в зашифрованою частини, що дозволяє використовувати її для ідентифікації «тимчасової сесії» (одного запуску обговорюваного протоколу створення ключів). Зловмисник не в змозі створити паралельну сесію з сервером з такими ж параметрами і перевикористати зашифровані клієнтом або сервером частини їх повідомлень в своїх цілях в паралельній сесії, оскільки для нової «тимчасової сесії» сервером буде обраний інший server_nonce.
Доказ виконання роботи
Клієнт розкладає число pq на прості множники p Тепер починається раунд обміну ключів по Діффі-Хелманом: Клієнт відправляє запит: Тут encrypted_data отримують у такий спосіб: Тут encrypted_answer виходить таким чином: Після цього кроку new_nonce все ще відомо тільки клієнту і серверу. Клієнт впевнений, що відповів саме сервер і що відповідь згенерований спеціально у відповідь на запит клієнта req_DH_params, оскільки дані відповіді шифруються з використанням new_nonce. Від клієнта очікується перевірка того, чи є p = dh_prime вірним 2048-бітовим простим числом (мається на увазі, що і p і (p-1) / 2 є простими числами, і що 2 ^ 2047
Якщо верифікація займає надто багато часу (в разі використання більш старих мобільних девайсів), вона може спочатку запустити тільки 15 ітерацій Міллера-Рабіна для верифікації первинності / приналежності до простих чисел p і (p - 1) / 2 з ймовірністю помилки не перевищує одну мільярдну , і зробити більше ітерацій пізніше у фоновому режимі. Інший оптимізацією може бути вбудовування в код програми клієнта маленьку таблицю з деякими «хорошими» парами (g, p) (або просто відомі вірні прості числа p, оскільки g легко перевіряється під час виконання), що перевіряється під час фази генерації коду, щоб уникнути виконання такий верифікації під час виконання. Сервер змінює ці значення рідко, таким чином зазвичай потрібно підставити в таку таблицю поточне значення dh_prime сервера. Наприклад, поточне значення dh_prime дорівнює (в порядку байт big-endian) Клієнт обчислює рандомноє 2048-бітове число b (використовуючи достатню кількість ентропії) і посилає серверу запит: Тут encrypted_data виходить таким чином: Поле retry_id дорівнює нулю під час першої спроби; або дорівнює auth_key_aux_hash від попередньої зафейленной спроби (див. пункт 9). Відповідно, auth_key дорівнює pow (g,) mod dh_prime; на сервері воно обчислюється як pow (g_b, a) mod dh_prime. а на клієнті як (g_a) ^ b mod dh_prime. auth_key_hash обчислюється: = 64 біта нижнього порядку SHA1 (auth_key). Сервер перевіряє, чи є вже інший ключ з таким же auth_key_hash і відповідає одним із таких способів. Сервер відповідає одним з трьох способів: В іншому випадку, клієнт звертається до пункту 6) генеруючи нове b. У першому випадку, клієнт і сервер реалізують auth_key. після чого вони забувають всі інші тимчасові дані, і клієнт створює іншу зашифровану сесію використовуючи auth_key. У той же самий час server_salt спочатку встановлюється як substr (new_nonce, 0, 8) XOR substr (server_nonce, 0, 8). При необхідності клієнт зберігає різницю між server_time отриманим в пункті 5) і своїм місцевим часом, щоб мати хорошу приблизну точність до часу сервера, яка потрібна для генерації правильних ідентифікаторів повідомлення. У тому випадку, якщо клієнт не отримує жодної відповіді від сервера на свій запит протягом якогось часу, він може просто повторити запит. Якщо сервер вже відправляв відповідь на цей запит (рівно на цей запит, а не на такий же - всі параметри при повторі повинні приймати те ж значення), але він не дійшов до клієнта, сервер просто повторить той же відповідь. Сервер пам'ятає відповідь до 10 хвилин після моменту отримання запиту 1). Якщо ж сервер вже забув відповідь або необхідні тимчасові дані, клієнтові доведеться почати все з самого початку. Сервер має право вважати, що якщо клієнт вже надіслав наступний запит, який використовує дані з попередньої відповіді сервера даного клієнта, то ця відповідь свідомо отриманий клієнтом і сервер може його забути.Відправка сервера і аутентифікація
Сервер відповідає двома способами:
генерація ключа
обчислення auth_key
обчислення auth_key_hash
Завершення обміну ключами
Обробка помилок
приклад використання