الرسائل الشخصية المشفرة

نود تكليفنا بتطوير إضافة (Plugin) تتيح المراسلة الخاصة المشفرة بين المستخدمين النهائيين.

:mega: هذه الإضافة موجودة الآن ويتم دعمها رسميًا، راجع Discourse Encrypt (deprecated)

في الوقت الحالي، توجد وسائل قليلة جدًا عبر الإنترنت للتواصل الآمن والخاص طويل الأمد. الأدوات الحالية غالبًا ما تكون معقدة للغاية وتتطلب مهارات تقنية متقدمة للاستخدام. ونتيجة لذلك، يتم تنفيذ معظم التواصل “الخاص” بشكل “قصير” عبر تطبيقات مثل Telegram أو Skype أو WhatsApp. بالإضافة إلى ذلك، فإن هذا النمط من التواصل الجماعي غير قابل للتدقيق بشكل صحيح لأنه يعتمد على أدوات ذات مصدر مغلق وبروتوكولات مغلقة المصدر في كثير من الأحيان.

نود بناء حل سهل الاستخدام وقابل للتدقيق للمراسلة المشفرة ضمن إضافة مخصصة لمنصة Discourse.

لتحقيق ذلك، نود الاعتماد على المبادئ التالية:

  1. بناء الحل على Web Crypto API.

  2. قيام الخادم بتخزين مفتاح خاص مشفر و مفتاح عام لكل مستخدم.

  3. قيام الخادم بتخزين مفتاح محادثة مشفر لكل مشارك في الرسائل الخاصة (مُشفّر باستخدام المفتاح الخاص للمستخدم النهائي).

  4. تخزين جميع تنسيقات Markdown والعناوين في شكلها الخام المشفر لكل رسالة (مُشفّر باستخدام مفتاح المحادثة).

  5. القبول بالقيود التالية: معرفة الخادم لمن تحدث مع من ومتى (نحن نحمي فقط “المحتوى”). والقبول بأن وظيفة البحث لن تعمل مع هذا المحتوى.

تجربة المستخدم المقترحة

تنتقل Jane إلى صفحتها الشخصية وتضغط على زر “تمكين المراسلة المشفرة”. بمجرد الضغط، يُطلب منها إدخال سر، مع توضيح واجهة المستخدم بوضوح أنه في حال نسيان هذا السر، لن تتمكن أبدًا من الوصول إلى رسائلها المشفرة مرة أخرى.

بمجرد تمكين المراسلة المشفرة، سيظهر عنصر جديد [ ] في واجهة إنشاء الرسالة مع النص [ ] encrypt message. سيكون هذا العنصر قابلاً للنقر فقط إذا كان جميع المستلمين قد قاموا بتمكين “المراسلة المشفرة”. إذا لم يكن لدى بعض المستخدمين مفاتيح عامة، وعند محاولة النقر عليه، ستظهر الرسالة: “عذرًا، لكن بعض المشاركين لم يفعّلوا المراسلة المشفرة”.

تقرر Jane أنها ترغب في التحدث بشكل خاص مع Pete، فتضيفه إلى قائمة المشاركين وتضغط على encrypt message ثم ترسل رسالة إلى Pete.

يتلقى Pete إشعارًا يفيد بأن Jane أرسلت له رسالة مشفرة. لا يوجد عنوان، فقط معلومات تفيد بوجود رسالة مشفرة وروابط للرسالة (في كل من الإشعارات البريدية والإشعارات على الويب).

إذا كان Pete يستخدم الجهاز الأصلي الذي تم فيه تمكين المراسلة المشفرة، فقد تم إدخال عبارة المرور السرية مسبقًا وتم تخزين بيانات الاعتماد بالفعل في قاعدة بيانات Index. أما إذا كان Pete يستخدم جهازًا جديدًا، فسيُطلب منه إدخال عبارة المرور السرية لتفعيل المراسلة المشفرة.

تعرض واجهة المستخدم بشكل واضح طبقة تراكب أو تلميح مرئي لإظهار أن الرسالة مشفرة.

بمجرد بدء التواصل بين Jane و Pete، يمكن لأي منهما دعوة أشخاص جدد إلى المحادثة بشرط أن يمتلكوا مفاتيح عامة.

