مرجع / الأدلة
شاهد مستقل
قم بتشغيل «شاهد» باستخدام مفتاحه الخاص وروبوته، وانشر نقاط التحقق الموقعة على قناة، وقارن الصادرات بها.
إعداد البوت والبروكسي باللغة الروسية.
يقوم المجمع بتوقيع سجله الخاص، لذا فإن من يتحكم في المجمع ومفتاحه يمكنه من حيث المبدأ إعادة كتابة السجل أو اقتطاعه وتوقيعه مرة أخرى. أما «الشهود» (Witness) فيجعلون ذلك قابلاً للكشف. وهي عملية منفصلة — عبارة عن حاوية أخرى، أو بالأحرى خادم يديره شخص آخر — تقوم كل بضع دقائق بجلب رأس السجل الموقّع الخاص بـ«المجمع»، وتوقّع ما رأته بمفتاحها الخاص، وتحتفظ به في سجلها الخاص وتنشره على قناة Telegram.
الرسم التخطيطي كنص
- أداة التجميع → Witness (نقطة التحقق الموقعة: عدد السجلات + هاش الرأس)
- Witness → سجل الشهود، مفتاح خاص
- Witness → قناة Telegram (منشور موقّع عبر الروبوت الخاص بها)
- ملف ZIP للأدلة → verify.py
- سجل الشهود، مفتاح خاص → verify.py
- قناة Telegram → verify.py (صفحة التصدير من Telegram Desktop أو صفحة t.me/s)
ما يحصل عليه الشاهد، وما لا يحصل عليه#
| الشاهد لديه | الشاهد لم يسبق له أبدًا |
|---|---|
| رمز شاهد للقراءة فقط لمساحة عمل واحدة | بيانات اعتماد جلسة Telegram الخاصة بالمجمع أو بيانات اعتماد واجهة برمجة التطبيقات (API) |
| مفتاح Ed25519 خاص بها وسجلها الخاص | خزينة المجمع، أو مفتاح التوقيع، أو رمز لوحة التحكم |
| رمز بوت Telegram الخاص به | محتوى الرسالة: يتكون العنوان من عدد السجلات وقيمة التجزئة |
يتم إنشاء الرمز المميز على صفحة Witness (الشاهد) في اللوحة، ويظهر مرة واحدة ويتم تخزينه فقط كـ
SHA-256. يفتح نقطة نهاية واحدة بالضبط، GET /api/witness/head، والتي تُرجع نقطة تفتيش
موقعة حديثًا بالإضافة إلى عدادات التجميع الخالية من المحتوى الموقعة وحالة التشغيل.
لا يمكنه فتح اللوحة، أو قراءة محتوى الرسائل، أو تغيير الإعدادات، كما أن
رمز اللوحة غير مقبول هناك. يمكن إلغاء الرمز في نفس الصفحة. يقوم المجمع بالتسجيل
عندما يبدأ مفتاح شاهد جديد في الفحص (witness.seen) ويعرض آخر فحص لكل رمز؛
ويتم وضع علامة «متأخر» على أي شاهد لم يتم فحصه خلال 2.5 فترة.
يرسل الشهود الجدد تحديًا عشوائيًا في كل استطلاع؛ وتكرره عبارة التسجيل تحت توقيع المجمع. وترتبط العدادات بنقطة التحقق المحددة وتُدرج في منشورات الشهود الموقعة. وتظل الرؤوس القديمة مقبولة من قبل الشاهد المستقل. ولا يُحسب نمو السجل وحده أبدًا كرسالة جديدة.
ما الذي تتحقق منه وتسجله#
في كل فترة زمنية (10 دقائق بشكل افتراضي)، تقوم الأداة بما يلي:
- يسترد الرأس نفسه (لا يمكن للمجمع دفعه أو تخطيه)؛
- يتحقق من توقيع المجمع، ومفتاح المجمع المثبت (
--collector-fingerprint، أو أول مفتاح يظهر)، وعدد غير متناقص، ورأس لم يتغير عند عدد لم يتغير؛ - يُلحق سجلًا موقّعًا بسجله الخاص:
witness.anchorمع الحالةok،key_changed،rollback(عدد سجلات أقل من ذي قبل)،fork(نفس الطول، رأس مختلف ) أوinvalid(فشل التحقق من الإجابة)، أوwitness.no_responseعندما لم يرد المُجمِّع؛ - ينشر النتيجة على القناة، موقعة، بما في ذلك «لا يوجد رد» أثناء تشغيل 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 في قسم النشر).
افتح «Extras» → «A bot in your channel» → قم بإعداد بوت
في اللوحة. تغطي الخطوات الثلاث
الوصول للقراءة فقط، وقناتك، والفاصل الزمني، ثم تشغيل الشاهد. توجد
سياسة النشر، والبروكسي الاختياري HTTP/SOCKS5، وعنوان واجهة برمجة تطبيقات البوت المخصص ضمن «الإعدادات المتقدمة
». يقوم النموذج
بتنزيل 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، فلا تكشف سوى نقطة النهاية المحددة لـ «Witness» على
اسم مضيف HTTPS منفصل باستخدام هذا المثال من Caddy.
تستخدم مساحة العمل الافتراضية عندئذٍ https://witness.example.org، بينما تستخدم مساحات العمل الأخرى
https://witness.example.org/profiles/ID. لا تزال الرموز مطلوبة؛ ولا يتم توجيه اللوحة و
مسارات واجهة برمجة التطبيقات (API) الأخرى الخاصة بها عبر ذلك المضيف الافتراضي.
اختر all للحصول على نقاط فحص تُنشر بانتظام. الفاصل الزمني البالغ خمس دقائق يعني حوالي 288
منشورًا لكل مساحة عمل يوميًا. أما changes وproblems فيتركان بعض عمليات الفحص غير منشورة عن قصد.
MTProxy مخصص لعميل Telegram الخاص بالمجمع. يستخدم استطلاع Witness عبر HTTP وواجهة برمجة تطبيقات Telegram HTTPS
Bot مسارها الخاص المباشر/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 | ثوانٍ للانتظار حتى يبدأ المجمع وواجهة برمجة تطبيقات الروبوت (Bot 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) الروبوت، على سبيل المثال خادم محلي لواجهة برمجة تطبيقات الروبوت |
--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 على أنها لم تُنشر أبدًا؛ ويحدد سجل البداية
السياسة. لا تزال كل عملية تحقق تظهر في السجل، لذا فإن عدد المنشورات الأقل يعني عددًا أقل من
أوقات Telegram المستقلة، وليس عددًا أقل من عمليات التحقق.
حتى في حالة عدم وجود قناة، تظل أداة TgWitness تحتفظ بسجلها. احفظ بصمة مفتاح TgWitness
(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 بالتحقق من سجل الشاهد (السلسلة والتوقيعات)، ثم التأكد من أن كل رأس
شاهده الشاهد هو جزء من السجل المصدَّر: يجب أن يكون للسجل عند ذلك العدد بالضبط
تلك القيمة التجزئية. أي رأس لا يتطابق يفشل في التحقق — مما يعني أن السجل قد تم تغييره بعد
أن شاهده الشاهد. كما يبلغ عن الرؤوس التي شوهدت بعد التصدير، والانحرافات التي سجلها الشاهد
، والإجابات التي فشلت، والفترات التي توجد نقاط تفتيش مطابقة لها في هذا
التصدير («تمت مشاهدتها من X إلى Y») والفجوات. لا تمدد نقاط التفتيش اللاحقة تلك الفترات.
تتضمن النتيجة رقم السجل الأخير المطابق وعدد السجلات اللاحقة
التي لا تحتوي على نقطة تفتيش مطابقة. لا تُحتسب سوى الإجابات الموقعة بمفتاح التصدير نفسه: يُبلغ عن التصدير الموقع
بمفتاح لم يره الشاهد قط على أنه غير مشهود، وبدون --fingerprint يظل
الموقع غير مثبت. مع --channel، يجب أن يتطابق كل منشور موقّع مع دفتر الشاهد
سجلًا بسجل: تفشل المنشورات التي تم تغييرها في التحقق، ويتم إدراج المنشورات المفقودة في القائمة. يُعد التاريخ الموجود في
ملف تصدير JSON المقدم من Telegram بيانات وصفية قابلة للتعديل، خارج نطاق رمز الشاهد الموقّع.
لا تؤدي مطابقة الرمز إلى مصادقة تاريخ النشر؛ حيث تُشير النتيجة صراحةً
إلى أنه لم يتم إجراء التحقق من وقت النشر.
يلزم وجود حدود تصدير مشهود عليها#
لإجراء عملية تسليم يجب أن تتضمن سجلاً نهائياً مشهوداً عليه، أضف --require-witness:
python verify.py tgwitness-evidence.zip --fingerprint COLLECTOR_SHA256 \
--witness witness.zip --witness-fingerprint WITNESS_SHA256 --require-witness
وهذا يتطلب الاحتفاظ بشكل مستقل ببصمة الشاهد ونقطة تفتيش مطابقة
في النهاية الدقيقة لعملية التصدير هذه. إن نقطة التفتيش التي تغطي فقط البادئة السابقة
غير كافية. أوقف عملية التجميع مؤقتًا، ودع الشاهد يراقب الحالة النهائية، ثم قم بالتصدير
قبل إجراء أي عمليات كتابة أخرى في السجل؛ إذا تغير السجل، فاحتفظ بنقطة تفتيش أخرى و
قم بتصدير تلك الحالة. لا يمكن لنقطة فحص لاحقة بمفردها التحقق من التجزئة النهائية لعملية تصدير أقصر.
عندما يتم توفير --channel أيضًا، فإن المنشورات المزعومة المفقودة أو مجموعة المطابقة الفارغة تفشل في اجتياز هذا
الفحص الصارم. بدون العلامة، لا تزال فحوصات السلامة العادية تبلغ عن السجلات غير المشهودة
دون رفض أرشيف سليم بخلاف ذلك.
يضمن هذا العلامة الاتساق مع سجلات الشهود المرفقة والمثبتة. ولا يزال يتعين على المشغل التأكد من استقلالية الشاهد والحفاظ على سجلاته بشكل منفصل. ولا يثبت هذا العلامة صحة الرسائل، أو اكتمال جمعها، أو مدة تشغيلها المقاسة بشكل مستقل.
يُظهر «الشاهد» ما أبلغ عنه المُجمِّع في تلك الأوقات، وأن عمليات التصدير اللاحقة تتوافق مع ذلك. ولا يُظهر أن المُجمِّع سجل كل ما أرسله Telegram، أو أن محتوى الرسالة صحيح. إن تشغيل «الشاهد» بواسطة نفس المشغل على نفس الجهاز يكون أضعف من تشغيله بواسطة شخص آخر.
لا يمكن لزيادة العدد وحدها إثبات استمرارية «الإضافة فقط» عبر الإنترنت: يجب أن تتطابق المقارنة في وضع عدم الاتصال مع كل هاش بادئة محفوظة مقابل التصدير الكامل للمجمع. يؤدي تعطل «Witness» وفشل النشر إلى وجود فترات زمنية دون نقاط ارتكاز خارجية. يمكن الإبلاغ عن المنشورات المفقودة مقارنةً بسجل «Witness» المحفوظ؛ ولا يُعد أي قناة أو خادم يخضع لسيطرة نفس المشغل أرشيفًا ثابتًا تابعًا لطرف ثالث.