Валидация initData в веб-приложении Телеграма (Telegram Mini App) на Qt

Телеграм позволяет открыть https-ресурс из приложения, предоставляя механизм для валидации пользователя на стороне веб-сервера. Судя по документации, в валидации ничего сложного нет. Однако при реализации возникло непонимание: мой HMAC-SHA256 хеш всегда отличается. Имею такой код:

    const static QByteArray secret = QMessageAuthenticationCode::hash("Мой_токен",
                                                                      "WebAppData", QCryptographicHash::Sha256).toHex();

    const auto initData = reqData.body->value("data").toObject().value("initData");
    QUrlQuery query(initData.toString());
    QString hash = query.queryItemValue("hash");

    const QString originalInitDataString = initData.toString();
    qInfo().noquote() << "Original initData:";
    qInfo().noquote() << originalInitDataString;
    qInfo().noquote() << "";

    QStringList initStringList = originalInitDataString.split('&');
    initStringList.removeIf([](const QString& str)->bool { return str.startsWith("hash="); });
    initStringList.sort();

    const QString initString = QByteArray::fromPercentEncoding( initStringList.join('\n').toUtf8() );
    qInfo().noquote() << "Init string:\n";
    qInfo().noquote() << initString;
    qInfo().noquote() << "\ninitStringList size:" << initStringList.size();

    const QString myHash1 = QMessageAuthenticationCode::hash(initString.toUtf8(), secret, QCryptographicHash::Sha256).toHex();
    qInfo().noquote() << "\nMy hash:" << myHash1;
    qInfo().noquote() << "Tg hash:" << hash;

И примерно такой вывод в консоль:

Original initData:
query_id=AAFMntEHAwAAAEye0QdtEbRW&user=%7B%22id%22%3A6573629%2C%22first_name%22%3A%22%D0%A0%D0%BE%D0%BC%D0%B0%D0%BD%22%2C%22last_name%22%3A%22%22%2C%22username%22%3A%22user111%22%2C%22language_code%22%3A%22ru%22%2C%22is_premium%22%3Atrue%2C%22allows_write_to_pm%22%3Atrue%7D&auth_date=1717189626&hash=c90ab846247bcaa3339911ac39272823eead4218a6e8ca7bb358ce85d6038275

Init string:

auth_date=1717189626
query_id=AAFMntEHAwAAAEye0QdtEbRW
user={"id":6573629,"first_name":"Роман","last_name":"","username":"user111","language_code":"ru","is_premium":true,"allows_write_to_pm":true}

initStringList size: 3

My hash: 0898cff38a65ff1c253145b068b7cda562e5392e1f02abcab50c81680103e9c9
Tg hash: c90ab846247bcaa3339911ac39272823eead4218a6e8ca7bb358ce85d6038275

Грешил на декодирование текста из url-encoded. Перепробовал все варианты, которые предоставляет Qt (fully decoded, encode urf-8 и прочее).

Есть ли у кого-то опыт или интуитивные соображения о том, что в этом коде делается неверно?


Ответы (1 шт):

Автор решения: mynameiskostya

Ошибка была в формировании secret:

const static QByteArray secret = QMessageAuthenticationCode::hash("Мой_токен", "WebAppData", QCryptographicHash::Sha256);

Ключ нужен в бинарном формате, НЕ в хексе.

→ Ссылка