يمكن لـ Pete أو Jane تغيير عبارة المرور السرية في أي وقت يرغبون فيه؛ وفي حال فعلوا ذلك، سيتم إعادة تشفير المفتاح الخاص باستخدام العبارة الجديدة وإرسالها إلى الخادم. (في الإصدار V1، لن نسمح بتغيير المفتاح الخاص الفعلي، بل فقط عبارة المرور).

التفاصيل التقنية

في أي وقت، لن يتم إرسال أي محادثات خاصة غير مشفرة أو بيانات اعتماد خاصة إلى الخادم. الثقة الوحيدة الممنوحة للخادم هي أن أحدًا لم يتلاعب بحزمة JavaScript المرسلة إلى العميل.

سيتم توليد أزواج المفاتيح الخاصة والعامة بنسبة 100% على جانب العميل، ثم سيتم تشفير المفتاح الخاص باستخدام تشفير AES المتماثل قبل تسليمه إلى الخادم لحفظه بأمان. سنقوم بتمديد عبارة المرور باستخدام ملح (salt) يتم توليده عشوائيًا ويتم تخزينه على الخادم. سيتم تنفيذ تمديد المفاتيح على جانب العميل باستخدام PBKDF2 (متوفر في Web Crypto API). سيتم تخزين زوج المفتاح الخاص/العام على جانب العميل في IndexDB باستخدام كائن CryptoKey غير قابل للتصدير. سيتم إزالة بيانات CryptoKey القابلة للتصدير من الذاكرة في أسرع وقت ممكن.

سيتم تخزين المفتاح الخاص المشفر والمفتاح العام في حقول مخصصة للمستخدم. فقط current_user مسموح له بقراءة/كتابة المفتاح الخاص المشفر، بينما يُسمح لجميع المستخدمين المسجلين بقراءة المفاتيح العامة لجميع المستخدمين.

سيتم توليد مفاتيح المحادثة على جانب العميل عند بدء المحادثة أو عند الدعوة، وسيتم تشفيرها باستخدام جميع المفاتيح العامة المشاركة في المحادثة. سيتم تخزين هذه البيانات في جدول مخصص (user_id, topic_id, encrypted_conversation_key)، ويمكن لأي مستخدم في المحادثة إنشاء هذا السطر، لكن فقط current_user == user_id مسموح له بقراءته.

سيتم اتخاذ عناية خاصة لعدم تسريب أي بيانات غير مشفرة إلى الخادم، بما في ذلك ضمان عدم تخزين المسودات بشكل غير مشفر.

لتجنب فئة كبيرة من الأخطاء، سيتم استخدام عناصر DOM جديدة (مع معرفات جديدة) لمحرر ومعاينة المؤلّف (Composer). لن تحتوي .d-editor-input الحالية إلا على كتل مشفرة، وسيتم تعطيل المعاينة التقليدية (مما يعني وجود مجالين للنص: مشفر وغير مشفر). سيتم تأخير التشفير بشكل كبير (debounced) لتجنب فئة من مشاكل الأداء.

بالنسبة للإصدار V1 (ونطاق هذا العنصر)، نحن سعداء بتجاهل ميزات معينة، بما في ذلك دعم رفع الملفات، وعرض الروابط (oneboxing) للمحتوى المشفر، وحالات الحافة المعقدة الأخرى.

نحن موافقون على فك التشفير/التحضير وعرض HTML عبر قائمة بيضاء (whitelister) عند عرض هذا المحتوى الخاص.

متطلبات التوثيق

قبل التنفيذ، سيتم إنشاء مواصفات مفصلة للغاية تتضمن نماذج ويب (web mockups) والأهم من ذلك نظرة عامة مفصلة على الأمان.

متطلبات الاختبار

يجب أن تتضمن هذه الإضافة مجموعة شاملة من اختبارات الوحدة والاختبارات التكاملية على جانب العميل والخادم. إذا تقبلتم هذا المشروع، فاكتبوا الاختبارات مبكرًا، ولا تنتظروا حتى ينتهي المشروع لتضمين الاختبارات لاحقًا.

المخاوف

العديد من المخاوف المذكورة في: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/ لم تعد ذات صلة نظرًا لـ Web Crypto API (توليد البايتات العشوائية الحقيقية، تخزين المفاتيح الخاصة، والقائمة تطول). المتجه الرئيسي الوحيد المتبقي هو إرسال الخادم لـ JavaScript خبيث للعميل. على المدى القصير، من المتوقع أن يثق المستخدمون بالخادم بنفس طريقة ثقتهم بـ 1password و LastPass وواجهات أمان الويب الأخرى. على المدى الطويل (الإصدار v3/v4 - العام المقبل أو بعده)، يمكننا النظر في إصدار امتداد للمتصفح يضع قفلًا على المواقع حيث جميع تجزئات استقرار حزم JavaScript معروفة جيدًا.

