تلپاتی
یک پیامرسان بدون سرور که هویت و تاریخچه گفتگوی کاربر را روی دستگاه خودش نگه میدارد؛ پیامهای آفلاین را از طریق رلههای عمومی و رمزنگاریشده تحویل میدهد و گفتگوی زنده و فایل را از مسیر مستقیم بین دو مرورگر ارسال میکند.
جزئیات پروژه
- تمرکز
- رمزنگاری سرتاسری پیامها، تحویل آفلاین از طریق رلههای عمومی، ارتباط زنده نقطهبهنقطه و انتقال فایل بدون عبور از سرور مرکزی
- سال
- 1405
- نقش
- برنامهنویس کل پروژه (طراحی معماری، پیادهسازی فرانتاند و لایههای رمزنگاری/پروتکل)
- کارفرما
- پروژه شخصی
- پلتفرم
- وب اپلیکیشن (PWA)
- مدت زمان
- 2 ماه
نمای کلی پروژه
تلپاتی یک پیامرسان است که کاملاً در مرورگر اجرا میشود و نیازی به نصب یا حساب کاربری ندارد. برخلاف پیامرسانهای معمولی که حساب و محتوای گفتگو را روی سرور مرکزی نگه میدارند، در این پروژه هویت کاربر، کلیدهای رمزنگاری و تاریخچهٔ پیامها فقط روی دستگاه خودش میماند و هیچ سرور مرکزیای برای این پروژه وجود ندارد.
مشکل اصلی که این پروژه حل میکند این است که پیامرسانهای سروری سه ضعف دارند: محتوای گفتگو در دسترس مالک سرور قرار میگیرد، حساب کاربر عملاً گروگان همان سرور است و نگهداشتن سرور بهصورت شبانهروزی خودش هزینه و دردسر دائمی دارد. تلپاتی تلاش میکند بدون داشتن هیچ سرور اختصاصی، هم امنیت محتوا، هم قابلیت دریافت پیام در حالت آفلاین و هم حفظ تاریخچهٔ گفتگو را همزمان تأمین کند.
رویکرد
معماری پروژه روی سه ستون اصلی سوار است: کل برنامه یک وباپ استاتیک (PWA) است که هیچ API یا دیتابیس سمت سرور ندارد؛ رساندن پیام در حالت آفلاین از طریق رلههای عمومی پروتکل Nostr انجام میشود که فقط یک پاکت رمزنگاریشده را جابهجا میکنند بدون اینکه محتوای آن را ببینند؛ و گفتگوی زنده و انتقال فایل از طریق اتصال مستقیم WebRTC بین دو مرورگر برقرار میشود، بدون عبور از هیچ واسطهای.
روی این سه ستون، چند لایهٔ فنی پیادهسازی شده است:
- هویت: بهجای ثبتنام، برای هر کاربر یک جفتکلید رمزنگاری (secp256k1) ساخته میشود؛ کلید خصوصی با عبارت عبور و رمزنگاری AES-256-GCM محافظت میشود و هیچوقت بهصورت خام ذخیره نمیشود.
- پاکتپوشی پیام: هر پیام پیش از ارسال چند لایه امضا و رمزنگاری میشود (بر پایه استانداردهای NIP-44 و NIP-59)، طوری که رلهای که پاکت را نگه میدارد نه متن پیام، نه فرستنده و نه نوع پیام را نمیبیند.
- مسیریابی: یک بخش مرکزی در برنامه برای هر پیام تصمیم میگیرد از کانال مستقیم (در صورت آنلاین بودن طرف مقابل) یا از رلهٔ عمومی (در صورت آفلاین بودن) عبور کند؛ در نبود هر دو مسیر، پیام در صف خروجی میماند و با تلاش پلهای دوباره ارسال میشود.
- ترتیب و دوام: بهجای اتکا به ساعت دستگاه (که قابل اعتماد نیست)، هر گفتگو یک شمارندهٔ منطقی (Lamport) دارد که ترتیب پیامها را تضمین میکند؛ پیامها، دوستان و تنظیمات هم در دیتابیس محلی مرورگر (IndexedDB) ذخیره میشوند.
- فایل و عکس: هدر فایل (نام، نوع، هش) از مسیر رمزنگاریشدهٔ معمولی میرود، ولی خودِ بایتهای فایل فقط از کانال مستقیم بین دو دستگاه رد میشوند، تکهتکه و با امکان ادامه از تکهٔ نیمهکاره در صورت قطعی.
چالش
بزرگترین چالش این بود که بدون داشتن هیچ سرور اختصاصی، سه چیز را همزمان تضمین کنم: امنیت محتوا، دریافت پیام در حالت آفلاین و حفظ کامل تاریخچهٔ گفتگو. این سه هدف معمولاً در تعارض با هم هستند و رسیدن به هرکدام معمولاً به قیمت از دست دادن یکی دیگر تمام میشود.
چالش فنی دیگر، هماهنگ نگهداشتن ترتیب پیامها بدون تکیه به ساعت دستگاهها بود؛ چون ساعت گوشیها میتواند اشتباه یا نامنظم باشد. پیادهسازی شمارندهٔ منطقی (Lamport) این مشکل را حل کرد و ترتیب گفتگو را حتی با ساعتهای نادرست هم پایدار نگه داشت.
چالش دیگر مربوط به انتقال فایل بود: باید تضمین میشد که هیچ بایت فایلی از رلههای عمومی رد نشود، در حالی که این محدودیت را هم داشت که هر دو طرف باید همزمان آنلاین باشند. برای اطمینان از درستی این منطق و منطق رمزنگاری/مسیریابی، بیش از ۳۴۰ تست واحد در ۴۲ فایل نوشته شد که هستهٔ اصلی برنامه (بدون وابستگی به ظاهر) را پوشش میدهد.