كيفية بناء مكتبة تشفير متماثل مع جافا سكريبت و WebAssembly

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

"العالم يعمل على الرموز والأصفار ، جون. من نظام الأمان بقيمة مليون جنيه في البنك إلى جهاز Pin ، أخذت استثناءً منه. تشفير يسكن كل لحظة اليقظة "- شيرلوك هولمز

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

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

البحث عن الكأس المقدسة في مكتبات تشفير الويب

هنا في Cubbit لدينا حلم اللامركزية في البنية التحتية للبيانات ، وللقيام بذلك ، نحن بحاجة إلى تطبيق ويب يستطيع المستخدمون من خلاله حفظ ملفاتهم والوصول إليها من أي مكان في العالم. لهذا السبب بدأنا بحثنا عن مكتبات تشفير الويب المتاحة التي تعمل على المتصفح. على الرغم من أن الكثير منهم ظهر على مر السنين ، إلا أن أحداً لم يناسب احتياجاتنا فيما يتعلق بسرعة التشفير وسهولة الاستخدام لثلاثة أسباب رئيسية:

  • واجهات برمجة التطبيقات معقدة للغاية.
  • أداء ضعيف عند تشفير / فك تشفير الملفات (التشفير هو تطبيق مكثف من الناحية الحسابية وعادة ما يكون أداءه ضعيفًا في Javascript).
  • عدم وجود معايير نحتاجها لبناء بنية التشفير.

السبب # 0: مكتبات تشفير الويب غير متقنة

دعنا نستكشف هذه الأسباب بعمق.

أولاً ، نفترض أن OpenSSL هو معيار التشفير الفعلي ، بالنظر إلى أن العديد من الشركات تعتمده في سير العمل الأمني ​​الخاص بها. ومع ذلك ، نظرًا لأنه مكتوب بلغة C ، فإنه يحمل توقيعات فظيعة لواجهة برمجة التطبيقات ولا يزال غير موثق بشكل سيء ، مما يجعل منحنى التعلم أكثر حدة من التقنيات الأخرى. لذلك ، تسعى جميع مكتبات التشفير الناشئة إلى الحفاظ على قاعدة الكود الخاصة بها متوافقة مع OpenSSL قدر الإمكان ، نتيجة عدم تبسيط واجهة برمجة التطبيقات الخاصة بها للمطورين الجدد.

السبب رقم 1: التشفير على الويب غير آمن وبطيء

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

السبب رقم 2: قلة الدعم لـ ECC والمعايير الأخرى في العديد من المكتبات

أخيرًا ، لا تتضمن أي من المكتبات التي وجدناها جميع الخوارزميات القياسية التي نحتاج إلى تنفيذها ؛ على سبيل المثال ، لا شيء يدعم تشفير Elliptic-curve. ما هو أكثر من ذلك ، كل واحد منهم مناسب لبروتوكول تشفير معين أكثر من غيره ، ونحن نستفيد من عدد كبير من بروتوكولات التشفير.

لنبدأ

للتغلب على كل هذه المشاكل ، بدأنا في تطوير مكتبة التشفير لدينا في المنزل. لقد قمنا بتصميمها مع وضع ثلاثة أهداف واضحة في الاعتبار:

  1. التماثل
  2. سرعة تشفير الملف
  3. لا تقم أبدًا بإعادة اختراع العجلة إلا إذا كانت مربعة

يشير التماثل إلى مفهوم الكود العالمي ، أي الكتابة مرة واحدة ، يعمل في أي مكان.

تعني سرعة تشفير الملفات أن مكتبة التشفير لدينا يجب أن تكون سريعة في تشفير الملفات من أجل تقديم أفضل تجربة مستخدم ممكنة.

المبدأ الثالث هو النهج الذي نتبعه في الكود. وبعبارة أخرى ، بما أن الوقت هو المورد الأكثر قيمة في الكون ، فلا ينبغي أن يضيع أبدًا إذا كانت هناك حلول فعالة بالفعل. لا ينبغي إهدار أي منهما إذا لم يحاولوا إخراج الدم من الحجر. بناء حل جديد ، في مثل هذه الحالة ، هو دائمًا أفضل وأسرع الطرق.

على الويب