لا يزال Web Crypto API حديثًا نسبيًا لكنه مدعوم على نطاق واسع، ويجب أن تعمل الإضافة عبر جميع المتصفحات المدعومة لدينا.

نماذج أولية تقريبية بسيطة

* عند بدء رسالة، يمكن للمستخدم اختيار تشفير المحادثة، وسيتم عرض تحذير إذا كان أي من المشاركين يفتقر إلى مفاتيح عامة.

* يمكن للمستخدمين تمكين الرسائل المشفرة بالضغط على هذا الزر والعمل من خلال واجهة مستخدم تولد زوج المفاتيح.

إذا تم تمكين الرسائل المشفرة، فيجب أن تظهر ببساطة عبارة “لقد قمت بتمكين المراسلة المشفرة”.

* نوع من الأيقونة أو الطبقة التراكبية سيوضح أن الرسالة مشفرة.

الميزانية

هذا مشروع معقد للغاية يتطلب تكاملًا عميقًا ومراجعة دقيقة. نتوقع أن يكون الاختبار ممتازًا للغاية (باستخدام اختبارات على جانب العميل والخادم). ميزانيتنا الحالية للنموذج الأولي القابل للتطبيق (MVP) هي 10,000 دولار أمريكي.

34 إعجابًا

If the implementation is open source with the rest of discourse I could probably get our lot to throw in £1000 or thereabouts to your budget.

12 إعجابًا

Cool, yes, this will be open source under the MIT license, with an additional full license assignment to Discourse.

Regarding browser support, we want to make sure it works on every platform: Chrome + Safari is a minimum (so it works on iPhone / Android / Desktop), but my preference is that we hit Firefox as well. Edge is in the nice-to-have and IE11 is in the I don’t really care department, especially if it is missing crypto stuff.

7 إعجابات

I’ll get the ball rolling now then, couple of questions though.

  • Is it plausible for this project to accommodate group encrypted chat, even if up to a point?
  • Would “Force every PM encrypted” option be on the cards?

Not for the initial version. Maybe for version 2 or 3, a PM between 20 users should absolutely work for V1.

Yes this is fine as an option. Basically would disallow PM to users that don’t have encryption enabled (but still allow admins to PM them unconditionally). We would need to think this through, but I don’t want to add this to the scope of the spec quite yet.

4 إعجابات

Thanks i’m obligated to sample an arbitrarily acceptable number of our PMs and reading people’s intimate conversations if only skimming is not only something I don’t want to do it takes time I haven’t got.

a PM between 20 users should absolutely work for V1.

That’s group chat in my context (Forgot where I am :slight_smile: ) and will be fine. I’d expect strong support from our lot.

Keep in mind with this plugin it is technically impossible for you to read members private conversations provided they have a reasonably strong passphrase.

They are encrypted in the database and only decrypted client side. You would have to add a code exploit to your server for you to be able to swing reading encrypted PMs. Longer term (in v3 / v4) this code exploit would result in a giant red flag on the screen for people who install the “confirm my encrypted discourse conversations have not been exploited” browser plugin.

إعجاب واحد (1)

Yes that’s ideal, i’m obligated to look at them because I can look at them.

إعجاب واحد (1)

This is fascinating. It would be refreshing to do something really technically challenging. But, at least for me, the cost / benefit of taking the time to master (assuming, optimistically, that I could) all the relevant pieces doesn’t make sense right now.

That said, I just did a little reading on cryptography and have a few questions / thoughts:

  • Am I correct in understanding that you would need to generate a new conversation key every time you added or removed a member from the PM?

  • You would need some protection or warning against using other plugins as well. I can imagine a scenario in which you install this plugin, then someone writes another plugin that exposes or stores the entered text in some way before it is encrypted.

  • Wouldn’t you need to also only allow this feature on sites that force https? From the article you linked.

    You can’t simply send a single Javascript file over SSL/TLS. You have to send all the page content over SSL/TLS. Otherwise, attackers will hijack the crypto code using the least-secure connection that builds the page.

    Otherwise, in addition to the issue of the server sending malicious javascript you could also have the issue of ‘hijacking’.

  • Searchable semantic encryption is possible (by no means do I mean to imply that I understand the description in that paper). I assume you’re excluding it as the cost / benefit isn’t worth it, at least for the MVP.

  • Why not use the Signal Protocol? (javascript library).

