Awiteb
d59664198a
All checks were successful
Build site / Rust CI (push) Successful in 4s
Signed-off-by: Awiteb <a@4rs.nl>
312 lines
20 KiB
Markdown
312 lines
20 KiB
Markdown
+++
|
||
title = "الأصدار الاول من بروتوكول OxideTalis"
|
||
|
||
[extra]
|
||
image = "/otmp_ar.png"
|
||
lang = "ar-SA"
|
||
dir = "rtl"
|
||
add_toc = true
|
||
+++
|
||
|
||
<small>المؤلف: [عويتب](https://4rs.nl)</small>\
|
||
<small>التاريخ: 2024/6/1</small>\
|
||
<small>الاصدار: 1.0.0</small>\
|
||
<small>الحالة: مسودة</small>
|
||
|
||
|
||
## نظرة عامة
|
||
بروتوكول OxideTalis هو بروتوكول تواصل بين طرفين بتشفير تام من طرف إلى طرف عبر
|
||
مفتاح تشفير مشترك بينهم، يهدف البروتوكول إلى توفير سهولة التنقل من خادم إلى أخر
|
||
بشكل إفتراضي وتوفير طريقة للتواصل بين الافراد في خوادم مختلفة بشكل مباشر بدون
|
||
تواصل خادم المرسل وخادم المستقبل مع بعضهم البعض.
|
||
|
||
### الاهداف
|
||
- تواصل آمن بين طرفين مُشفر من ند إلى ند.
|
||
- سهولة التنفيذ.
|
||
- امكانية الإنتقال إلى خادم آخر.
|
||
- امكانية التواصل مع اطراف خارج الخادم الخاص بالمرسل.
|
||
- عدم الحاجة لتواصل المرسل مع الخادم الخاص به للتواصل مع اشخاص خارج الخادم.
|
||
- عدم الحاجة ﻷسم مستخدم وكلمة مرور لتخويل المسخدم للمراسلة، والاكتفاء بالعنوان
|
||
العام الخاص به.
|
||
|
||
### الاهداف الغير مرغوبة
|
||
- التواصل الجماعي.
|
||
- المكالمات الصوتية أو الفيديو.
|
||
|
||
## العناوين العامة
|
||
العنوان العام هو المفتاح العام الخاص بخوارزمية [Elliptic Curve Diffie-Hellman]
|
||
مضغوط وهو يتكون من 33 بايت (264 بت) يتم ترميزه بترميز [base58] على سبيل المثال
|
||
العنوان التالي `becZJsZZqGR7qBG8t1Pm4uy62jDTzJsabxnkARhr2syo`.
|
||
|
||
يتم وضع العنوان العام في رأس (Header) الطلب (Request) بأسم `X-OTMP-PUBLIC` ويجب ان يكون نص [base58] صحيح مكون من 33 بايت (264 بت).
|
||
|
||
## أسم الخادم
|
||
يكون أسم الخادم عنوان إلكتروني مثل `example.com` ولا يجب أن يكون الخادم نفسه، هو
|
||
أسم فقط يشير إلى الخادم، على سبيل المثال، أسم الخادم `example.com` ولكن الخادم
|
||
هو `otmp.example.com:443`، هكذا سوف يتم الإشارة لى مستخدمين هذا الخادم <snap
|
||
dir='ltr'><code>@becZJsZZqGR7qBG8t1Pm4uy62jDTzJsabxnkARhr2syo/example.com</code></snap>
|
||
ويمكن إختصاره بالواجهات الرسومية بأخذ أول ثلاث أحرف و أخر ثلاث أحرف ووضع `..`
|
||
بينهم، ليصبح بهذا الشكل <snap
|
||
dir='ltr'><code>@bec..syo/example.com</code></snap>.
|
||
|
||
### كيفية الإشارة
|
||
يشير أسم الخادم إلى الخادم عبر المسار التالي <span
|
||
dir='ltr'><code>/.well-known/oxidetalis/server</code></span>
|
||
|
||
سوف يتم إرسال طلب GET إلى هذا المسار و يجب أن يُرجع هذا المسار نص بتنسيق
|
||
`application/json` يحتوي على المفتاح `otmp_server` ولذي يحتوي على مكان إستضافة
|
||
الخادم والمنفذ الذي يستمع إليه، سوف يتم إرسال الطلب ببروتوكول https و يجب أن
|
||
يدعم الخادم https و يجب ان تكون الشهادة موقعة من جهة موثوقة وليست موقعة
|
||
ذاتياً[^1]
|
||
|
||
### مفتاح `otmp_server`
|
||
محتوى هذا المفتاح يجب أن يكون نص، يتكون هذا النص من جزئين يفصل بينهم نقطتان
|
||
رأسيتان، الجزء الأول هو مكان الإستضافة و الجزء الثاني هو المنفذ على سبيل المثال
|
||
`"example.com:443"` و `"otmp.example.com:7294"` و `"93.184.215.14:7294"` و <snap
|
||
dir='ltr'><code>"[2606:2800:021f:cb07:6820:80da:af6b:8b2c]:7294"</code></snap>.
|
||
|
||
### مثال
|
||
|
||
<div dir="ltr">
|
||
|
||
```json
|
||
{"otmp_server": "otmp.example.com:443"}
|
||
```
|
||
|
||
</div>
|
||
|
||
> يجب على الخوادم عدم تخزين اسماء خوادم المرسلين الخارجيين، ويتم تحديده في الطلب
|
||
> المرسل من قبلهم فقط، حيث يعتبر المفتاح العام هو المعرف المشترك بين جميع
|
||
> الخوادم. سوف يوفر هذا سهولة إنتقال الافراد من خادم إلى أخر مع بقاء تعرف
|
||
> الخوادم الاخرى عليهم.
|
||
|
||
## مفتاح التشفير المشترك
|
||
يتم انشاء مفتاح التشفير المشترك عبر خوارزمية [Elliptic Curve Diffie-Hellman] حيث
|
||
سوف يقوم مرسل الرسالة بوضع العنوان العام الخاص بالمستقبِل ليتم انتاج المفتاح
|
||
المشترك، بعد إنتاج المفتاح المشترك يتم ادخاله إلى دالة [HKDF] **بدون ملح**
|
||
بخوارزمية [Sha256] وبعد ذلك يتم عمل له توسعة (expand) بدون معلومات (info) بطول
|
||
32 بايت (256 بت).
|
||
|
||
### التشفير
|
||
سوف يتم استخدام [مفتاح التشفير المشترك] مفتاحاً للتشفير في خوارزمية [AES-256
|
||
CBC]، بعد تشفير الرسالة يتم وضع قيمة التهيئة (iv) في أخر الرسالة، ليكون اخر 16
|
||
بايت (128 بت) هي قيمة التهيئة (iv) التي سوف يستخدمها المستقبِل لفك تشفير
|
||
الرسالة.
|
||
|
||
مثال لمفتاح تشفير مشترك بترميز [base58] <span
|
||
dir="ltr"><code>LKGKeuV3SRu1n3fez4SdboM3FT48vbBxHai9MbuWxb3</code></span>
|
||
|
||
## مفتاح الخادم العام
|
||
مفتاح الخادم العام هو مثل العنواين العامة الخاصة بالمستخدمين، ولكنه خاص بالخادم،
|
||
حيث ان الخادم سوف يقوم بأنشاء مفتاح مشترك بينه وبين مرسل الطلب (Request) ليتأكد
|
||
من أن المرسل (صاحب العنوان العام) هو مالك هذا العنوان. يتم التأكد عبر مطابقة
|
||
التوقيع الموجود في الطلب (Request).
|
||
|
||
يتم جلب مفتاح الخادم العام من المسار <span
|
||
dir='ltr'><code>/api/info</code></span> سوف يتم إرسال طلب GET إلى هذا المسار و
|
||
يجب أن يُرجع هذا المسار نص بتنسيق `application/json` يحتوي على المفتاح
|
||
`public_key` ولذي قيمته نص المفتاح العام الخاص بالخادم بترميز [base58]، سوف يتم
|
||
إرسال الطلب ببروتوكول https و يجب أن يدعم الخادم https و يجب ان تكون الشهادة
|
||
موقعة من جهة موثوقة وليست موقعة ذاتياً[^1]
|
||
|
||
> تم توضيح المفتاح العام هنا ([العناوين العامة](#l-nwyn-l-m))
|
||
|
||
> حاول ان لا تقوم بتغيير المفتاح العام الخاص بالخادم بشكل مستمر، لآن العملاء سوف
|
||
> يقومون بتخزينه بالعادة.
|
||
|
||
## توقيع الطلب
|
||
هو التوقيع الخاص بالطلب يتم وضعه في رأس الطلب (Header) بأسم `X-OTMP-SIGNATURE`
|
||
او في بيانات ال [Websocket] في المفتاح `signature` بترميز [Hex] ويتم أستخدامه
|
||
للتأكد من ان مرسل الطلب هو مالك المفتاح العام.
|
||
|
||
### إنشاء التوقيع
|
||
التوقيع يحتاج إلى ثلاث اشياء ليتم إنشائه
|
||
- مفتاح التشفير المشترك.
|
||
- جسم الطلب (body) أو بيانات الحدث (data) أو طريقة الطلب+المسار، مثال (GET/ws/chat)
|
||
- ثواني الوقت الحالي للمنطقة الزمنية UTC بتنسيق [Unix Time] (8 بايت أي 64 بت
|
||
**big-endian**).
|
||
- 16 بايت عشوائي (128 بت).
|
||
|
||
يتم إدخال جسم الطلب (body) او بيانات الحدث في الـ[Websocket] إلى دالة
|
||
[HMAC-SHA256] و إستخدام [مفتاح التشفير المشترك] مضافاً إليه الوقت الحالي (8
|
||
بايت) و الـ16 بايت العشوائي، أي المفتاح المستخدم في دالة [HMAC-SHA256] سوف يكون
|
||
|
||
```
|
||
مفتاح التشفير المشترك+الوقت الحالي+16 بايت عشوائي
|
||
```
|
||
بعد ذلك يتم أخذ نتيجة دالة [HMAC-SHA256] و إضافة الوقت المستخدم في الأعلى و
|
||
الـ16 بايت المستخدمة في الأعلى و جميعهم بترميز [Hex]، مثال
|
||
|
||
|
||
<div dir="ltr">
|
||
|
||
```
|
||
bad035084e11bfd266c7b7dfa473d6603be551b3aa215f869776b75bf42ef31900000000665e1a696e6d776f65726e6664757265686a66
|
||
```
|
||
|
||
</div>
|
||
|
||
بعد تحويله إلى بايتات سوف يكون المجموع 56 بايت، وسوف يكون التقسيم كالتالي
|
||
- مخرج دالة [HMAC-SHA256]: من بايت 0 إلى بايت31. (التوقيع الذي سوف يتحقق منه
|
||
الخادم)
|
||
- الوقت: من بايت 32 إلى بايت 39. (الذي سوف يتم إضافته بعد [مفتاح التشفير
|
||
المشترك])
|
||
- ال 16 بايت العشوائي: من بايت 40 إلى بايت 55. (سوف يتم إضافته بعد الوقت)
|
||
|
||
سوف يتحقق الخادم من أن الوقت الذي في التوقيع لم يتجاوز الـ20 ثانية، وسوف يقوم
|
||
الخادم بتخزين ال 16 بايت العشوائي في الكاش بمدة حياة 30 ثانية، ليتأكد الخادم من
|
||
ان ال 16 بايت العشوائي لن يتم إستخدامهم في توقيع أخر، بالتالي ضمان عدم إرسال
|
||
الطلب مرة أخرى من المهاجمين (ضمان أن التوقيع صالح لمرة واحدة فقط).
|
||
|
||
### شكل البيانات داخل إتصال الـWebsocket
|
||
بعد الإتصال بـ[Websocket] مع الخادم، يكون تنسيق البيانات التي يتم تبادلها
|
||
بين المرسل والخادم json ويجب عليها توفر المفاتيح التالية
|
||
|
||
- `event`: إسم الحدث، على سبيل المثال إرسال رسالة او تحديث حالة الكتابة (التنسيق PascalCase).
|
||
- `data`: البيانات الخاصة بالحدث.
|
||
- `signature`: توقيع بيانات الحدث (data)، هذا التوقيع يكون بين المرسل وبين
|
||
الخادم وليس المُستقبل.
|
||
|
||
#### مثال لشكل البيانات في ال websocket
|
||
|
||
|
||
<div dir="ltr">
|
||
|
||
```json
|
||
{
|
||
"event": "EventName",
|
||
"data": {
|
||
"key": "value"
|
||
},
|
||
"signature": "bad035084e11bfd266c7b7dfa473d6603be551b3aa215f869776b75bf42ef31900000000665e1a696e6d776f65726e6664757265686a66"
|
||
}
|
||
```
|
||
|
||
</div>
|
||
|
||
> يمكن للخادم طلب أي شكل من البيانات، و يجب أن تكون المعلومات الحساسة مثل
|
||
> الرسالة او الملف أن مشفر بينك وبين المُستقبل فقط.
|
||
|
||
## طريقة التواصل
|
||
هنا سوف يتم توضيح طريقة التواصل بين طرفين في خادم واحد (تواصل داخلي)، وبين طرفين
|
||
في خوادم مختلفة (تواصل خارجي)
|
||
|
||
### مفاهيم مهمة
|
||
- التواصل الداخلي: هو تواصل طرفين في الخادم نفسه.
|
||
- التواصل الخارجي: هو تواصل طرفين في خوادم مختلفة.
|
||
- القائمة البيضاء: هي قائمة يمتلكها كل مستخدم في الخادم يوجد بها المستخدمين
|
||
المسموح لهم بمراسلته.
|
||
- القائمة السوداء: هي قائمة يمتلكها كل مستخدم في الخادم يوجد بها المستخدمين
|
||
الغير مسموح لهم بمراسلته.
|
||
- قائمة الخادم السوداء: هي قائمة يقوم بوضعها مالك الخادم ليمنع خادمه من التواصل
|
||
مع خوادم محددة او اشخاص محددين.
|
||
- جدول الإتصالات الخارجية: هو جدول يتم حفظ به الرسائل الخارجية التي وصلت إلى
|
||
المستخدم عندما لم يكن متصل بالخادم، ويتم مسحها بعد إرسالها له.
|
||
- جدول طلبات الدردشة: هو جدول يتضمن طلبات الدردشة التي قاموا بإرسالها او
|
||
إستقبالها افراد الخادم إلى/من افراد اخرين في نفس الخادم او في خوادم أخرى، ويتم
|
||
مسح الطلب بعد وصول قبوله او رفضه. يتم الإستفادة من هذا الجدول لعدم إستقبال
|
||
إشعارات قبول او رفض مزيفة.
|
||
|
||
> سوف يتم استبدال العنوان العام بأسم Alice و Bob لآن العناوين العامة طويلة
|
||
> نسبياً
|
||
|
||
### التواصل الداخلي
|
||
اولاً **يجب**[^2] عند فتحك لعميل التواصل أن تقوم بإنشاء تواصل [Websocket] بينك
|
||
وبين الخادم الخاص بك، عبر هذا الإتصال سوف تستقبل الرسائل الجديدة من الخادم الخاص
|
||
بك، وسوف تقوم بالتواصل من خلاله لإرسال الرسائل إلى افراد الخادم.
|
||
|
||
لدينا الآن المرسل alice والمستقبِل bob و كلاهم في الخادم نفسه، سوف يقوم alice
|
||
بإرسال رسالة [Websocket] يطلب من الخادم إرسال طلب الدردشة إلى bob وسوف يرد
|
||
الخادم بأحد الأخطأ التالية، او لا يقوم بالرد إذا لم يكن هناك خطأ.
|
||
|
||
#### إذا لم يكن هناك مستخدم بأسم bob في الخادم
|
||
سوف يرجع الخادم خطأ ويخبر فيه العميل أنه ليس هناك مستخدم بهذا الأسم.
|
||
|
||
#### إذا لم يكن alice في قائمة bob البيضاء ولا السوداء
|
||
سوف يقوم الخادم اولاً بإضافة bob إلى قائمة alice البيضاء، وبعد ذلك إضافة الطلب
|
||
في جدول طلبات الدردشة **المُستقبلة** بالنسبة لـbob إذا كان غير متصل مع الخادم
|
||
وسوف يضيفه إلى **المُرسلة** بالنسبة إلى alice، لا يرجع الخادم أي خطأ في هذه
|
||
الحالة.
|
||
|
||
عندما يرد bob بالموافقة ام الرفض (عبر إتصال ال [Websocket])، سوف يُعلم الخادم
|
||
alice بأن bob وافق او رفض التواصل معه (عبر إتصال الـ [Websocket] او إضافته إلى
|
||
جدول ليعلمه عند تواصله مع الخادم). إذا لم يوافق bob سوف يقوم الخادم بإضافة alice
|
||
إلى قائمة bob السوداء، و إذا وافق سوف يتم إضافته إلى القائمة البيضاء.
|
||
|
||
#### إذا كان alice في قائمة bob البيضاء
|
||
سوف يرجع الخادم خطأ، يعلم العميل أنه في قائمة bob البيضاء.
|
||
|
||
#### إذا كان alice في قائمة bob السوداء
|
||
سوف يرجع الخادم خطأ و يُعلم alice انه في قائمة bob السوداء ولا يمكنه الدردشة
|
||
معه.
|
||
|
||
> يتم تخزين رسائل الطرفين مُشفرة في قاعدة البيانات الخاصة بالخادم
|
||
|
||
### التواصل الخارجي
|
||
لدينا الآن المرسل alice من `example1.com` والمستقبِل bob من `example2.com` سوف
|
||
يقوم alice بإرسال طلب Get إلى `example2.com` يطلب فيه الدردشة مع bob، سوف يرد
|
||
الخادم بأحد الردود التالية
|
||
|
||
#### إذا لم ي3كن هناك مستخدم بأسم bob في الخادم
|
||
سوف يرجع الخادم 404 و يُعلم alice بأنه ليس لديه مستخدم بهذا الأسم.
|
||
|
||
#### إذا لم يكن alice في قائمة bob البيضاء ولا السوداء
|
||
سوف يقوم خادم bob بإرسال طلب الدردشة إلى bob او يقوم بتخزين الطلب في جدول طلبات
|
||
الدردشة **المٌستقبلة**، ويرد عليه بـ200، بعد ذلك يقوم alice بطلب الخادم الخاص به
|
||
من إضافة bob إلى قائمته البيضاء ليستقبل منه الرسائل مستقبلاً بدون حاجة bob إرسال
|
||
طلب دردشة وإنتظار قبولها، سوف يقوم alice ايضاً بطلب الخادم من إضافة bob إلى جدول
|
||
طلبات الدردشة **المُرسلة** ويتم تضمين خادم bob الحالي الذي تم إرسال طلب الدردشة
|
||
إليه[^3]
|
||
|
||
إذا قبل/رفض bob الدردشة سوف يُعلم خادم bob خادم alice أن bob قام بقبول/رفض
|
||
الدردشة، سوف يضع الخادم التوقيع الخاص به في `X-OTMP-SIGNATURE` وسوف يتم جلب
|
||
المفتاح العام الخاص به من مسار الخادم[^4] (لقد قام alice بإضافة bob والخادم
|
||
الخاص به في جدول طلبات الدردشة **المُرسلة** لذالك خادم alice يعلم ماهو خادم
|
||
bob).
|
||
|
||
بعد ذلك إذا لم يكن لـalice إتصال [Websocket] سابق مع خادم bob، سوف يقوم بإرسال
|
||
طلب دردشة ليتم ترقية الإتصال إلى [Websocket]، ونفس المسئلة مع bob إذا اراد
|
||
التواصل مع alice سوف يقوم بإرسال طلب دردشة ويتم ترقية الإتصال او إعلامه بوجود
|
||
إتصال [Websocket] مفتوح.
|
||
|
||
#### إذا كان alice في قائمة bob البيضاء
|
||
سوف يقوم الخادم بترقية الإتصال إلى [Websocket] او إذا كان alice متصل معه من قبل،
|
||
سوف يقوم بإرجاع 400 ويخبر alice بالتواصل معه عبر ال [Websocket].
|
||
|
||
#### إذا كان alice في قائمة bob السوداء او كان هو او خادمه في قائمة الخادم السوداء
|
||
سوف يرجع الخادم 403 مع توضيح السبب.
|
||
|
||
#### أساسيات
|
||
- يجب على alice فتح إتصال [Websocket] مع جميع الخوادم التي يريد التواصل مع
|
||
افرادها.
|
||
- لايتم تخزين الرسائل التي يستقبلها الخادم بشكل دائم، يتم تخزينها فقط إذا لم يكن
|
||
bob متصل بالخادم، ويتم مسحها بعد إرسالها إلى bob.
|
||
- الرسائل والملفات بين الطرفين تكون مشفرة وتكون موقعة للخادم المراد التواصل مع
|
||
افراده.
|
||
|
||
## شكر و تقدير
|
||
شكراً للأشخاص التاليين على مراجعة و تحسين البروتوكول.
|
||
- أمجد الشرفي <<me@amjad.alsharafi.dev>>: تحسين طريقة عمل التوقيع، و أقتراح
|
||
الطريقة الحالية.
|
||
|
||
{{ hr(data_content="وصلات") }}
|
||
|
||
[^1]: لضمان عدم وجود شخص في المنتصف، يقوم بالتلاعب بالبيانات و الإطلاع عليها.
|
||
|
||
[^2]: طالما انك عضو في الخادم، سوف يعتقد الخادم دائماً انك في إتصال [Websocket] معه، ولن يقوم بترقية أي إتصال إلى [Websocket]
|
||
|
||
[^3]: يتم إضافة العنوان الخاص بـbob و الخادم الخاص به في جدول طلبات الدردشة للتاكد من عدم إستقبال إشعارات قبول/رفض من خوادم مزيفة هدفها الإزعاج.
|
||
|
||
[^4]: للتاكد من انه الخادم فعلاً، لن يتم طلب منه المفتاح العام بشكل مباشر، بل سوف يتم جلبه من مسار الخاص به، وهو <span
|
||
dir='ltr'><code>/api/info</code></span>
|
||
|
||
[Websocket]: https://en.wikipedia.org/wiki/WebSocket
|
||
[HMAC-SHA256]: https://en.wikipedia.org/wiki/HMAC
|
||
[مفتاح التشفير المشترك]: #mfth-ltshfyr-lmshtrk
|
||
[Hex]: https://en.wikipedia.org/wiki/Hexadecimal
|
||
[Unix Time]: https://en.wikipedia.org/wiki/Unix_time
|
||
[AES-256 CBC]: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
|
||
[Sha256]: https://en.wikipedia.org/wiki/SHA-2
|
||
[HKDF]: https://en.wikipedia.org/wiki/HKDF
|
||
[base58]: https://bitcoinwiki.org/wiki/base58
|
||
[Elliptic Curve Diffie-Hellman]: https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman
|