قضينا ساعات وساعات (إعادة) البحث في مكتبة مع الميزات والعروض التي نحتاجها دون أي نجاح. لذلك قررنا تجربة مسار الترجمة.

ماذا؟ ترجمة جافا سكريبت؟ كيف؟

شكرا على المخطوطات!

Emscripten هي تقنية جديدة تمامًا مع بعض الإدعاءات المثيرة للاهتمام للغاية ، نقلاً عن:

Emscripten عبارة عن سلسلة أدوات للتجميع إلى asm.js و WebAssembly ، تم إنشاؤها باستخدام LLVM ، والتي تتيح لك تشغيل C و C ++ على الويب بسرعة قريبة من دون ملحقات إضافية.

يستحق المحاولة ، ألا تعتقد ذلك؟

بدأنا من تنفيذ ED25519. يحتوي Emscripten على مكتبة خاصة به يجب تضمينها في الارتباطات.

وهناك اعتبار مهم يدور حول إدارة الذاكرة. في عالم Javascript ، اعتدنا ، كمطورين ، على الإيمان بأكبر جامع للقمامة يسمح لنا ببساطة بتجاهل كل الجوانب المتعلقة بالذاكرة. ولكن من أجل استخدام رمز Emscripten بنجاح ، فإننا مضطرون للعناية بالذاكرة المشتركة مع malloc ومجاني.

const heap_seed = em_array_malloc ((النفس كأي). لغز ، البذور) ؛
ED25519.create_keypair (heap_seed.byteOffset، seed.length)؛
em_array_free ((self as any). enigma، heap_seed)؛

مع نتيجة العمل هذه في الحقيبة ، انتقلنا إلى موضوع آخر: وضع تدفق AES. لم نجد أداءً جيدًا للغاية خلال بحثنا ولذا اخترنا تجربة OpenSSL. هذا يعني أن قاعدة الشفرة كان لابد من تجميعها مع Emscripten ؛ لسوء الحظ ، على الرغم من عدم وجود وثائق. حتى بعد بعض الأوقات وجدنا تجريبيا الإجراء لتحقيق النتائج ،

بمعنى ، الخطوات التالية:

  1. استبعاد جميع الأصفار التي ليست مطلوبة بشكل صارم
  2. عبر الترجمة
  3. ربط مع التعليمات البرمجية الخاصة بك

و...

على Node.js

إن Typescript ، وهي مجموعة مكتوبة من Javascript بواسطة Microsoft ، هي الموقد الخاص بالمجموعة التقنية هنا في Cubbit. وبالتالي كان من الطبيعي بناء مكدس التشفير في Typescript أيضًا. ومع ذلك ، تتوافق العروض والتشفير تمامًا مع اللغات الأصلية مثل C ++ ، بينما ، كما قلنا ، فإن Typescript غير مناسب للمهمة.

لذلك قررنا استخدام Node.js كلغة أساسية ، لأنها تتيح لنا الاستفادة من الوظائف الإضافية لدمج الكود الأصلي بسهولة. في هذا الصدد ، يعد N-API أداة رائعة من قِبل فريق Node.js ، وهو واجهة برمجة تطبيقات مستقرة عبر إصدارات Node.js: ما عليك إلا الإنشاء مرة واحدة وسيتم تشغيلها على كل إصدار رئيسي لاحق دون إعادة تجميع.

ما هو أكثر من ذلك ، إنه سهل الاستخدام أيضًا:

قم فقط بلف وتصدير الكائنات والوظائف التي تريد مشاركتها مع عالم Javascript ودع المترجم يقوم بالعمل الشاق من أجلك.

لغز ، مكتبة تشفير عالمي سريع

وهكذا ، بعد بضعة أشهر من البحث والترميز ، ظهرت Enigma في الحياة.

Enigma هي مكتبة تشفير مصممة للعمل بكفاءة على المتصفحات من خلال الاستفادة من التقنيات الرائعة مثل WebCrypto و WebAssembly. هدفنا هو توفير خوارزميات التشفير القياسية الرئيسية بالإضافة إلى مجموعة من الأدوات المساعدة لتبسيط الاستخدام للمطور "القياسي".

