Как можно проверить данные, полученные из Telegram Web App, используя Python?

Привет! Я столкнулся с проблемой в следующем коде: <br/> <pre><code class="python">import hmac
import hashlib
from urllib.parse import unquote, parse_qs


def get_secret_key(bot_token: str) -&gt; bytes:
    """
    Генерация секретного ключа с использованием HMAC-SHA-256 и строки 'WebAppData'.
    """
    return hmac.new(b"WebAppData", bot_token.encode(), hashlib.sha256).digest()


def validate_hash(init_data: dict, bot_token: str) -&gt; bool:
    """
    Проверяет данные, полученные от Telegram Web App.
    """
    init_data = unquote(init_data)
    init_data = parse_qs(init_data)
    secret_key = get_secret_key(bot_token)

    # Извлекаем hash и удаляем его из данных
    received_hash = init_data.pop("hash", None)
    if not received_hash:
        return False

    # Формируем data-check-string
    data_check_string = "\n".join(f"{key}={value}" for key, value in sorted(init_data.items()))

    # Генерируем HMAC-SHA-256 hash
    calculated_hash = hmac.new(secret_key, data_check_string.encode(), hashlib.sha256).hexdigest()

    return hmac.compare_digest(calculated_hash, received_hash[0])</code></pre> <br/> <br/> Несмотря на то, что я указываю только <pre><code>"auth_date=&lt;auth_date&gt;\nquery_id=&lt;query_id&gt;\nuser=&lt;user&gt;"</code></pre> в строке data_check_string, хеши, которые я получаю, все время различаются. Можете подсказать, что необходимо изменить, чтобы исправить эту ситуацию?
  • 25 декабря 2024 г. 5:53
Ответы на вопрос 1
Ваша функция `validate_hash` подходит в целом, но есть несколько моментов, которые могут вызывать несоответствие хэш-значений.

1. **Правильный порядок параметров**: Убедитесь, что вы сортируете параметры в словаре так, как они передаются из Telegram. В частности, ключи и значения в `init_data` должны быть правильно экранированы и представлены в одной строке.

2. **Кодирование данных**: В строке `data_check_string` вы должны убедиться, что правильно обрабатываете значения. WebApp передает данные в виде строки, где значения могут быть закодированы в URL. Использование `unquote` здесь может быть ошибочным, так как значения уже должны использоваться в исходном виде без изменений. Также вам нужно убедиться, что вы корректно обрабатываете символы перевода строки и пробелы.

3. **Проверка на наличие ключа**: Проверьте, что вы правильно извлекаете ключи и значения от `init_data`. Например, ключи могут быть закодированы, и значения могут содержать символы, которые могут вызвать неправильное поведение.

4. **Проверка формата строки**: Убедитесь, что строки формируются корректно. Например, необходимо объединить ключ и значение с символом `=` и использовать `\n` для разделения пар.

Вот обновленный код, который может помочь вам справиться с этой проблемой:

```python
import hmac
import hashlib
from urllib.parse import unquote, parse_qs

def get_secret_key(bot_token: str) -> bytes:
    return hmac.new(b"WebAppData", bot_token.encode(), hashlib.sha256).digest()

def validate_hash(init_data: str, bot_token: str) -> bool:
    # Декодируем и парсим данные
    init_data = unquote(init_data)
    init_data_dict = parse_qs(init_data)
    
    secret_key = get_secret_key(bot_token)

    # Извлекаем hash и удаляем его из данных
    received_hash = init_data_dict.pop("hash", None)
    if not received_hash:
        return False

    # Формируем data-check-string
    data_check_string = "\n".join(f"{key}={value[0]}" for key, value in sorted(init_data_dict.items()))

    # Генерируем HMAC-SHA-256 hash
    calculated_hash = hmac.new(secret_key, data_check_string.encode(), hashlib.sha256).hexdigest()

    return hmac.compare_digest(calculated_hash, received_hash[0])
```

### Основные изменения:
1. Убедился, что значения в `init_data_dict` обрабатываются правильно, включая их извлечение через `[0]` (так как `parse_qs` возвращает список значений).
2. Убедился, что `data_check_string` формируется правильно, учитывая ключ и единственное значение.
3. Убедился, что `init_data` передается как строка в функцию `validate_hash`.

Попробуйте протестировать этот измененный код с данными, полученными из вашего Telegram Web App. Если возникнут дальнейшие проблемы, убедитесь, что все переданные данные соответствуют ожидаемому формату.
Похожие вопросы