Справочник / Доказательства
Независимый свидетель
Запустите Witness с собственным ключом и ботом, публикуйте подписанные контрольные точки в канале и сверяйте экспортированные данные с ними.
Настройка бота и прокси на русском языке.
Сборщик подписывает свой собственный журнал, поэтому тот, кто контролирует сборщик и его ключ, в принципе может переписать или сократить журнал и подписать его заново. Свидетель делает это обнаружимым. Это отдельный процесс — ещё один контейнер, или, лучше сказать, сервер, который управляет кто-то другой, — который каждые несколько минут извлекает начальную часть подписанного журнала сборщика, подписывает то, что он зафиксировал, своим собственным ключом, сохраняет это в своём собственном журнале и публикует в канале Telegram.
Схема в текстовом формате
- Collector → Witness (подписанный контрольный пункт: количество записей + хеш заголовка)
- Witness → Журнал Witness, собственный ключ
- Witness → Канал в Telegram (подписанное сообщение, отправленное через собственного бота)
- Архив доказательств в формате ZIP → verify.py
- Журнал Witness, собственный ключ → verify.py
- Канал в Telegram → verify.py (Экспорт из Telegram Desktop или страница «t.me/s»)
Что предоставляет TgWitness, а чего не предоставляет#
| У TgWitness есть | Свидетель никогда не имеет |
|---|---|
| Токен-свидетель только для чтения для одного рабочего пространства | Сессия Telegram сборщика данных или учетные данные для доступа к API |
| Собственный ключ Ed25519 и журнал | Хранилище сборщика, ключ подписи или токен панели |
| Собственный токен бота в Telegram | Содержание сообщения: в заголовке указано количество записей и хеш |
Токен создаётся на странице «Witness» панели управления, отображается однократно и хранится исключительно в виде
хеша SHA-256. Он открывает ровно одну конечную точку — GET /api/witness/head, которая возвращает свежеподписанную
контрольную точку, а также подписанные счетчики сбора данных без содержания и информацию о работоспособности системы.
Он не может открывать панель, считывать содержание сообщений или изменять настройки, и
токен панели там не принимается. Отзыв токена осуществляется на той же странице. Коллектор фиксирует
момент начала проверки нового ключа-свидетеля (witness.seen) и отображает последнюю проверку для каждого токена;
свидетель, который не прошел проверку в течение 2,5 интервалов, помечается как просроченный.
Новые свидетели отправляют случайный контрольный запрос при каждом опросе; оператор фиксации повторяет его под подписью сборщика. Счётчики привязаны к конкретной контрольной точке и включаются в подписанные сообщения свидетелей. Старые заголовки по-прежнему принимаются автономным свидетелем. Сам по себе рост объёма журнала никогда не учитывается как новое сообщение.
Что проверяется и фиксируется#
Каждый интервал (по умолчанию — 10 минут) TgWitness:
- самостоятельно извлекает заголовок (коллектор не может его добавлять или пропускать);
- проверяет подпись сборщика, закреплённый ключ сборщика (
--collector-fingerprint, или первый обнаруженный ключ), неубывающий счётчик и неизменную головку при неизменном значении счётчика; - добавляет подписанную запись в свой собственный журнал:
witness.anchorсо статусомok,key_changed,rollback(меньше записей, чем ранее),fork(та же длина, другой заголовок) илиinvalid(ответ не прошел проверку), либоwitness.no_response, если коллектор не ответил; - Результат публикуется в канале с подписью, включая ответ «no answer», пока TgWitness
работает и имеет доступ к Bot API. Идентификатор публикации фиксируется (
witness.posted), также фиксируется неудачная публикация (witness.post_failed).
Запись выглядит следующим образом; в последней строке приводится подписанное заявление:
TgWitness witness #42 · journal head
Collector 3fa9c2d1e0b4a7f6: 18234 records
Head 9b1f…c07e
2026-10-28T19:40:00.123+00:00
TGW1.eyJhdCI6…<statement>.<signature>
Запустить Witness#
Вам потребуется бот Telegram (создайте его с помощью @BotFather), канал, в котором этот бот является администратором, а также адрес сборщика, доступный для свидетеля — через HTTPS за пределами частной сети (см. раздел «HTTPS» в разделе «Развертывание»).
Откройте «Дополнительные настройки» → «Бот в вашем канале» → «Настроить бота»
на панели. Три шага охватывают
доступ только для чтения, ваш канал и интервал, а затем запуск Witness. Политика
публикации, опциональный прокси HTTP/SOCKS5 и настраиваемый адрес Bot API находятся в разделе «Расширенные настройки
». Форма
загружает файл witness.json
с закреплённым ключом сборщика данной рабочей области. Загрузите вновь
созданный токен «только для чтения», сохранив файл доступа
как witness-token.txt
; поместите его и файл bot-token.txt
, созданный на хосте Witness, рядом с этим JSON-файлом. Сборщик никогда не получает токен бота.
Загрузка не приводит к запуску службы или публикации сообщения. Ни один свидетель хостируемого проекта не
регистрируется неявно.
python -m tgwitness.witness run --config witness.json --check-config
python -m tgwitness.witness run --config witness.json
python -m tgwitness.witness fingerprint --config witness.json
Первая команда проверяет файлы конфигурации и секретные файлы без сетевых запросов и создания ключей. Пути в JSON являются относительными по отношению к данному файлу; пути CLI/окружения являются относительными по отношению к рабочему каталогу. Сохраняйте отпечаток свидетеля за пределами его хоста. Индикатор последнего опроса коллектора подтверждает лишь наличие запроса; о публикации сообщается через Proof или проверяется в журнале свидетеля и на канале.
Если панель находится за SSH-туннелем, открывайте доступ только к конечной точке Witness с ограниченным доступом на
отдельном HTTPS-хосте, как показано в этом примере использования Caddy.
Рабочая область по умолчанию использует https://witness.example.org, остальные рабочие области —
https://witness.example.org/profiles/ID. Токены по-прежнему требуются; панель и её
другие маршруты API не перенаправляются этим виртуальным хостом.
Выберите all для регулярно публикуемых контрольных точек. Пятиминутный интервал означает около 288
записей на рабочую область в день. changes/problems намеренно оставляют некоторые проверки неопубликованными.
MTProxy предназначен для клиента Telegram сборщика данных. HTTP-опрос Witness и HTTPS-интерфейс
Bot API Telegram используют собственные маршруты: прямой, HTTP и SOCKS5 (Bot API).
Рядом с коллектором, с использованием Docker (на том же хосте — независимый процесс и ключ, но
тот же оператор): введите значения в поле «.env» и запустите профиль.
TGWITNESS_WITNESS_TOKEN=tgww_...
TGWITNESS_WITNESS_BOT_TOKEN=123456:ABC...
TGWITNESS_WITNESS_CHANNEL=@your_witness_channel
# another workspace: TGWITNESS_WITNESS_COLLECTOR=http://tgwitness:8787/profiles/<workspace ID>
docker compose --profile witness up -d
docker compose logs witness # prints the witness key fingerprint
При использовании опубликованного изображения указывайте код docker compose --project-directory . -f deploy/compose/compose.image.yaml --profile witness up -d.
На чужом сервере (настоящем независимом «свидетеле»): скопируйте туда репозиторий, установите
TGWITNESS_WITNESS_COLLECTOR=https://your-collector.example.org плюс три указанных выше значения
в .env, затем
docker compose --project-directory . -f deploy/compose/compose.witness.yaml up -d
или без использования Docker:
python -m tgwitness.witness run --collector https://your-collector.example.org \
--token-file witness-token.txt --bot-token-file bot-token.txt --channel @your_witness_channel
Параметры#
| Вариант | Среда | По умолчанию | Значение |
|---|---|---|---|
--interval |
TGWITNESS_WITNESS_INTERVAL |
10 | Интервал между проверками: от 1 до 1440 минут |
--timeout |
_TIMEOUT |
30 | Время ожидания запуска сборщика данных и API-интерфейса бота: от нескольких секунд до 5–600 |
--post |
_POST |
all |
all: все в порядке; changes: новая проблема; problems: одни проблемы и отсутствующие ответы |
--title |
_TITLE |
TgWitness witness |
Первые слова каждого сообщения в канале |
--collector-fingerprint |
_COLLECTOR_FINGERPRINT |
– | Зафиксируйте ключ сборщика, а не полагайтесь на первый ответ |
--proxy |
_PROXY |
прямой | socks5://host:port или http://host:port |
--bot-api |
_BOT_API |
https://api.telegram.org |
Адрес API бота, например, локальный сервер API бота |
--data-dir |
_DATA |
witness-data |
Ключ Witness и журнал |
--config |
_CONFIG |
– | Файл JSON с любым из перечисленных выше вариантов |
Адрес сборщика, токены и канал берутся из --collector, --token или
--token-file, --bot-token или --bot-token-file и --channel, либо _COLLECTOR, _TOKEN,
_TOKEN_FILE, _BOT_TOKEN, _BOT_TOKEN_FILE и _CHANNEL, что позволяет сохранить конфиденциальность данных вне
списка процессов.
В файле конфигурации используются названия параметров с подчеркиваниями, а также texts, который заменяет слова
в сообщениях канала:
{"collector": "https://your-collector.example.org", "token_file": "witness-token.txt",
"bot_token_file": "bot-token.txt", "channel": "@your_witness_channel",
"interval": 5, "timeout": 30, "post": "changes", "title": "Partner witness",
"texts": {"ok": "journal head", "no_response": "no answer from the collector", "records": "records"}}
Ключи texts: ok, key_changed, rollback, fork, invalid, no_response, collector,
records, head. Командная строка имеет приоритет над средой, а среда — над файлом.
Неизвестные опции или текстовые ключи приводят к остановке работы Witness с выводом сообщения, а не игнорируются.
Формулировка никогда не влияет на проверку: verify.py проверяет подписанный токен в конце каждого
сообщения. В случае --post changes или problems проверки, которые не были опубликованы, по-прежнему находятся в
журнале свидетелей, а verify.py указывает их как никогда не опубликованные; в начальной записи указывается
политика. Каждая проверка по-прежнему отображается в журнале, поэтому меньшее количество публикаций означает меньшее количество независимых
моментов отправки сообщений в Telegram, а не меньшее количество проверок.
Даже без канала «Witness» продолжает вести свой журнал. Храните отпечаток ключа «Witness»
(python -m tgwitness.witness fingerprint) в другом месте.
Проверить#
Со стороны свидетеля экспортируйте его журнал:
python -m tgwitness.witness export --out witness.zip
# Docker (add -f deploy/compose/compose.witness.yaml on a witness server):
docker compose exec witness python -m tgwitness.witness export --out /witness/witness.zip
docker compose cp witness:/witness/witness.zip .
Затем в любом месте, используя подписанный ZIP-файл сбора данных и канал, экспортированный из Telegram
Desktop (Экспорт истории чата
→ JSON даёт result.json
) или его общедоступную страницу https://t.me/s/…
:
python verify.py tgwitness-evidence.zip --fingerprint COLLECTOR_SHA256 \
--witness witness.zip --witness-fingerprint WITNESS_SHA256 --channel result.json
verify.py проверяет журнал «Witness» (цепочку и подписи), а затем удостоверяется, что каждый заголовок, который
увидел «Witness», входит в экспортированный журнал: запись с данным номером должна иметь именно
этот хеш. Заголовок, не совпадающий с хэшем, не проходит проверку — журнал был изменен после того, как
«Witness» его увидел. Он также сообщает о заголовках, увиденных после экспорта, аномалиях, которые
зафиксировал свидетель, ответах, не прошедших проверку, периодах, соответствующие контрольные точки которых присутствуют в данном
экспорте («Заверен с X по Y»), а также о пробелах. Более поздние контрольные точки не продлевают эти периоды.
Результат включает номер последней совпавшей записи и количество последующих записей,
не имеющих соответствующей контрольной точки. Учитываются только ответы, подписанные собственным ключом экспорта: экспорт, подписанный
ключом, который свидетель никогда не видел, указывается как не подтверждённый, и без --fingerprint его
подписант остаётся не закреплённым. При использовании --channel каждая подписанная запись должна совпадать с журналом свидетеля
запись за записью: измененные записи не проходят проверку, отсутствующие записи указываются в списке. Дата в
предоставленном экспорте Telegram в формате JSON является редактируемыми метаданными, не входящими в состав подписанного токена свидетеля.
Совпадение токена не подтверждает подлинность даты публикации; в результате явно
указывается, что проверка времени публикации не проводилась.
Требуется граница экспорта с подтверждением#
Для передачи, которая должна включать заверенную окончательную запись, добавьте --require-witness:
python verify.py tgwitness-evidence.zip --fingerprint COLLECTOR_SHA256 \
--witness witness.zip --witness-fingerprint WITNESS_SHA256 --require-witness
Для этого требуется независимо сохраненный отпечаток свидетеля и соответствующая контрольная точка,
расположенная точно в конце данного экспорта. Контрольная точка, охватывающая только более ранний префикс,
является недостаточной. Приостановите сбор данных, позвольте свидетелю наблюдать за конечным состоянием и выполните экспорт
до дальнейших записей в журнал; если журнал изменится, сохраните ещё одну контрольную точку и
осуществите экспорт этого состояния. Один только более поздний контрольный точка не может подтвердить окончательный хеш более короткого экспорта.
Если также указан флаг --channel, отсутствие заявленных сообщений или пустой набор совпадений приводят к сбою этой
строгой проверки. Без этого флага обычные проверки целостности по-прежнему сообщают о записях, не подтверждённых свидетелем,
не отклоняя при этом архив, который в остальном является целостным.
Данный флаг обеспечивает согласованность с предоставленными и закреплёнными записями свидетеля. Оператор по-прежнему обязан подтвердить независимость свидетеля и хранить его записи отдельно. Данный флаг не подтверждает достоверность сообщений, полноту сбора данных или время работы, измеренное независимым образом.
Свидетель показывает, что именно фиксировал сборщик данных в указанные моменты времени, и что последующие экспортированные данные с этим совпадают. Он не подтверждает, что сборщик зафиксировал всё, что было доставлено Telegram, или что содержание сообщений соответствует действительности. Свидетель, запущенный тем же оператором на том же компьютере, имеет меньшую достоверность, чем тот, который запущен кем-либо другим.
Само по себе увеличение количества записей не может подтвердить непрерывность онлайн-архива, доступного только для добавления: при офлайн- сравнении каждый сохраненный префикс хэша должен совпадать с полным экспортом из коллектора. Время простоя «Witness» и сбои в публикации приводят к появлению интервалов без внешних ориентиров. О пропущенных сообщениях можно сообщать на основании сохраненного журнала «Witness»; ни канал, ни сервер, контролируемые одним и тем же оператором, не являются неизменяемым сторонним архивом.