لتسهيل اعتماده ، جعلنا Enigma isomorphic ، أي متوافق مع كل من Node.js والويب لجعله قابلاً للتشغيل دون تغيير سطر واحد من الكود. يجب أن تكون الشفرة عالمية ، وفقًا لشعار WORA ، أي "الكتابة مرة واحدة ، ركض في أي مكان".

كيفية استخدامها

الآن يمكنك القول: "حسناً ، بارد! ولكن كيف يمكنني استخدامه؟ "بادئ ذي بدء ، تحتاج إلى تثبيته. كونها Enigma وحدة NPM ، يمكنك ببساطة كتابة الأمر التالي في الجهاز:

تثبيت npm @ cubbit / لغز

أو إذا كنت تفضل الغزل:

إضافة غزل @ cubbit / لغز

الآن تم تثبيت Enigma وجزء من تبعياتك.

حان الوقت للبدء في استخدامه بعد ذلك!

دعنا نقول أنك تريد تشفير رسالة مع AES-256 (فقط لبدء سهلة). ها نحن ذا. أول شيء أولاً ، نحن بحاجة إلى تهيئة لغز. نظرًا لأنه يستخدم الكود الأصلي لتعزيز الأداء ، نحتاج إلى انتظار المتصفح لتحميله قبل أن نتمكن من البدء في استخدام المكتبة.

ملاحظة: يتم كتابة التعليمات البرمجية التالية في Typescript ، ولكن يمكنك أيضًا كتابة Javascript pure بالطبع!

هدفنا هنا هو تشفير سلسلة نصية بسيطة.

احذر أنه نظرًا لأن AES256 عبارة عن خوارزمية تشفير متماثل ، نحتاج إلى استخدام نفس المفتاح الذي استخدمناه لتشفير الرسالة لفك تشفيرها مرة أخرى. شيء مثل:

لنفترض الآن أننا نريد تشفير ملف قبل إرساله إلى الشبكة. حسنًا ، تحتاج إلى معرفة أن معظم المتصفحات الحالية بها قيود تتعلق بالحد الأقصى للذاكرة التي يمكن تخصيصها بواسطة صفحة ويب. على سبيل المثال ، يمكن لـ Google Chrome تخصيص 1.5 جيجابايت بحد أقصى من ذاكرة الوصول العشوائي. أيضًا ، تعمل خوارزميات تشفير البلوك عمومًا بشكل أفضل مع قطع صغيرة من البيانات. وبالتالي ، لا ينصح بتشفير الملف بالكامل ولكن تشفيره تدريجياً. في هذا الحقل ، يوفر Node.js أداة سهلة الاستخدام وذات تصميم جيد للتعامل مع تدفقات البيانات: كائن الدفق. لذلك أخذنا الإلهام منه لتوفير API سلس.

تتمثل قوة هذا النوع من بناء الجملة في أنه يمكنك إرفاق الأنابيب معًا لإرسال الملف المشفر تلقائيًا عبر الشبكة أثناء تشفيره. سحر! :)

file_stream.pipe (aes_stream) .pipe (مقبس)؛

يوفر Enigma الكثير من الميزات ، لذلك إذا كنت مهتمًا فلا تتردد في زيارة مستودعها والمساهمة فيها.

النتائج

نحن ندير مجموعة من المعايير للمقارنة بين Enigma والمكتبات الأخرى الموجودة على الويب. إليك النتائج (Chrome 72 في I7-7820HQ - الأقل أفضل):

تشفير AES. الاقل هو الافضل

كما ترى ، فإن Enigma تعمل بشكل أفضل عند تشفير الملفات ومعالجتها بدلاً من تشفير السلاسل الصغيرة. في الواقع ، نحن نقدم مقدارًا صغيرًا من الحمل عن طريق تحميل ثنائيات تجميع الويب ، لكن الأمر يتغير عندما نحتاج إلى تشفير كمية أكبر من البيانات مثل الملفات.

رؤيتنا لمستقبل لغز

هدفنا هو إنشاء مكتبة تشفير قوية وبسيطة.

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

ملاحظة. تم تطوير Enigma كطبقة تشفير لـ Cubbit ، التي تبدأ الآن في السحابة الموزعة. إذا كنت تريد معرفة المزيد ، تحقق من ذلك هنا.