Проверка подписи Telegram Mini App без библиотек

Тридцать строк на Python, чтобы сервер верил только настоящим данным из Telegram.

1 мин чтенияTelegramбезопасностьPython

Мини-приложение получает от Telegram строку initData с данными пользователя и подписью. Доверять ей на сервере можно только после проверки - иначе кто угодно пришлет user.id администратора.

import hashlib
import hmac
import time
from urllib.parse import parse_qsl


def check_init_data(init_data: str, bot_token: str, max_age: int = 86400) -> dict | None:
    pairs = dict(parse_qsl(init_data, keep_blank_values=True))
    received = pairs.pop("hash", None)
    if not received:
        return None

    # Все поля, кроме hash, по алфавиту, через перевод строки.
    check_string = "\n".join(f"{k}={v}" for k, v in sorted(pairs.items()))
    secret = hmac.new(b"WebAppData", bot_token.encode(), hashlib.sha256).digest()
    expected = hmac.new(secret, check_string.encode(), hashlib.sha256).hexdigest()

    if not hmac.compare_digest(expected, received):
        return None  # чужая или подмененная подпись
    if time.time() - int(pairs.get("auth_date", 0)) > max_age:
        return None  # подпись настоящая, но старая
    return pairs

Три вещи, на которых обычно ошибаются:

  • Ключ - не токен бота. Сначала HMAC от токена с ключом WebAppData, и уже им подписывается строка.
  • Сравнение через compare_digest, а не ==: обычное сравнение отвечает быстрее на первом несовпавшем символе, и по времени ответа можно подбирать подпись.
  • Срок жизни. Без проверки auth_date перехваченная однажды строка работает вечно.
Esc

↑↓ выбор Enter открыть