# شاهد مستقل

Canonical page: https://phishdestroy.github.io/TgWitness/fa/docs/reference/witness/

یک ویژنس را با کلید و بات اختصاصی خود اجرا کنید، نقاط کنترل امضا شده را در یک کانال منتشر کنید و خروجی‌ها را با آن مطابقت دهید.

[راهنمای تنظیم ربات و پروکسی به زبان روسی](https://github.com/phishdestroy/TgWitness/blob/main/docs/ru/WITNESS.md).

یک گردآورنده دفترچه خود را امضا می‌کند، بنابراین هر کسی که کنترل گردآورنده و کلید آن را در دست داشته باشد، از نظر تئوری می‌تواند دفترچه را بازنویسی یا کوتاه کند و دوباره آن را امضا نماید. یک شاهد این کار را قابل تشخیص می‌کند. این یک فرآیند جداگانه است — یک کانتینر دیگر، یا بهتر بگوییم یک سرور که شخص دیگری آن را اجرا می‌کند — که هر چند دقیقه یک‌بار سرآیند دفترچه ثبت امضا شدهٔ گردآورنده را دریافت می‌کند، آنچه را که دیده با کلید خود امضا می‌کند، آن را در دفترچه ثبت خود نگه می‌دارد و آن را در یک کانال تلگرام منتشر می‌کند.

نمودار جریان · جمع‌آور → شاهد (نقطهٔ کنترل امضا شده: تعداد رکوردها + هش سرآیند); شاهد → دفترچه شواهد، کلید شخصی; شاهد → کانال تلگرام (ارسال امضا شده از طریق ربات اختصاصی خود); فایل فشرده شواهد → verify.py; دفترچه شواهد، کلید شخصی → verify.py; کانال تلگرام → verify.py (صادرات تلگرام دسکتاپ یا صفحهٔ t.me/s) · جمع‌آور · شاهد · دفترچه شواهد، کلید شخصی · کانال تلگرام · فایل فشرده شواهد · verify.py · نقطهٔ کنترل امضا شده: تعداد · رکوردها + هش سرآیند · ارسال امضا شده از طریق ربات · اختصاصی خود · صادرات تلگرام دسکتاپ یا · صفحهٔ t.me/s

**نمودار به صورت متن**

1. جمع‌آور → شاهد (نقطهٔ کنترل امضا شده: تعداد رکوردها + هش سرآیند)
2. شاهد → دفترچه شواهد، کلید شخصی
3. شاهد → کانال تلگرام (ارسال امضا شده از طریق ربات اختصاصی خود)
4. فایل فشرده شواهد → verify.py
5. دفترچه شواهد، کلید شخصی → verify.py
6. کانال تلگرام → verify.py (صادرات تلگرام دسکتاپ یا صفحهٔ t.me/s)

## آنچه ویجت دریافت می‌کند و آنچه دریافت نمی‌کند

| شاهد دارد | شاهد هرگز نداشته است |
| --- | --- |
| **توکن شاهد** فقط-خواندنی برای یک فضای کاری | اطلاعات جلسه تلگرام یا اعتبارنامه‌های API گردآورنده |
| کلید Ed25519 اختصاصی و دفترچهٔ خود | گنجینهٔ گردآورنده، کلید امضا یا توکن پنل |
| توکن ربات تلگرام خود | محتوای پیام: سرآیند شامل تعداد رکوردها و یک هش است |

توکن در صفحه **Witness** پنل ایجاد می‌شود، تنها یک‌بار نمایش داده می‌شود و فقط به صورت SHA-256 ذخیره می‌گردد. این توکن دقیقاً یک نقطه پایانی (endpoint) را باز می‌کند: `GET /api/witness/head`، که یک نقطه کنترل تازه امضا شده به همراه شمارنده‌های جمع‌آوری بدون محتوا که امضا شده‌اند و وضعیت عملیاتی را بازمی‌گرداند. این توکن نمی‌تواند پنل را باز کند، محتوای پیام را بخواند یا تنظیمات را تغییر دهد، و توکن پنل در آنجا پذیرفته نمی‌شود. توکن را در همان صفحه لغو کنید. کالکتور ثبت می‌کند که یک کلید شاهد جدید (`witness.seen`) چه زمانی شروع به بررسی می‌کند و آخرین بررسی را برای هر توکن نشان می‌دهد؛ شهادی که در عرض ۲.۵ بازه زمانی بررسی نکرده باشد، به عنوان «دیر شده» (overdue) علامت‌گذاری می‌شود.

شاهدان جدید در هر نظرسنجی یک چالش تصادفی ارسال می‌کنند؛ عبارت ضبط، آن را زیر امضای گردآورنده منعکس می‌کند. شمارنده‌ها به نقطه کنترل دقیق متصل هستند و در پست‌های امضا شده شاهد گنجانده می‌شوند. هدرهای قدیمی همچنان توسط شاهد مستقل پذیرفته می‌شوند. رشد مجله به تنهایی هرگز به عنوان یک پیام جدید شمرده نمی‌شود.

## آنچه بررسی و ثبت می‌کند

در هر بازه زمانی (به طور پیش‌فرض ۱۰ دقیقه) شاهد:

1. خودِ سر را بازیابی می‌کند (جمع‌کننده نمی‌تواند آن را جابجا کند یا از آن بگذرد)؛
2. امضای گردآورنده، کلید ثابت‌شده گردآورنده (`--collector-fingerprint`، یا اولین کلید مشاهده‌شده)، یک شمارش نزولی‌نبوده و یک هِد ثابت‌شده در شمارش ثابت را تأیید می‌کند؛
3. یک رکورد امضا شده را به ژورنال خود ضمیمه می‌کند: `witness.anchor` با وضعیت `ok`، `key_changed`، `rollback` (رکوردهای کمتر از قبل)، `fork` (طول یکسان، هدر متفاوت) یا `invalid` (پاسخ در اعتبارسنجی شکست خورد)، یا `witness.no_response` وقتی گردآورنده پاسخ نداد؛
4. نتیجه را در حالی که شاهد در حال اجرا است و می‌تواند به 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>
```

## اجرای یک شاهد

شما به یک ربات تلگرام (با استفاده از @BotFather یکی بسازید)، یک کانال که آن ربات در آن مدیر است، و آدرس کلکسیونر که از طریق شاهد قابل دسترسی باشد — از طریق HTTPS خارج از شبکه خصوصی (به پروفایل HTTPS در [بخش استقرار](https://phishdestroy.github.io/TgWitness/fa/docs/reference/deployment/) مراجعه کنید) نیاز دارید.

**«افزونه» را** باز کنید **→ «یک ربات در کانال شما» → «یک ربات را** در پنل **راه‌اندازی کنید** ». سه مرحله دسترسی فقط-خواندنی، کانال شما و فاصله زمانی را پوشش می‌دهد، سپس شاهد را راه‌اندازی می‌کند. سیاست انتشار، پروکسی اختیاری HTTP/SOCKS5 و آدرس Bot API سفارشی در زیر **«تنظیمات پیشرفته»** قرار دارند. این فرم، `witness.json` را با کلید گردآورنده این فضای کاری که سنجاق شده دانلود می‌کند. توکن فقط-خواندنی تازه‌ساخت را با **«ذخیره فایل دسترسی** به عنوان `witness-token.txt` » دانلود کنید؛ آن را و یک `bot-token.txt` که روی میزبان شاهد ایجاد شده را در کنار آن 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 قرار دارد، فقط endpoint محدودشده witness را با [این مثال Caddy](https://github.com/phishdestroy/TgWitness/blob/main/deploy/Caddyfile.witness.example) روی یک نام میزبان HTTPS جداگانه در دسترس قرار دهید. فضای کاری پیش‌فرض سپس از `https://witness.example.org` استفاده می‌کند، فضاهای کاری دیگر از `https://witness.example.org/profiles/ID` استفاده می‌کنند. توکن‌ها همچنان لازم هستند؛ پنل و مسیرهای API دیگر آن توسط آن میزبان مجازی فوروارد نمی‌شوند.

برای نقاط کنترل منتشرشده به‌طور منظم، `all` را انتخاب کنید. فاصله زمانی پنج دقیقه به معنای حدود ۲۸۸ پست در روز برای هر فضای کاری است. `changes`/`problems` عمداً برخی از بررسی‌ها را منتشر نمی‌کنند. MTProxy برای کلاینت تلگرام گردآورنده است. پینگ HTTP ویटनेس و API بات تلگرام از مسیر مستقیم/HTTP/SOCKS5 خود ([API بات](https://core.telegram.org/bots/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
```

یا بدون داکر:

```
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 | دقایق بین بررسی‌ها، ۱–۱۴۴۰ |
| `--timeout` | `_TIMEOUT` | 30 | ثانیه‌ها برای انتظار تا شروع کار جمع‌آورنده و API ربات: ۵۰۰–۶۰۰ |
| `--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` | کلید شاهد و دفترچه شواهد |
| `--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`. خط فرمان بر محیط و محیط بر فایل ارجحیت دارد. گزینه‌های ناشناخته یا کلیدهای متنی به جای نادیده گرفته شدن، با یک پیام شاهد را متوقف می‌کنند. استفاده از کلمات هرگز بر اعتبارسنجی تأثیر نمی‌گذارد: verify.py در پایان هر پست، توکن امضا شده را بررسی می‌کند. با `--post changes` یا `problems`، چک‌هایی که ارسال نشده‌اند همچنان در دفترچه یادداشت شاهد باقی می‌مانند و `verify.py` آنها را به عنوان هرگز ارسال نشده لیست می‌کند؛ رکورد شروع، سیاست را نام‌گذاری می‌کند. هر چک همچنان در دفترچه یادداشت ظاهر می‌شود، بنابراین تعداد کمتر پست‌ها به معنای زمان‌های مستقل تلگرام کمتر است، نه تعداد کمتر چک‌ها.

بدون کانال، شاهد همچنان دفترچه یادداشت خود را حفظ می‌کند. اثر انگشت کلید شاهد (`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 امضا شده توسط گردآورنده و کانال خروجی‌گرفته شده از تلگرام دسکتاپ (*تاریخچه چت را صادر کنید* → 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` دفترچه یادداشت شاهد (زنجیره و امضاها) را بررسی می‌کند، و سپس بررسی می‌کند که آیا **هر سر که شاهد دیده بخشی از دفترچه یادداشت صادرشده است** یا **خیر**: رکورد در آن شمارش باید دقیقاً همان هش را داشته باشد. سری که مطابقت نداشته باشد، اعتبارسنجی را رد می‌کند — یعنی دفترچه یادداشت پس از آنکه شاهد آن را دید، تغییر کرده است. همچنین سرهایی را که پس از صدور گزارش مشاهده شده‌اند، ناهنجاری‌هایی را که شاهد ثبت کرده است، پاسخ‌های ناموفق، دوره‌هایی را که نقاط کنترل تطابق‌دارشان در این گزارش موجود است («گواهی‌شده از X تا Y») و فواصل را گزارش می‌کند. نقاط کنترل بعدی آن دوره‌ها را گسترش نمی‌دهند. نتیجه شامل شماره آخرین رکورد تطبیق‌یافته و تعداد رکوردهای انتهایی بدون چک‌پوینت تطبیق‌شده است. تنها پاسخ‌هایی که با کلید خودِ اکسپورت امضا شده‌اند، شمارش می‌شوند: اکسپورتی که با کلیدی امضا شده باشد که شاهد هرگز آن را ندیده است، به عنوان «شاهد نشده» گزارش می‌شود و بدون `--fingerprint` امضاکننده آن پین نمی‌شود. با `--channel`، هر پست امضا شده باید رکورد به رکورد با دفترچه یادداشت شاهد مطابقت داشته باشد: پست‌های تغییر یافته در اعتبارسنجی شکست می‌خورند و پست‌های گمشده فهرست می‌شوند. یک تاریخ در خروجی JSON تلگرام ارائه‌شده، یک متادیتای قابل ویرایش است که خارج از توکن شاهد امضا شده قرار دارد. تطابق توکن، تاریخ انتشار را احراز هویت نمی‌کند؛ نتیجه صراحتاً گزارش می‌دهد که اعتبارسنجی زمان انتشار انجام نشده است.

### نیاز به مرز خروجی گواهی‌شده

برای واگذاری که باید شامل یک رکورد نهایی با گواهی شاهد باشد، `--require-witness` را اضافه کنید:

```
python verify.py tgwitness-evidence.zip --fingerprint COLLECTOR_SHA256 \
    --witness witness.zip --witness-fingerprint WITNESS_SHA256 --require-witness
```

این امر مستلزم اثر انگشت شاهدی است که به‌طور مستقل نگهداری شده و یک نقطه کنترل تطابق‌دار در انتهای دقیق این خروجی. یک نقطه کنترل که فقط پیشوند قبلی را پوشش می‌دهد ناکافی است. جمع‌آوری را متوقف کنید، اجازه دهید شاهد وضعیت نهایی را مشاهده کند و قبل از نوشتن‌های بیشتر در ژورنال، خروجی را صادر کنید؛ اگر ژورنال تغییر کرد، یک نقطه کنترل دیگر نگهداری کرده و آن وضعیت را صادر کنید. یک نقطه کنترل بعدی به تنهایی نمی‌تواند هش نهایی یک خروجی کوتاه‌تر را تأیید کند. هنگامی که `--channel` نیز ارائه شود، عدم وجود پست‌های ادعا شده یا یک مجموعه تطابق خالی، این بررسی سخت‌گیرانه را ناموفق می‌کند. بدون این پرچم، بررسی‌های یکپارچگی عادی همچنان رکوردهای بدون شاهد را گزارش می‌کنند بدون اینکه آرشیوی را که در غیر این صورت سالم است، رد کنند.

این پرچم، سازگاری با سوابق شاهدی که ارائه و سنجاق شده‌اند را تضمین می‌کند. اپراتور همچنان باید استقلال شاهد را احراز کرده و سوابق آن را به طور جداگانه حفظ کند. این امر صحت پیام، جمع‌آوری کامل یا زمان اجرای اندازه‌گیری‌شده به طور مستقل را تضمین نمی‌کند.

یک ویژه‌گواه آنچه را که گردآورنده در آن زمان‌ها گزارش کرده است نشان می‌دهد و اینکه خروجی‌های بعدی با آن مطابقت دارند. این نشان نمی‌دهد که گردآورنده همه چیز را که تلگرام ارائه کرده ضبط کرده است، یا اینکه محتوای پیام‌ها درست است. ویژه‌گواهی که توسط همان اپراتور روی همان دستگاه اجرا می‌شود، از ویژه‌گواهی که توسط شخص دیگری اجرا شده ضعیف‌تر است.

تنها افزایش تعداد به تنهایی نمی‌تواند تداوم الحاقی صرف را به صورت آنلاین اثبات کند: مقایسه آفلاین باید هر هش پیشوند نگهداری‌شده را با خروجی کامل گردآورنده مطابقت دهد. از کار افتادن شاهد و انتشار ناموفق، بازه‌های زمانی را بدون لنگرهای خارجی رها می‌کند. پست‌های گمشده را می‌توان در دفترچه شاهد نگهداری‌شده گزارش کرد؛ نه یک کانال و نه سروری که توسط همان اپراتور کنترل می‌شود، یک آرشیو ثالث تغییرناپذیر نیست.
