+++
title = "الأصدار الاول من بروتوكول OxideTalis"
[extra]
image = "/otmp_ar.png"
lang = "ar-SA"
dir = "rtl"
add_toc = true
+++
المؤلف: [عويتب](https://4rs.nl)\
التاريخ: 2024/6/1\
الاصدار: 1.0.0\
الحالة: مسودة
## نظرة عامة
بروتوكول OxideTalis هو بروتوكول تواصل بين طرفين بتشفير تام من طرف إلى طرف عبر
مفتاح تشفير مشترك بينهم، يهدف البروتوكول إلى توفير سهولة التنقل من خادم إلى أخر بشكل إفتراضي
والتواصل مع الافراد بغض النظر عن خوادمهم، ويهدف
البروتوكول أيضاً على توفير طريقة للتواصل بين الافراد في خوادم مختلفة بشكل مباشر
بدون تواصل خادم المرسل وخادم المستقبل مع بعضهم البعض.
### الاهداف
- تواصل آمن بين طرفين مُشفر من ند إلى ند.
- سهولة التنفيذ.
- امكانية الإنتقال إلى خادم آخر.
- امكانية التواصل مع اطراف خارج الخادم الخاص بالمرسل.
- **عدم الحاجة** لتواصل المرسل مع الخادم الخاص به للتواصل مع اشخاص خارج الخادم.
- عدم الحاجة ﻷسم مستخدم وكلمة مرور لتخويل المسخدم للمراسلة، والاكتفاء بالعنوان
العام الخاص به.
### الاهداف الغير مرغوبة
- التواصل الجماعي.
- المكالمات الصوتية أو الفيديو.
## العناوين العامة
العنوان العام هو المفتاح العام الخاص بخوارزمية [Elliptic Curve Diffie-Hellman]
مضغوط وهو يتكون من 33 بايت (264 بت) يتم ترميزه بترميز [base58] على سبيل المثال
العنوان التالي `becZJsZZqGR7qBG8t1Pm4uy62jDTzJsabxnkARhr2syo`.
يتم وضع العنوان العام في رأس (Header) الطلب (Request) بأسم `X-OTMP-PUBLIC` ويجب
ان يكون نص [base58] صحيح مكون من 33 بايت (264 بت).
> يجب على الخوادم عدم تخزين اسماء خوادم المرسلين الخارجيين، ويتم تحديده في الطلب المرسل من قبلهم فقط، حيث يعتبر المفتاح العام هو المعرف المشترك بين جميع الخوادم.
> سوف يوفر هذا سهولة إنتقال الافراد من خادم إلى أخر مع بقاء تعرف الخوادم الاخرى عليهم.
## أسم الخادم
أسم الخادم هو نطاق إلكتروني طبيعي، على سبيل المثال `example.com` ويتم جلب عنوان
الخادم و المنفذ (port) من خلال المسار التالي
`https://example.com/.well-known/oxidetalis/server` وهو نص بتنسيق json بالشكل
الآتي
```json
{"otmp_server": "otmp.example.com:443"}
```
حيث يتم وضع نقطتان رأسيتان `:` بين عنوان الخادم والمنفذ الذي يستمع إليه. سيسهل
هذا من جعل أسماء الخوادم سهلة التذكر والكتابة.
يتم وضع اسم خادم المرسل في رأس الطلب بأسم `X-OTMP-SERVER` ويجب ان يكون اسم الخادم فقط، على سبيل المثال `example.com`.
## مفتاح التشفير المشترك
يتم انشاء مفتاح التشفير المشترك عبر خوارزمية [Elliptic Curve Diffie-Hellman] حيث
سوف يقوم مرسل الرسالة بوضع العنوان العام الخاص بالمستقبِل ليتم انتاج المفتاح
المشترك، بعد إنتاج المفتاح المشترك يتم ادخاله إلى دالة [HKDF] **بدون ملح**
بخوارزمية [Sha256] وبعد ذلك يتم عمل له توسعة (expand) بدون معلومات (info) بطول
32 بايت (256 بت)، وسوف يتم استخدام هذه النتيجة مفتاحاً للتشفير في خوارزمية
AES-256 CBC، بعد تشفير الرسالة يتم وضع قيمة التهيئة (iv) في أخر الرسالة، ليكون
اخر 16 بايت (128 بت) هي قيمة التهيئة (iv) التي سوف يستخدمها المستقبِل لفك تشفير
الرسالة.
مثال لمفتاح تشفير مشترك بترميز [base58]\
`LKGKeuV3SRu1n3fez4SdboM3FT48vbBxHai9MbuWxb3`
## عنوان الخادم
عنوان الخادم مثل العنواين العامة الخاصة بالمستخدمين، ولكنه خاص بالخادم، حيث ان
الخادم سوف يقوم بأنشاء مفتاح مشترك بينه وبين مرسل الطلب (Request) ليتأكد من أن
المرسل (صاحب العنوان العام) هو مالك هذا العنوان. يتم التأكد عبر مطابقة التوقيع
الموجود في الطلب (Request).
يتم توفير المفتاح العام الخاص بالخادم في هذا المسار
`https://example.com/.well-known/oxidetalis/public`
> حاول ان لا تقوم بتغيير المفتاح العام الخاص بالخادم بشكل مستمر، لآن العملاء سوف
> يقومون بتخزينه بالعادة.
## توقيع الطلب
هو التوقيع الخاص بالطلب يتم وضعه في رأس الطلب (Header) بأسم `X-OTMP-SIGNATURE`
بترميز [Hex] ويتم أستخدامه للتأكد من ان مرسل الطلب هو مالك المفتاح العام.
### إنشاء التوقيع
التوقيع يحتاج إلى شيئين ليتم إنشائه
- جسم الطلب (body)
- ثواني الوقت الحالي للمنطقة الزمنية UTC بتنسيق [Unix Time] (8 بايت أي 64 بت)
يتم إدخال جسم الطلب في دالة [Sha256] وبعد ذلك يتم تشفير مخرج الدالة بخوارزمية
[AES-256 CBC] بـ[مفتاح التشفير المشترك] بين مرسل الطلب والخادم، بعد ذلك يتم
إضافة الوقت الحالي إلى النتيجة و إدخالها مرة أخرى إلى دالة [Sha256].
> يجب ترميز التوقيع بـ[Hex] قبل وضعه في الرأس. يفضل ان يقوم الخادم بإنشاء توقيع
> الثانية الحالية والثانية السابقة والتحقق إذا كان التوقيع واحداً منهم
### شكل البيانات داخل إتصال الـWebsocket
بعد الإتصال بـ[Websocket] مع الخادم، سوف يكون تنسيق البيانات التي يتم تبادلها بين المرسل والخادم json ويجب عليها توفر المفاتيح التالية
- `event`: إسم الحدث، على سبيل المثال إرسال رسالة او تحديث حالة الكتابة.
- `data`: البيانات الخاصة بالحدث.
- `public_key`: وهو العنوان العام الخاص بالمرسل.
- `signature`: توقيع بيانات الحدث (data)، هذا التوقيع يكون بين المرسل وبين الخادم وليس المُستقبل.
ليكون الشكل النهائي كالتالي (مثال)
```json
{
"event": "EVENT_NAME",
"data": {
"key": "value"
},
"public_key": "becZJsZZqGR7qBG8t1Pm4uy62jDTzJsabxnkARhr2syo",
"signature": "1a2fc26dc7ea5a2a4748b7cb2b1ef193d96ab2c99f93092f69e63075b28d1278"
}
```
> يمكن للخادم طلب أي شكل من البيانات، ويمكنه طلب منك بعض القيم مشفرة بينك وبينه (مثل عنوان المُستقبل) ولكن يجب على المعلومات الحساسة مثل الرسالة او الملف أن يكون مشفر بينك وبين المُستقبل فقط.
## طريقة التواصل
هنا سوف يتم توضيح طريقة التواصل بين طرفين في خادم واحد (تواصل داخلي)، وبين
طرفين في خوادم مختلفة (تواصل خارجي)
### مفاهيم مهمة
- التواصل الداخلي: هو تواصل طرفين في الخادم نفسه.
- التواصل الخارجي: هو تواصل طرفين في خوادم مختلفة.
- القائمة البيضاء: هي قائمة يمتلكها كل مستخدم في الخادم يوجد بها المستخدمين
المسموح لهم بمراسلته.
- القائمة السوداء: هي قائمة يمتلكها كل مستخدم في الخادم يوجد بها المستخدمين
الغير مسموح لهم بمراسلته.
- قائمة الخادم السوداء: هي قائمة يقوم بوضعها مالك الخادم ليمنع خادمه من التواصل مع خوادم محددة او اشخاص محددين.
- جدول الإتصالات الخارجية: هو جدول يتم حفظ به الرسائل الخارجية التي وصلت إلى
المستخدم عندما لم يكن متصل بالخادم، ويتم مسحها بعد إرسالها له.
- جدول طلبات الدردشة: هو جدول يتضمن طلبات الدردشة التي قاموا بإرسالها او إستقبالها افراد الخادم إلى/من افراد اخرين في نفس الخادم او في خوادم أخرى، ويتم مسح الطلب بعد وصول قبوله او رفضه. يتم الإستفادة من هذا الجدول لعدم إستقبال إشعارات قبول او رفض مزيفة.
> سوف يتم استبدال العنوان العام بأسم Alice و Bob لآن العناوين العامة طويلة
> نسبياً
### التواصل الداخلي
اولاً **يجب**[^1] عند فتحك لعميل التواصل أن تقوم بإنشاء تواصل [Websocket] بينك وبين الخادم
الخاص بك، عبر هذا الإتصال سوف تستقبل الرسائل الجديدة من الخادم الخاص بك، وسوف
تقوم بالتواصل من خلاله لإرسال الرسائل إلى افراد الخادم.
لدينا الآن المرسل alice والمستقبِل bob و كلاهم في الخادم نفسه، سوف يقوم
alice بإرسال طلب Get إلى الخادم يطلب فيه الدردشة مع bob، سوف يرد الخادم بأحد الردود التالية إعتماداً
على حالة alice
#### إذا لم يكن هناك مستخدم بأسم bob في الخادم
سوف يرجع الخادم 404 و يُعلم alice بأنه ليس لديه مستخدم بهذا الأسم.
#### إذا لم يكن alice في قائمة bob البيضاء ولا السوداء
سوف يقوم الخادم اولاً سوف يقوم الخادم بإضافة bob إلى قائمة alice البيضاء، وبعد ذلك إضافة الطلب في جدول طلبات الدردشة **المُستقبلة** بالنسبة لـbob وسوف يضيفه إلى **المُرسلة** بالنسبة إلى alice ويرجع 200 ويقوم بإرسال طلب الدردشة إلى bob وينتظر رد bob، عندما يرد
bob بالموافقة ام الرفض (عبر إتصال ال [Websocket])، سوف يُعلم الخادم alice بأن
bob وافق او رفض التواصل معه (عبر إتصال الـ [Websocket] او إضافته إلى جدول ليعلمه عند تواصله مع الخادم). إذا لم يوافق bob سوف
يقوم الخادم بإضافة alice إلى قائمة bob السوداء، و إذا وافق سوف يتم إضافته إلى القائمة البيضاء.
#### إذا كان alice في قائمة bob البيضاء
سوف يرجع الخادم 400 و يُعلم alice بأنه يمكنه مراسلة bob بشكل مباشر عبر إتصال الـ[Websocket].
#### إذا كان alice في قائمة bob السوداء
سوف يرجع الخادم 403 و يُعلم alice انه في قائمة bob السوداء ولا يمكنه الدردشة معه.
> يتم تخزين رسائل الطرفين مُشفرة في قاعدة البيانات الخاصة بالخادم
### التواصل الخارجي
لدينا الآن المرسل alice من `example1.com` والمستقبِل bob من `example2.com` سوف يقوم
alice بإرسال طلب Get إلى `example2.com` يطلب فيه الدردشة مع bob، سوف يرد الخادم
بأحد الردود التالية
#### إذا لم يكن هناك مستخدم بأسم bob في الخادم
سوف يرجع الخادم 404 و يُعلم alice بأنه ليس لديه مستخدم بهذا الأسم.
#### إذا لم يكن alice في قائمة bob البيضاء ولا السوداء
سوف يقوم خادم bob بإرسال طلب الدردشة إلى bob او يقوم بتخزين الطلب في جدول طلبات الدردشة **المٌستقبلة**، ويرد عليه بـ200، بعد ذلك يقوم alice بطلب الخادم الخاص به من إضافة bob إلى قائمته البيضاء ليستقبل منه الرسائل مستقبلاً بدون حاجة bob إرسال طلب دردشة وإنتظار قبولها، سوف يقوم alice ايضاً بطلب الخادم من إضافة bob إلى جدول طلبات الدردشة **المُرسلة** ويتم تضمين خادم bob الحالي الذي تم إرسال طلب الدردشة إليه[^2]
إذا قبل/رفض bob الدردشة سوف يعلم خادم bob خادم alice أن bob قام بقبول/رفض الدردشة، سوف يضع الخادم عنوانه في `X-OTMP-SERVER` و التوقيع الخاص به في `X-OTMP-SIGNATURE` وسوف يتم جلب المفتاح العام الخاص به من مسار الخادم[^3].
بعد ذلك إذا لم يكن لـalice إتصال [Websocket] سابق مع خادم bob، سوف يقوم بإرسال طلب دردشة
ليتم ترقية الإتصال إلى [Websocket]، ونفس المسئلة مع bob إذا اراد التواصل مع
alice سوف يقوم بإرسال طلب دردشة ويتم ترقية الإتصال او إعلامه بوجود إتصال
[Websocket] مفتوح.
#### إذا كان alice في قائمة bob البيضاء
سوف يقوم الخادم بترقية الإتصال إلى [Websocket] او إذا كان alice متصل معه من قبل،
سوف يقوم بإرجاع 400 ويخبر alice بالتواصل معه عبر ال [Websocket].
#### إذا كان alice في قائمة bob السوداء او كان هو او خادمه في قائمة الخادم السوداء
سوف يرجع الخادم 403 مع توضيح السبب.
#### أساسيات
- يجب على alice فتح إتصال [Websocket] مع جميع الخوادم التي يريد التواصل مع
افرادها.
- لايتم تخزين الرسائل التي يستقبلها الخادم بشكل دائم، يتم تخزينها فقط إذا لم يكن
bob متصل بالخادم، ويتم مسحها بعد إرسالها إلى bob.
- الرسائل والملفات بين الطرفين تكون مشفرة وتكون موقعة للخادم المراد التواصل مع
افراده.
{{ hr(data_content="وصلات") }}
[^1]: طالما انك عضو في الخادم، سوف يعتقد الخادم دائماً انك في إتصال [Websocket] معه، ولن يقوم بترقية أي إتصال إلى [Websocket]
[^2]: يتم إضافة العنوان الخاص بـbob و الخادم الخاص به في جدول طلبات الدردشة للتاكد من عدم إستقبال إشعارات قبول/رفض من خوادم مزيفة هدفها الإزعاج.
[^3]: للتاكد من انه الخادم فعلاً، لن يتم طلب منه المفتاح العام بشكل مباشر، بل سوف يتم جلبه من مسار الخاص به، وهو `/.well-known/oxidetalis/public`
[Websocket]: https://en.wikipedia.org/wiki/WebSocket
[مفتاح التشفير المشترك]: #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