Если вы читаете эту статью, значит, слову «честно» вы не верите по умолчанию, и это здравая позиция. Здесь нет рассказа о том, как «всё устроено красиво». Вместо этого мы поставим себя на место проверяющего: определим, какие виды обмана вообще возможны в игре на случай, какой шаг аудита каждый из них выдаёт, и пройдём весь путь от сбора данных до собственного кода. Напомним сразу: апгрейд на DOTAGRADE — азартная механика, доступная только с 18 лет, выигрыш не гарантирован, а сам Provably Fair шансов не повышает. Сайт не связан с Valve и Steam.
Что значит «поймать нечестность»
Проверка честности — это не поиск доказательства удачи. Мы ищем противоречия: место, где опубликованные данные, формула и записанный исход перестают сходиться. Если после аудита противоречий нет, подмена результата на стороне сайта исключена для этой конкретной игры. Если есть — у вас на руках готовый материал для обращения в поддержку.
Для аудита нужны три вещи: данные игры, формула и сравнение с исходом. Формула общая для всех и полностью известна:
- публичный хеш:
HMAC-SHA256, где ключ — секретная соль, а сообщение — серверный сид; - ролл:
HMAC-SHA512, где ключ — клиентский сид, дефис и нонс, а сообщение — серверный сид; из полученной hex-строки берутся первые 15 символов, число делится с остатком на maxRoll, к остатку прибавляется единица; - победа: ролл лежит внутри окна выигрыша.
Значение maxRoll мы здесь не называем намеренно: берите его со страницы проверки, на правом краю шкалы диапазона.
Четыре способа обмана и чем каждый ловится
Модель угроз проста: у сайта есть мотив и техническая возможность изменить что-то после вашей ставки. Перечислим, что именно и где это всплывёт.
| Гипотетическая подмена | Что делает нечестный оператор | Какой шаг аудита её выдаёт |
|---|---|---|
| Подмена серверного сида | После ставки подставляет другой сид, чтобы получить нужный ролл | Хеш раскрытой пары не совпадёт с публичным хешем, который вы видели заранее |
| Подгонка ролла | Записывает в историю число, не равное формуле | Ваш пересчёт даст другое число, чем поле roll |
| Неверное окно | Двигает границы from…to или сужает их относительно заявленного шанса | Ширина окна не сойдётся с произведением шанса на maxRoll, а ролл окажется не там, где указан исход |
| Пропуск или перекрутка nonce | Выбрасывает «неудобные» номера или повторяет их | Нонсы внутри пары идут подряд; дыра или повтор видны в серии проверенных игр |
Обратите внимание на логику первой строки. Публичный хеш виден до игры, а серверный сид — после смены пары. Нечестному оператору пришлось бы подобрать другой сид с тем же HMAC-SHA256 от той же соли, а это вычислительно нереально. Поэтому именно сравнение хеша — фундамент всей проверки, а остальные шаги страхуют формулу и исход.
Важно. Аудит подтверждает расчёт, а не вашу выгоду. Даже безупречно честный ролл чаще всего будет проигрышным при низком шансе, а долгосрочный ожидаемый результат в такой игре отрицательный. Ставьте только то, что не жалко потерять.
Гигиена клиентского сида
Клиентский сид — ваш вклад в расчёт, и обращаться с ним стоит осознанно.
- Придумайте свою строку. Допустимая длина — от 4 до 64 символов. Сид действует во всех играх, поэтому после сохранения он влияет на каждый следующий апгрейд.
- Не используйте личное. Сид потом появляется в JSON и в истории клиентских сидов, а вы можете захотеть показать данные другому человеку. Не вставляйте туда пароли, имена, почту.
- Не меняйте его перед каждой игрой. Каждая смена закрывает пару и раскрывает прошлый серверный сид. Это полезно для аудита, но слишком частые смены лишают вас серии: проверять придётся россыпь коротких пар.
- Фиксируйте момент смены. Записывайте, какой сид был до и после. История клиентских сидов на странице хранит это, но копия у вас под рукой надёжнее.
- Не считайте «красивый» сид счастливым. Строка влияет на ролл непредсказуемо, и подобрать её под выигрыш нельзя: серверный сид вы до игры не знаете.
Чек-лист аудита по шагам
Ниже порядок действий, который можно выполнять от первого пункта до последнего. Если на каком-то шаге появляется расхождение, остановитесь и сохраните данные.
- До игры. Откройте страницу Provably Fair, вкладку «Настройки сидов», и скопируйте публичный хеш пары. Запишите текущий клиентский сид и убедитесь, что он ваш.
- Сыграйте один или несколько апгрейдов. Запишите ID каждой игры: он есть в профиле, а кнопка «Проверить» доступна у каждого апгрейда в профиле.
- Смените клиентский сид. Раскрыть серверный сид можно только после первого апгрейда на этой паре, и только после смены.
- Раскройте сид кнопкой «Раскрыть серверный сид» или найдите его в истории серверных сидов.
- Сверьте хеш. Вычислите HMAC-SHA256 от раскрытого сида с раскрытой солью и сравните с хешем из пункта 1.
- Для каждой игры откройте вкладку «Проверка апгрейда», введите ID и заберите JSON.
- Пересчитайте ролл собственным кодом и сравните с полем roll.
- Проверьте окно: ширину, положение и попадание ролла.
- Проверьте нонсы: внутри пары они должны идти без дыр.
- Сопоставьте исход («Выигрыш» или «Проигрыш») с результатом пункта 8.
Весь процесс занимает несколько минут, если автоматизировать пункты 5–8 функцией из разделов ниже.
Какие данные забрать: Copy JSON и поля
На вкладке «Проверка апгрейда» введите ID и дождитесь данных. Сразу после игры расчёт может занять несколько секунд, и страница об этом сообщит. Далее нажмите «Скопировать JSON» (в англоязычном виде — Copy JSON). В буфер попадает объект с шестью полями:
| Поле | Что это | Для чего нужно в аудите |
|---|---|---|
server_seed | Серверный сид | Сообщение в обеих формулах HMAC |
secret_salt | Секретная соль | Ключ для проверки публичного хеша |
public_hash | Публичный хеш | Эталон, с которым сравнивается ваш расчёт |
client_seed | Ваш сид | Часть ключа для ролла |
nonce | Номер апгрейда в паре | Вторая часть ключа для ролла |
roll | Выпавшее число | То, что вы воспроизводите |
Границы окна from…to в JSON не входят: их читайте на странице проверки рядом со шкалой. Туда же смотрите за maxRoll. Если серверный сид ещё не раскрыт, нужных полей не будет, и сначала придётся сменить пару.
Проверка в браузере через Web Crypto
Страница сама пересчитывает результат через Web Crypto, но вы можете сделать то же самое независимо: вставьте код в консоль разработчика вкладки с другим сайтом или в локальный файл. Работает на crypto.subtle, которому нужно безопасное соединение (HTTPS или localhost). Число из 15 hex-символов занимает 60 бит, поэтому обычный Number не годится: он теряет точность после 53 бит, и нужен BigInt.
const enc = new TextEncoder();
async function hmacHex(hash, key, message) {
const k = await crypto.subtle.importKey(
"raw", enc.encode(key), { name: "HMAC", hash }, false, ["sign"]
);
const sig = await crypto.subtle.sign("HMAC", k, enc.encode(message));
return [...new Uint8Array(sig)]
.map(b => b.toString(16).padStart(2, "0"))
.join("");
}
async function audit(data, maxRoll, win) {
const hashOk =
(await hmacHex("SHA-256", data.secret_salt, data.server_seed)) === data.public_hash;
const h = await hmacHex("SHA-512", `${data.client_seed}-${data.nonce}`, data.server_seed);
const roll = Number(BigInt("0x" + h.slice(0, 15)) % BigInt(maxRoll)) + 1;
const inWindow = win.from <= win.to
? roll >= win.from && roll <= win.to
: roll >= win.from || roll <= win.to;
return { hashOk, roll, rollMatches: String(roll) === String(data.roll), inWindow };
}
// Пример вызова (числа условные, подставьте свои):
// audit(JSON.parse(text), 100, { from: 41, to: 65 }).then(console.log);
Обратите внимание на порядок параметров hmacHex: сначала ключ, потом сообщение. В обоих вызовах сообщением служит серверный сид. Перепутать аргументы — самая частая причина ложного «несовпадения».
Те же вычисления на Python и PHP
Если не доверяете браузеру или хотите прогнать десятки игр подряд, подойдёт любой язык с HMAC. Ниже функции, которые возвращают сразу несколько результатов, а не один print.
import hmac, hashlib
def verify(data, max_roll, window):
"""window = (from_, to) со страницы проверки; max_roll берётся оттуда же."""
msg = data["server_seed"].encode()
calc = hmac.new(data["secret_salt"].encode(), msg, hashlib.sha256).hexdigest()
key = f'{data["client_seed"]}-{data["nonce"]}'.encode()
h = hmac.new(key, msg, hashlib.sha512).hexdigest()
roll = int(h[:15], 16) % max_roll + 1
lo, hi = window
inside = (lo <= roll <= hi) if lo <= hi else (roll >= lo or roll <= hi)
return {
"hash_ok": calc == data["public_hash"],
"roll": roll,
"roll_ok": str(roll) == str(data["roll"]),
"in_window": inside,
}
<?php
function verify(array $d, int $maxRoll, int $from, int $to): array {
$hashOk = hash_equals($d['public_hash'],
hash_hmac('sha256', $d['server_seed'], $d['secret_salt']));
$h = hash_hmac('sha512', $d['server_seed'], $d['client_seed'] . '-' . $d['nonce']);
$roll = (hexdec(substr($h, 0, 15)) % $maxRoll) + 1;
$in = $from <= $to ? ($roll >= $from && $roll <= $to)
: ($roll >= $from || $roll <= $to);
return ['hash_ok' => $hashOk, 'roll' => $roll,
'roll_ok' => (string)$roll === (string)$d['roll'], 'in_window' => $in];
}
В PHP порядок аргументов у hash_hmac иной, чем у Python: сначала алгоритм, затем сообщение, затем ключ. Для hexdec с 15 hex-символами нужна 64-разрядная сборка PHP. Интерфейс сайта ссылается на онлайн-интерпретатор PHP, и этот код можно запустить там.
Три значения true и совпавшее число в поле roll означают, что расчёт чист. Значение in_window само по себе ни хорошее, ни плохое: оно просто должно соответствовать исходу, который записан за игрой.
Окно выигрыша на условной шкале 1…100
Окно — самая необычная часть алгоритма, поэтому разберём его на учебных числах. Условный пример: maxRoll равен 100, шанс 25%. Ширина окна — round(0,25 × 100), то есть 25 позиций.
Обычное окно. Пусть оно идёт от 41 до 65. В диапазон входят позиции 41, 42, …, 65 — ровно 25 штук. Ролл 52 внутри, значит, апгрейд выигран. Ролл 70 снаружи, это проигрыш. Граничные значения проверьте отдельно: 41 и 65 внутри, 40 и 66 снаружи.
Окно через край. Теперь пусть from равен 90, а to равен 14. Раз from больше to, окно состоит из двух частей: 90…100 (11 позиций) и 1…14 (14 позиций). Сумма снова 25. Ролл 3 — выигрыш, ролл 95 — выигрыш, ролл 50 — проигрыш. Границы: 90 внутри, 89 снаружи, 14 внутри, 15 снаружи.
Типичная ошибка при самостоятельной проверке — применить условие from <= roll <= to без разбора случая from > to. Тогда любая игра с окном через край покажет «несоответствие» там, где его нет. В коде выше этот случай обработан отдельной веткой.
Ещё одна проверка, дешёвая и полезная: посчитайте ширину окна и сравните с шансом, показанным перед игрой. Если на шкале 1…100 вы видели 25%, а окно занимает 40 позиций, вопрос уместен. Помните, что при сдвиге окна кнопкой «Подвинуть окно выигрыша» меняется его положение, но не ширина.
Что показывает страница проверки: статусы и ошибки
Статусы страницы проверки удобно читать как диагноз.
- «Пересчёт совпал с ответом сервера». Встроенный расчёт в вашем браузере дал то же число, что у сервера. Это сильный сигнал, но полный аудит всё равно включает хеш и окно.
- «Пересчёт не совпал с ответом сервера». Не торопитесь с выводами: сначала убедитесь, что вы смотрите на правильный ID, а ваши скопированные данные целые. Если ваш независимый код тоже даёт другое число, чем поле roll, сохраните JSON и пишите в поддержку.
- «Серверный сид ещё не раскрыт». Сверить ролл нельзя, пока пара не сменена. До этого проверяется только опубликованный хеш, то есть вы лишь убеждаетесь, что он зафиксирован.
- «Раскрыть серверный сид» не работает. Так бывает, если на паре ещё не сыграно ни одного апгрейда: кнопка требует хотя бы одной игры. Также возможен сбой загрузки, тогда помогает «Повторить».
- «Пересчёт недоступен: браузер не даёт доступ к Web Crypto». Это ограничение соединения, а не обвинение сайту. Откройте страницу по HTTPS или используйте код из разделов выше.
- «Апгрейд не найден». Проверьте ID: лишний пробел или чужой номер дают именно такой ответ.
- «Апгрейд ещё рассчитывается». Подождите несколько секунд и повторите.
- Отменённые и компенсированные ставки. Сервер не возвращает для них нонс и ролл, поэтому сверять нечего: проверен только опубликованный хеш. Это штатная ситуация, а не признак подлога.
В выводе сервера вы также увидите строки «данные корректны» или «данные не сходятся». Вторая означает внутреннюю несогласованность данных, и это повод сохранить JSON и скриншот, а не повод паниковать.
Чего Provably Fair не доказывает
Скептик вправе знать пределы метода, и они довольно широкие.
- Цены. Система не оценивает, справедливо ли оценены предметы в ставке и в цели. Цены сверяйте самостоятельно, учитывая, что они могут отличаться от Steam Market.
- Сам шанс как параметр. Проверка подтверждает, что ролл вычислен честно и сопоставлен с окном. Является ли заявленный шанс выгодным для вас — вопрос не к криптографии. Подробнее о том, как шанс связан со стоимостью, написано в статье как работает апгрейд.
- «Повезло» или «не повезло». Честный ролл не обязан радовать. Ни одна серия проверок не делает проигрыш менее вероятным.
- Выдачу предметов. Отдельная история — вывод в Steam, где свои условия; о них читайте в материале про вывод скинов.
- Вашу дисциплину. Система не ограничивает ставки за вас.
Ответы на частые вопросы по механике собраны в FAQ по апгрейду. Сама страница проверки открывается по адресу /ru/provably-fair после входа через Steam, а начать можно с главной.
Итог для тех, кто читает по диагонали
- Подмена серверного сида ловится сравнением хеша, подгонка ролла — пересчётом, неверное окно — шириной и положением границ, пропуск нонса — просмотром серии.
- Для аудита нужны JSON (шесть полей), maxRoll и границы окна со страницы проверки.
- Окно с
from > toсостоит из двух частей, и в коде для него нужна отдельная ветка. - Provably Fair не оценивает цены и не меняет шанс; игра остаётся азартной, 18+.
Частые вопросы
Достаточно ли одной проверки, чтобы считать сайт честным?
Нет. Одна проверка подтверждает одну игру. Чтобы картина была убедительной, разумно проверить серию апгрейдов в закрытой паре сидов: хеш, ролл, окно и порядок нонсов. Даже серия лишь показывает отсутствие подмены в проверенных играх и ничего не говорит о будущих результатах или о вашей удаче.
Почему мой код выдаёт другой ролл, хотя данные я скопировал верно?
Чаще всего причина в мелочах. Проверьте, что ключ — это клиентский сид, дефис и нонс без пробелов, а сообщение — серверный сид; что взяты первые 15 hex-символов; что в JavaScript используется BigInt; что значение maxRoll взято с вашей страницы проверки. В PHP отдельно следите за порядком аргументов hash_hmac. Если после этого число всё равно отличается от поля roll, сохраните JSON и обратитесь в поддержку.
Что делать, если ставка отменена или компенсирована и ролла нет?
Для таких ставок сервер не возвращает нонс и ролл, поэтому пересчитывать нечего. Страница сообщает, что проверен только опубликованный хеш. Это нормальное поведение, а не ошибка: вы можете убедиться лишь в том, что хеш был зафиксирован заранее.
Повышает ли Provably Fair мои шансы на выигрыш?
Нет. Система только позволяет проверить, что результат вычислен по зафиксированным данным и не подменён. Шанс определяется соотношением стоимости ваших предметов и цели, а выигрыш никогда не гарантирован. Игра предназначена для совершеннолетних, и ставить стоит лишь то, что вы готовы потерять.