ps. for whoever takes this on

15 إعجابًا

Great questions:

The encrypted conversation key does not need to change on add. All members of the conversation have a copy of the decrypted conversation key. So to add a member you would encrypt this conversation key using the “invitee” public key and teach the server about that.

Technically it would be correct to amend the conversation key if you are removing members from a conversation, but we can wait on v2 for that. Cause it would be a very expensive operation from the client side, entire conversation would have to be re-encrypted, or complex multi conversation key systems need to be built.

Yes, the long term V3 / V4 goal here is to have a whitelist of JS integrity hashes stored in a browser extension. That is really the only way a client can know 100% that the “server is not messing with stuff”. However for V1 we trust the server and server operator not to be malicious.

Yes, if SSL is off all bets are off. We do not expect this feature to even remotely work if SSL is off.

Yes search is off the cards for now cause it is just going to be too hard to get right for the MVP.

Maybe, not against leaning on existing standards, but I suspect the Discourse integration work here is going to be enormous regardless.

11 إعجابًا

Congrats! @dan will be taking this project! We will update here as we make progress!

29 إعجابًا

Signed up to comment on this because I’m curious on the implementation as a developer myself.

I’m personally no cryptography pro, so forgive me if these are silly questions.

Would it not be viable to encrypt the message on the server-side using the public keys of people currently in the conversation, in this case?
Essentially I guess this would lead to a double layer of encryption - the data is encrypted client-side for true E2E encryption as described with the conversation key, and then encrypted on the way out by the server to only the public keys active in the conversation. At that point, removing a member from the conversation would mean any future messages wouldn’t be decryptable by them.

I’m not too sure on the security implications of nested encryption like that, however.

My second question is how well this would work cross-device? Does it require a private key on the device, or is that handled by the passphrase encrypted private key being stored?

4 إعجابات

Interesting idea the “double” encrypting. It does though add more responsibility to the server and a lot of this is about removing responsibility from the server so I am not sure it is a great idea protocol wise.

Cross device is handled by retrieving the encrypted private key from the server and decrypting using the key phrase.

Longer term we can introduce more “security” modes with a super strict one when say the server never even stores the private key encrypted (like say 1 password), but short term this is out of scope.

10 إعجابات

Welcome! :discourse: :heart:

Those are not silly questions at all! If you want to dig deeper, I highly recommend Dan Boneh’s courses on Coursera.org.

This depends a lot on the particularities of the system you use. Check out double DES (i.e. vulnerable to meet-in-the-middle) and triple DES.

Let’s say Eve used to be a part of a group discussion with Alice and Bob. Even if Alice or Bob kick Eve out she will still have the conversation key and theoretically, she could intercept the messages before they get to the server and decrypt them.

If the conversation key gets compromised, the safest approach is to revoke it and use a new one for new messages. Ideally, you’d probably want to re-encrypt the old messages.

7 إعجابات

That makes sense to me, thanks for the explanation! (@sam too)

So adding or removing users from the conversation would involve decrypting everything client-side, revoking the conversation key and generating a new one, then re-encrypting messages before sending to the server?
Plus encrypting the new conversation key with the user passphrase and storing it.

إعجاب واحد (1)

I’ve been talking to my wife about this feature. While this may raise an eyebrow at mealtime conversation in our family, she’s a security engineer for Thales eSecurity.

She’s of the opinion that the Specification needs some use cases with bad actors and how the system should respond. For example: Malicious Admin, Malicious SysOps.

This would then give rise to a security statement that could be presented to users of the system.

9 إعجابات

I would love it if your wife or anyone interested in this problem at her work would pop by and give feedback.

@dan has made tremendous progress here, I am testing v1 with him this week.

To answer your specific question of bad sys admins. Overall if you can commandeer the web site and deliver malicious payloads our current v1 can not offer privacy. This is by design.

Our plans for v3/v4 is to have a browser plugin that validates every single JavaScript file on the page matches a particular hash in the whitelist. That way if you would be running this plugin you would be able to disallow unrecognized JS payloads.

Overall the underlying design means that passwords can not be fished out after the fact even if the server is malicious, but it can trick the client if it wishes to decrypt arbitrary payloads. Native browser plugins or a more refined web standard longer term will help eliminate this

14 إعجابًا

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.