ملاحظة
النشر والاختبار على الشبكة قيد التقدم. خاضع لمراجعات طفيفة. انظر SPEC للمواصفات الرسمية.
السمات التالية لم تُنفَّذ اعتبارًا من الإصدار 0.9.46:
- كتل MessageNumbers وOptions وTermination
- استجابات طبقة البروتوكول
- مفتاح ثابت صفري
- البث المتعدد (Multicast)
نظرة عامة
هذا اقتراح لنوع تشفير جديد من طرف إلى طرف منذ بداية I2P، ليحل محل ElGamal/AES+SessionTags Elg-AES .
يعتمد على أعمال سابقة كالتالي:
- مواصفات الهياكل المشتركة Common Structures
- مواصفات I2NP متضمنة LS2
- ElGamal/AES+Session Tags Elg-AES
- http://zzz.i2p/topics/1768 نظرة عامة على التشفير غير المتماثل الجديد
- نظرة عامة على التشفير منخفض المستوى CRYPTO-ELG
- ECIES http://zzz.i2p/topics/2418
- NTCP2 اقتراح 111
- 123 إدخالات جديدة في netDB
- 142 قالب تشفير جديد
- بروتوكول Noise
- خوارزمية الترس المزدوج Signal (double ratchet)
الهدف هو دعم التشفير الجديد للتواصل من طرف إلى طرف، من وجهة إلى وجهة.
سيستخدم التصميم عملية تبادل يد (handshake) باستخدام Noise ومرحلة بيانات تدمج ترس الإشارة المزدوج (Signal’s double ratchet).
جميع الإشارات إلى Signal وNoise في هذا الاقتراح هي فقط لمعلومات خلفية. لا يشترط معرفة بروتوكولات Signal وNoise لفهم أو تنفيذ هذا الاقتراح.
الاستخدامات الحالية لـ ElGamal
كمراجعة، يمكن العثور على مفاتيح عامة لـ ElGamal بطول 256 بايت في هياكل البيانات التالية. راجع مواصفات الهياكل المشتركة.
في هوية الموجه (Router Identity) هذا هو مفتاح التشفير للموجه.
في الوجهة (Destination) استُخدم المفتاح العام للوجهة للتشفير القديم من i2cp إلى i2cp والذي تم تعطيله في الإصدار 0.6، وهو حاليًا غير مستخدم باستثناء استخدامه كـ IV لتشفير LeaseSet، وهو ما تم إهماله. يتم استخدام المفتاح العام في LeaseSet بدلاً من ذلك.
في LeaseSet هذا هو مفتاح التشفير للوجهة.
في LS2 هذا هو مفتاح التشفير للوجهة.
أنواع التشفير في شهادات المفاتيح (EncTypes in Key Certs)
كمراجعة، أضفنا دعمًا لأنواع التشفير عندما أضفنا دعمًا لأنواع التوقيع. حقل نوع التشفير يكون دائمًا صفرًا، سواء في الوجهات أو في هويات الموجهات. ما إذا كان سيتم تغيير ذلك أم لا لم يُقرّر بعد. راجع مواصفات الهياكل المشتركة Common Structures .
استخدامات التشفير غير المتماثل
كمراجعة، نستخدم ElGamal في:
رسائل بناء النفق (key is in RouterIdentity) الاستبدال غير مغطى في هذا الاقتراح. انظر الاقتراح 152 Proposal 152 .
تشفير الموجه إلى الموجه للـ netdb ورسائل I2NP الأخرى (Key is in RouterIdentity) يعتمد على هذا الاقتراح. يتطلب اقتراحًا لـ 1) أيضًا، أو وضع المفتاح في خيارات RI.
التشفير من طرف إلى طرف للعميل باستخدام ElGamal+AES/SessionTag (key is in LeaseSet، المفتاح في الوجهة غير مستخدم) الاستبدال مغطى في هذا الاقتراح.
تبادل DH مؤقت لـ NTCP1 وSSU الاستبدال غير مغطى في هذا الاقتراح. انظر الاقتراح 111 لـ NTCP2. لا يوجد حاليًا اقتراح لـ SSU2.
الأهداف
- التوافق العكسي
- يتطلب ويعتمد على LS2 (الاقتراح 123)
- الاستفادة من التشفير الجديد أو البدائل المضافة لـ NTCP2 (الاقتراح 111)
- لا يتطلب تشفيرًا أو بدائل جديدة للدعم
- الحفاظ على فصل التشفير عن التوقيع؛ دعم جميع الإصدارات الحالية والمستقبلية
- تمكين تشفير جديد للوجهات
- تمكين تشفير جديد للموجهات، ولكن فقط لرسائل الثوم (garlic) - بناء النفق سيكون اقتراحًا منفصلًا
- عدم إتلاف أي شيء يعتمد على تجزئة الوجهات الثنائية بطول 32 بايت، مثل bittorrent
- الحفاظ على توصيل الرسائل بدون انتظار (0-RTT) باستخدام DH مؤقت-ثابت
- عدم اشتراط تخزين/تجميع الرسائل في طبقة البروتوكول هذه؛ الاستمرار في دعم توصيل الرسائل غير المحدود في كلا الاتجاهين دون انتظار استجابة
- الترقية إلى DH مؤقت-مؤقت بعد 1 RTT
- الحفاظ على معالجة الرسائل الواردة خارج الترتيب
- الحفاظ على أمان 256 بت
- إضافة السرية الأمامية (forward secrecy)
- إضافة المصادقة (AEAD)
- أكثر كفاءة بكثير من حيث وحدة المعالجة المركزية (CPU) مقارنة بـ ElGamal
- عدم الاعتماد على Java jbigi لجعل DH فعالًا
- تقليل عمليات DH
- أكثر كفاءة بكثير من حيث عرض النطاق الترددي مقارنة بـ ElGamal (كتلة ElGamal بطول 514 بايت)
- دعم التشفير الجديد والقديم على نفس النفق إذا رُغب في ذلك
- تمكين المستلم من التمييز بكفاءة بين التشفير الجديد والقديم الوارد عبر نفس النفق
- عدم تمكين الآخرين من التمييز بين التشفير الجديد والقديم أو المستقبلي
- إزالة تصنيف طول الجلسة الجديد مقابل الحالي (دعم التعبئة)
- لا تتطلب رسائل I2NP جديدة
- استبدال مجموع التحقق SHA-256 في حمولة AES بـ AEAD
- دعم ربط جلسات الإرسال والاستقبال بحيث يمكن حدوث الإقرار ضمن البروتوكول، وليس فقط خارج النطاق. سيسمح ذلك أيضًا بأن تكون الردود ذات سرية أمامية فورًا.
- تمكين التشفير من طرف إلى طرف لرسائل معينة (مخازن RouterInfo) لا نقوم بها حاليًا بسبب تكلفة وحدة المعالجة المركزية.
- عدم تغيير رسالة I2NP Garlic Message أو تنسيق تعليمات توصيل رسالة Garlic Message.
- إزالة الحقول غير المستخدمة أو الزائدة في تنسيقات Garlic Clove Set وClove.
إلغاء العديد من مشكلات session tags، بما في ذلك:
- عدم القدرة على استخدام AES حتى أول رد
- عدم الموثوقية والتوقفات إذا افترض تسليم العلامات
- عدم الكفاءة من حيث عرض النطاق الترددي، خاصة في التسليم الأولي
- عدم الكفاءة الكبيرة من حيث المساحة لتخزين العلامات
- عرض النطاق الترددي الكبير المطلوب لتسليم العلامات
- تعقيد شديد، صعب التنفيذ
- صعوبة الضبط لحالات استخدام مختلفة (التدفق مقابل datagrams، الخادم مقابل العميل، عرض النطاق العالي مقابل المنخفض)
- نقاط ضعف استنزاف الذاكرة بسبب تسليم العلامات
غير الأهداف / خارج النطاق
- تغييرات تنسيق LS2 (تم الانتهاء من الاقتراح 123)
- خوارزمية جديدة لتدوير DHT أو إنشاء عشوائي مشترك
- تشفير جديد لبناء النفق. انظر الاقتراح 152 Proposal 152 .
- تشفير جديد لتشفير طبقة النفق. انظر الاقتراح 153 Proposal 153 .
- طرق تشفير، إرسال، واستقبال رسائل I2NP DLM / DSM / DSRM. لن يتم تغييرها.
- لا يدعم اتصال من LS1 إلى LS2 أو من ElGamal/AES إلى هذا الاقتراح. هذا الاقتراح هو بروتوكول ثنائي الاتجاه. يمكن للوجهات التعامل مع التوافق العكسي من خلال نشر مجموعتي إيجار باستخدام نفس الأنفاق، أو وضع كلا نوعي التشفير في LS2.
- تغييرات نموذج التهديد
- تفاصيل التنفيذ غير مطروحة هنا وتُترك لكل مشروع.
- (متفائل) إضافة امتدادات أو وصلات لدعم البث المتعدد (multicast)
التبرير
كان ElGamal/AES+SessionTag هو بروتوكول التشفير الوحيد من طرف إلى طرف لدينا منذ حوالي 15 عامًا، بشكل أساسي دون تعديلات على البروتوكول. توجد الآن بدائل تشفير أسرع. نحتاج إلى تعزيز أمان البروتوكول. كما طورنا استراتيجيات واستراتيجيات تجاوز لتصغير الاستهلاك من الذاكرة وعرض النطاق الترددي للبروتوكول، ولكن هذه الاستراتيجيات هشة، صعبة الضبط، وتجعل البروتوكول أكثر عرضة للانهيار، مما يؤدي إلى فقدان الجلسة.
منذ فترة مماثلة تقريبًا، وصفت مواصفات ElGamal/AES+SessionTag والوثائق ذات الصلة كيف أن تسليم session tags مكلف من حيث عرض النطاق الترددي، واقترحت استبدال تسليم session tags بـ “PRNG متزامن”. يولد PRNG متزامن نفس العلامات في كلا الطرفين بشكل حتمي، مشتقة من بذرة مشتركة. يمكن أيضًا تسمية PRNG متزامن بـ “ترس” (ratchet). يحدد هذا الاقتراح (أخيرًا) آلية الترس هذه، ويلغي تسليم العلامات.
من خلال استخدام ترس (PRNG متزامن) لتوليد session tags، نلغي تكلفة إرسال session tags في رسالة New Session والرسائل اللاحقة عند الحاجة. لعدد نموذجي من العلامات يبلغ 32 علامة، تكون هذه التكلفة 1 كيلوبايت. كما يلغي ذلك تخزين session tags على جانب المرسل، مما يقلل متطلبات التخزين إلى النصف.
يُحتاج إلى عملية تبادل يد ثنائية الاتجاه كاملة، مشابهة لنمط Noise IK، لتجنب هجمات تزوير المفتاح (Key Compromise Impersonation - KCI). انظر جدول “خصائص أمان الحمولة” في NOISE . لمزيد من المعلومات حول KCI، انظر الورقة https://www.usenix.org/system/files/conference/woot15/woot15-paper-hlauschek.pdf
نموذج التهديد
نموذج التهديد مختلف بعض الشيء عن NTCP2 (الاقتراح 111). عقد الوسيط (MitM) هي OBEP وIBGW ويفترض أن لديها رؤية كاملة لـ NetDB العالمي الحالي أو التاريخي، من خلال التواطؤ مع عقد الفيضان (floodfills).
الهدف هو منع هذه عقد الوسيط من تصنيف حركة المرور كـ رسائل جلسة جديدة وحالية، أو كتشفير جديد مقابل قديم.
الاقتراح التفصيلي
يحدد هذا الاقتراح بروتوكولًا جديدًا من طرف إلى طرف ليحل محل ElGamal/AES+SessionTags. سيستخدم التصميم عملية تبادل يد باستخدام Noise ومرحلة بيانات تدمج ترس الإشارة المزدوج (Signal’s double ratchet).
ملخص التصميم التشفيري
توجد خمسة أجزاء من البروتوكول يجب إعادة تصميمها:
- تنسيقات حاويات الجلسة الجديدة والحالية يتم استبدالها بتنسيقات جديدة.
- يتم استبدال ElGamal (مفاتيح عامة بطول 256 بايت، مفاتيح خاصة بطول 128 بايت) بـ ECIES-X25519 (مفاتيح عامة وخصوصية بطول 32 بايت)
- يتم استبدال AES بـ AEAD_ChaCha20_Poly1305 (يشار إليها اختصارًا بـ ChaChaPoly أدناه)
- يتم استبدال SessionTags بـ ratchets، وهو في الأساس PRNG متزامن تشفيري.
- يتم استبدال حمولة AES، كما هو معرف في مواصفات ElGamal/AES+SessionTags، بتنسيق كتلة مشابه لذلك في NTCP2.
يحتوي كل تغيير من هذه التغييرات الخمسة على قسم خاص به أدناه.
بدائل التشفير الجديدة لـ I2P
ستتطلب تنفيذات موجه I2P الحالية تنفيذات للبدائل التشفيرية القياسية التالية، التي لا تتطلبها بروتوكولات I2P الحالية:
- ECIES (لكن هذا في الأساس X25519)
- Elligator2
ستتطلب تنفيذات موجه I2P الحالية التي لم تنفذ بعد NTCP2 (اقتراح 111 ) أيضًا تنفيذات للآتي:
- توليد مفتاح X25519 وDH
- AEAD_ChaCha20_Poly1305 (يشار إليها اختصارًا بـ ChaChaPoly أدناه)
- HKDF
نوع التشفير (Crypto Type)
نوع التشفير (المستخدم في LS2) هو 4. يشير هذا إلى مفتاح X25519 عام بطول 32 بايت بتنسيق little-endian، وبروتوكول من طرف إلى طرف كما هو محدد هنا.
نوع التشفير 0 هو ElGamal. أنواع التشفير 1-3 محفوظة لـ ECIES-ECDH-AES-SessionTag، انظر الاقتراح 145 Proposal 145 .
إطار بروتوكول Noise
يوفر هذا الاقتراح المتطلبات بناءً على إطار بروتوكول Noise NOISE (النسخة 34، 2018-07-11). يتمتع Noise بخصائص مشابهة لبروتوكول Station-To-Station STS ، وهو الأساس لبروتوكول SSU . في لغة Noise، أليس (Alice) هي المبادرة، وبوبي (Bob) هو المستجيب.
يستند هذا الاقتراح إلى بروتوكول Noise Noise_IK_25519_ChaChaPoly_SHA256. (المعرف الفعلي لدالة اشتقاق المفتاح الأولي هو “Noise_IKelg2_25519_ChaChaPoly_SHA256” للإشارة إلى امتدادات I2P - انظر قسم KDF 1 أدناه) يستخدم هذا بروتوكول Noise البدائل التالية:
نمط تبادل اليد التفاعلي: IK ترسل أليس مفتاحها الثابت فورًا إلى بوبي (I) أليس تعرف مفتاح بوبي الثابت مسبقًا (K)
نمط تبادل اليد أحادي الاتجاه: N لا ترسل أليس مفتاحها الثابت إلى بوبي (N)
دالة DH: X25519 تبادل مفاتيح X25519 بطول مفتاح 32 بايت كما هو محدد في RFC-7748 .
دالة التشفير: ChaChaPoly AEAD_CHACHA20_POLY1305 كما هو محدد في RFC-7539 القسم 2.8. رقم عشوائي (nonce) بطول 12 بايت، مع تعيين أول 4 بايتات إلى صفر. مطابق تمامًا لما في NTCP2 .
دالة التجزئة: SHA256 تجزئة قياسية بطول 32 بايت، تُستخدم على نطاق واسع بالفعل في I2P.
إضافات إلى الإطار
يحدد هذا الاقتراح التحسينات التالية على Noise_IK_25519_ChaChaPoly_SHA256. عادةً ما تتبع هذه الإضافات الإرشادات في NOISE القسم 13.
يتم ترميز المفاتيح المؤقتة الواضحة باستخدام Elligator2 .
يتم بادئة الرد بعلامة واضحة.
تم تعريف تنسيق الحمولة للرسائل 1، 2، ومرحلة البيانات. بالطبع، هذا غير معرف في Noise.
تشمل جميع الرسائل رأس رسالة I2NP Garlic Message. تستخدم مرحلة البيانات تشفيرًا مشابهًا، ولكن غير متوافق مع، مرحلة بيانات Noise.
أنماط تبادل اليد
تستخدم عمليات تبادل اليد أنماط Noise .
يتم استخدام التعيين الحرف التالي:
- e = مفتاح مؤقت لمرة واحدة
- s = مفتاح ثابت
- p = حمولة الرسالة
الجلسات لمرة واحدة وغير المربوطة مشابهة لنمط Noise N.
<- s
...
e es p ->
الجلسات المرتبطة مشابهة لنمط Noise IK.
<- s
...
e es s ss p ->
<- tag e ee se
<- p
p ->
الجلسات
البروتوكول الحالي ElGamal/AES+SessionTag هو أحادي الاتجاه. على هذا المستوى، لا يعرف المستقبل من أين أتت الرسالة. لا يتم ربط الجلسات الصادرة والواردة. تتم الإقرارات خارج النطاق باستخدام رسالة DeliveryStatusMessage (مغلفة في GarlicMessage) في clove.
توجد كفاءة كبيرة في بروتوكول أحادي الاتجاه. أي رد يجب أيضًا استخدام رسالة ‘New Session’ مكلفة. هذا يتسبب في زيادة في عرض النطاق الترددي، وحدة المعالجة المركزية، واستخدام الذاكرة.
توجد أيضًا نقاط ضعف أمنية في بروتوكول أحادي الاتجاه. جميع الجلسات تعتمد على DH مؤقت-ثابت. بدون مسار عودة، لا توجد طريقة لبوبي “ترس” مفتاحه الثابت إلى مفتاح مؤقت. بدون معرفة مصدر الرسالة، لا توجد طريقة لاستخدام مفتاح DH المؤقت المستلم للرسائل الصادرة، لذلك يستخدم الرد الأولي أيضًا DH مؤقت-ثابت.
لهذا الاقتراح، نحدد آلية لخلق بروتوكول ثنائي الاتجاه - “الاقتران” و"الربط". توفر هذه الآليات كفاءة وأمانًا متزايدًا.
سياق الجلسة
كما هو الحال مع ElGamal/AES+SessionTags، يجب أن تكون جميع الجلسات الواردة والصادرة في سياق معين، إما سياق الموجه أو سياق وجهة محلية معينة. في Java I2P، يُسمى هذا السياق مدير مفتاح الجلسة (Session Key Manager).
يجب ألا تُشارك الجلسات بين السياقات، لأن ذلك سيسمح بربط الوجهات المحلية المختلفة، أو بين وجهة محلية وموجه.
عندما تدعم وجهة معينة كلاً من ElGamal/AES+SessionTags وهذا الاقتراح، يمكن لكلا نوعي الجلسات مشاركة سياق. انظر القسم 1c) أدناه.
اقتران الجلسات الواردة والصادرة
عند إنشاء جلسة صادرة عند المُرسِل (أليس)، تُنشأ جلسة واردة جديدة وتُقترن بالجلسة الصادرة، ما لم يكن لا يوجد رد متوقع (مثل datagrams الخام).
تُنشأ دائمًا جلسة واردة جديدة وتُقترن بجلسة صادرة جديدة، ما لم يُطلب عدم الرد (مثل datagrams الخام).
إذا طُلب رد وارتباط بوجهة أو موجه بعيد، تُربط تلك الجلسة الصادرة الجديدة بتلك الوجهة أو الموجه، وتستبدل أي جلسة صادرة سابقة لتلك الوجهة أو الموجه.
يتيح اقتران الجلسات الواردة والصادرة بروتوكولًا ثنائي الاتجاه مع القدرة على ترس مفاتيح DH.
ربط الجلسات والوجهات
توجد جلسة صادرة واحدة فقط إلى وجهة أو موجه معين. قد توجد عدة جلسات واردة حالية من وجهة أو موجه معين. بشكل عام، عند إنشاء جلسة واردة جديدة، وعند استلام حركة مرور على تلك الجلسة (والتي تخدم كـ ACK)، يتم وضع علامة على أي جلسات أخرى لانتهائها بسرعة نسبية، خلال دقيقة أو نحو ذلك. يتم التحقق من قيمة الرسائل السابقة المرسلة (PN)، وإذا لم تكن هناك رسائل غير مستلمة (ضمن حجم النافذة) في الجلسة الواردة السابقة، يمكن حذف الجلسة السابقة فورًا.
عند إنشاء جلسة صادرة عند المُرسِل (أليس)، تُربط بالوجهة البعيدة (بوبي)، وستُربط أي جلسة واردة مقترنة أيضًا بالوجهة البعيدة. بينما تتقدم الجلسات، تستمر في الارتباط بالوجهة البعيدة.
عند إنشاء جلسة واردة عند المستقبل (بوبي)، قد تُربط بالوجهة البعيدة (أليس)، حسب خيار أليس. إذا أدرجت أليس معلومات الربط (مفتاحها الثابت) في رسالة New Session، ستُربط الجلسة بتلك الوجهة، وستُنشأ جلسة صادرة وتُربط بنفس الوجهة. بينما تتقدم الجلسات، تستمر في الارتباط بالوجهة البعيدة.
فوائد الربط والاقتران
في الحالة الشائعة، التدفق، نتوقع أن تستخدم أليس وبوبي البروتوكول كالتالي:
- تُقرن أليس جلستها الصادرة الجديدة بجلسة واردة جديدة، كلاهما مربوطان بالوجهة البعيدة (بوبي).
- تُدرج أليس معلومات الربط والتوقيع، وطلب رد، في رسالة New Session المرسلة إلى بوبي.
- يُقرن بوبي جلسته الواردة الجديدة بجلسة صادرة جديدة، كلاهما مربوطان بالوجهة البعيدة (أليس).
- يرسل بوبي رد (ack) إلى أليس في الجلسة المقترنة، مع ترس إلى مفتاح DH جديد.
- تُرس أليس إلى جلسة صادرة جديدة مع مفتاح بوبي الجديد، مقترنة بالجلسة الواردة الحالية.
من خلال ربط جلسة واردة بوجهة بعيدة، واقتران الجلسة الواردة بجلسة صادرة مربوطة بنفس الوجهة، نحقق فائدتين رئيسيتين:
يستخدم الرد الأولي من بوبي إلى أليس DH مؤقت-مؤقت
بعد أن تستلم أليس رد بوبي وتُرس، جميع الرسائل اللاحقة من أليس إلى بوبي تستخدم DH مؤقت-مؤقت.
إقرارات الرسائل (Message ACKs)
في ElGamal/AES+SessionTags، عندما يتم تجميع LeaseSet كـ garlic clove، أو يتم تسليم العلامات، يطلب الموجه المرسل إقرارًا. هذا عبارة عن garlic clove منفصل يحتوي على رسالة DeliveryStatus Message. لأغراض أمنية إضافية، يتم تغليف رسالة DeliveryStatus Message في رسالة Garlic Message. هذه الآلية خارج النطاق من منظور البروتوكول.
في البروتوكول الجديد، نظرًا لأن الجلسات الواردة والصادرة مقترنة، يمكن أن تكون الإقرارات داخل النطاق. لا يتطلب clove منفصل.
الإقرار الصريح هو ببساطة رسالة Existing Session بدون كتلة I2NP. ومع ذلك، في معظم الحالات، يمكن تجنب الإقرار الصريح، حيث توجد حركة مرور عكسية. قد يكون من المرغوب أن تنتظر التنفيذات لفترة قصيرة (ربما مائة مللي ثانية) قبل إرسال إقرار صريح، لإعطاء طبقة التدفق أو التطبيق وقتًا للاستجابة.
ستحتاج التنفيذات أيضًا إلى تأجيل إرسال أي إقرار حتى بعد معالجة كتلة I2NP، لأن رسالة Garlic Message قد تحتوي على رسالة Database Store Message مع lease set. سيكون lease set حديثًا ضروريًا لتوجيه الإقرار، وستكون الوجهة البعيدة (الموجودة في lease set) ضرورية للتحقق من مفتاح الربط الثابت.
انتهاء صلاحية الجلسات
يجب أن تنتهي صلاحية الجلسات الصادرة دائمًا قبل الجلسات الواردة. بمجرد انتهاء صلاحية جلسة صادرة، وتم إنشاء واحدة جديدة، سيتم إنشاء جلسة واردة مقترنة جديدة أيضًا. إذا كانت هناك جلسة واردة قديمة، سيُسمح لها بالانتهاء.
البث المتعدد (Multicast)
قيد التحديد (TBD)
التعريفات
نحدد الدوال التالية المقابلة للكتل البنائية التشفيرية المستخدمة.
ZEROLEN مصفوفة بايتات فارغة الطول
CSRNG(n) مخرجات بطول n بايت من مولد أرقام عشوائية آمن تشفيريًا.
H(p, d) دالة تجزئة SHA-256 التي تأخذ سلسلة تخصيص p وبيانات d، وتُنتج مخرجات بطول 32 بايت. كما هو معرف في NOISE . || أدناه تعني إلحاق.
استخدم SHA-256 كالتالي::
H(p, d) := SHA-256(p || d)
MixHash(d) دالة تجزئة SHA-256 التي تأخذ تجزئة سابقة h وبيانات جديدة d، وتُنتج مخرجات بطول 32 بايت. || أدناه تعني إلحاق.
استخدم SHA-256 كالتالي::
MixHash(d) := h = SHA-256(h || d)
STREAM ChaCha20/Poly1305 AEAD كما هو محدد في RFC-7539 . S_KEY_LEN = 32 و S_IV_LEN = 12.
ENCRYPT(k, n, plaintext, ad)
يشفّر plaintext باستخدام مفتاح التشفير k، ورقم عشوائي n الذي يجب أن يكون فريدًا
للمفتاح k.
البيانات المرتبطة ad اختيارية.
يُرجع نصًا مشفرًا بحجم النص الأصلي + 16 بايت للـ HMAC.
يجب أن يكون النص المشفر بأكمله غير قابل للتمييز عن بيانات عشوائية إذا كان المفتاح سريًا.
DECRYPT(k, n, ciphertext, ad)
يفك تشفير ciphertext باستخدام مفتاح التشفير k، ورقم عشوائي n.
البيانات المرتبطة ad اختيارية.
يُرجع النص الأصلي.
DH نظام اتفاق المفاتيح العامة X25519. مفاتيح خاصة بطول 32 بايت، مفاتيح عامة بطول 32 بايت، تُنتج مخرجات بطول 32 بايت. له الوظائف التالية:
GENERATE_PRIVATE()
يولد مفتاحًا خاصًا جديدًا.
DERIVE_PUBLIC(privkey)
يُرجع المفتاح العام المقابل للمفتاح الخاص المعطى.
GENERATE_PRIVATE_ELG2()
يولد مفتاحًا خاصًا جديدًا يُرسم إلى مفتاح عام مناسب لترميز Elligator2.
لاحظ أن نصف المفاتيح الخاصة المولدة عشوائيًا لن تكون مناسبة ويجب التخلص منها.
ENCODE_ELG2(pubkey)
يُرجع المفتاح العام المشفر باستخدام Elligator2 المقابل للمفتاح العام المعطى (رسم عكسي).
المفاتيح المشفرة تكون بتنسيق little endian.
يجب أن يكون المفتاح المشفر بطول 256 بت غير قابل للتمييز عن بيانات عشوائية.
انظر قسم Elligator2 أدناه للمواصفات.
DECODE_ELG2(pubkey)
يُرجع المفتاح العام المقابل للمفتاح العام المشفر باستخدام Elligator2 المعطى.
انظر قسم Elligator2 أدناه للمواصفات.
DH(privkey, pubkey)
يولد سرًا مشتركًا من المفتاح الخاص والعامة المعطى.
HKDF(salt, ikm, info, n) دالة اشتقاق مفتاح تشفيرية تأخذ مواد مفتاح إدخال ikm (التي يجب أن تكون ذات إنتروبيا جيدة ولكن لا يشترط أن تكون سلسلة عشوائية موحدة)، وملح بطول 32 بايت، وقيمة ‘info’ محددة بالسياق، وتُنتج مخرجات بطول n بايت مناسبة للاستخدام كمواد مفتاح.
استخدم HKDF كما هو محدد في [RFC-5869](https://tools.ietf.org/html/rfc5869)، باستخدام دالة تجزئة HMAC SHA-256
كما هو محدد في [RFC-2104](https://tools.ietf.org/html/rfc2104). هذا يعني أن SALT_LEN هو 32 بايت كحد أقصى.
MixKey(d) استخدم HKDF() مع chainKey سابق وبيانات جديدة d، و اضبط chainKey الجديد و k. كما هو معرف في NOISE .
استخدم HKDF كالتالي::
MixKey(d) := output = HKDF(chainKey, d, "", 64)
chainKey = output[0:31]
k = output[32:63]
1) تنسيق الرسالة
مراجعة تنسيق الرسالة الحالي
كما هو محدد في I2NP ، رسالة Garlic Message هي كالتالي. بهدف التصميم أن العقد الوسيطة لا يمكنها التمييز بين التشفير الجديد والقديم، لا يمكن تغيير هذا التنسيق، حتى لو كان حقل الطول زائدًا. يُعرض التنسيق مع رأس كامل بطول 16 بايت، على الرغم من أن الرأس الفعلي قد يكون بتنسيق مختلف، حسب النقل المستخدم.
عند فك التشفير، تحتوي البيانات على سلسلة من Garlic Cloves وبيانات إضافية، تُعرف أيضًا بـ Clove Set.
انظر I2NP للتفاصيل والمواصفات الكاملة.
+----+----+----+----+----+----+----+----+
|type| msg_id | expiration
+----+----+----+----+----+----+----+----+
| size |chks|
+----+----+----+----+----+----+----+----+
| length | |
+----+----+----+----+ +
| encrypted data |
~ ~
~ ~
| |
+----+----+----+----+----+----+----+----+
مراجعة تنسيق البيانات المشفرة
تنسيق الرسالة الحالي، المستخدم لأكثر من 15 عامًا، هو ElGamal/AES+SessionTags. في ElGamal/AES+SessionTags، هناك تنسيقان للرسائل:
- جلسة جديدة:
- كتلة ElGamal بطول 514 بايت
- كتلة AES (128 بايت كحد أدنى، مضاعف لـ 16)
- جلسة حالية:
- علامة جلسة بطول 32 بايت
- كتلة AES (128 بايت كحد أدنى، مضاعف لـ 16)
الحد الأدنى للتعبئة إلى 128 كما هو مُنفذ في Java I2P ولكن لا يتم فرضه عند الاستقبال.
تُغلف هذه الرسائل في رسالة I2NP garlic، والتي تحتوي على حقل طول، لذلك يكون الطول معروفًا.
لاحظ أنه لا يوجد تعبئة معرفة لطول غير مضاعف لـ 16، لذلك تكون الجلسة الجديدة دائمًا (mod 16 == 2)، والجلسة الحالية دائمًا (mod 16 == 0). نحتاج إلى إصلاح هذا.
أولًا يحاول المستقبل البحث عن أول 32 بايت كـ Session Tag. إذا وُجد، يفك تشفير كتلة AES. إذا لم يُوجد، وكانت البيانات بطول لا يقل عن (514+16)، يحاول فك تشفير كتلة ElGamal، وإذا نجح، يفك تشفير كتلة AES.
Session Tags الجديدة ومقارنة بـ Signal
في Signal Double Ratchet، يحتوي الرأس على:
- DH: مفتاح عام حالي للترس
- PN: طول سلسلة الرسائل السابقة
- N: رقم الرسالة
“سلسلة الإرسال” في Signal تُعادل تقريبًا مجموعات العلامات لدينا. من خلال استخدام session tag، يمكننا إلغاء معظم ذلك.
في New Session، نضع فقط المفتاح العام في الرأس غير المشفر.
في Existing Session، نستخدم session tag للرأس. تُرتبط session tag بالمفتاح العام الحالي للترس، ورقم الرسالة.
في كل من الجلسة الجديدة والحالية، تكون PN وN في جسم الرسالة المشفر.
في Signal، الأمور تتقدم باستمرار. مفتاح عام DH جديد يتطلب من المستقبل أن يُرس ويُرسل مفتاح عام جديد للعودة، والذي يخدم أيضًا كـ ack للمفتاح العام المستلم. هذا سيكون عددًا كبيرًا جدًا من عمليات DH بالنسبة لنا. لذلك نفصل بين ack للمفتاح المستلم وإرسال مفتاح عام جديد. أي رسالة تستخدم session tag تم إنشاؤها من مفتاح DH الجديد تُشكل ack. نرسل مفتاحًا عامًا جديدًا فقط عندما نرغب في إعادة تعيين المفتاح.
الحد الأقصى لعدد الرسائل قبل أن يجب أن يُرس DH هو 65535.
عند تسليم مفتاح الجلسة، نُشتق “مجموعة العلامات” (Tag Set) منه، بدلاً من الحاجة إلى تسليم session tags أيضًا. يمكن أن تحتوي مجموعة العلامات على ما يصل إلى 65536 علامة. ومع ذلك، يجب على المستقبلين تنفيذ استراتيجية “النظر إلى الأمام”، بدلاً من إنشاء جميع العلامات الممكنة دفعة واحدة. أنشئ فقط ما يصل إلى N علامة بعد آخر علامة جيدة تم استلامها. قد يكون N كحد أقصى 128، ولكن 32 أو أقل قد يكون خيارًا أفضل.
1a) تنسيق الجلسة الجديدة
مفتاح عام جديد لمرة واحدة (32 بايت) بيانات مشفرة وMAC (البايتات المتبقية)
قد تحتوي رسالة New Session على المفتاح العام الثابت للمرسل أو لا. إذا تم تضمينه، تُربط الجلسة العكسية بذلك المفتاح. يجب تضمين المفتاح الثابت إذا كان متوقعًا الرد، أي للتدفق وdatagrams القابلة للرد. لا يجب تضمينه لـ datagrams الخام.
تُشبه رسالة New Session نمط Noise أحادي الاتجاه NOISE “N” (إذا لم يُرسل المفتاح الثابت)، أو نمط “IK” ثنائي الاتجاه (إذا تم إرسال المفتاح الثابت).
1b) تنسيق الجلسة الجديدة (مع الربط)
الطول هو 96 + طول الحمولة. التنسيق المشفر:
+----+----+----+----+----+----+----+----+
| |
+ +
| New Session Ephemeral Public Key |
+ 32 bytes +
| Encoded with Elligator2 |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ Static Key +
| ChaCha20 encrypted data |
+ 32 bytes +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for Static Key Section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
| |
+ Payload Section +
| ChaCha20 encrypted data |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for Payload Section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
Public Key :: 32 bytes, little endian, Elligator2, cleartext
Static Key encrypted data :: 32 bytes
Payload Section encrypted data :: remaining data minus 16 bytes
MAC :: Poly1305 message authentication code, 16 bytes
مفتاح مؤقت جديد للجلسة
المفتاح المؤقت بطول 32 بايت، مشفر باستخدام Elligator2. لا يُعاد استخدام هذا المفتاح أبدًا؛ يتم إنشاء مفتاح جديد مع كل رسالة، بما في ذلك إعادة الإرسال.
المفتاح الثابت
عند فك التشفير، مفتاح X25519 الثابت الخاص بأليس، 32 بايت.
الحمولة
طول التشفير هو الباقي من البيانات. طول فك التشفير أقل بـ 16 بايت من طول التشفير. يجب أن تحتوي الحمولة على كتلة DateTime وعادةً ما تحتوي على كتلة أو أكثر من Garlic Clove. انظر قسم الحمولة أدناه للتنسيق والمتطلبات الإضافية.
1c) تنسيق الجلسة الجديدة (بدون ربط)
إذا لم يكن هناك رد مطلوب، لا يتم إرسال مفتاح ثابت.
الطول هو 96 + طول الحمولة. التنسيق المشفر:
+----+----+----+----+----+----+----+----+
| |
+ +
| New Session Ephemeral Public Key |
+ 32 bytes +
| Encoded with Elligator2 |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ Flags Section +
| ChaCha20 encrypted data |
+ 32 bytes +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for above section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
| |
+ Payload Section +
| ChaCha20 encrypted data |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for Payload Section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
Public Key :: 32 bytes, little endian, Elligator2, cleartext
Flags Section encrypted data :: 32 bytes
Payload Section encrypted data :: remaining data minus 16 bytes
MAC :: Poly1305 message authentication code, 16 bytes
مفتاح مؤقت جديد للجلسة
مفتاح أليس المؤقت. المفتاح المؤقت بطول 32 بايت، مشفر باستخدام Elligator2، بتنسيق little endian. لا يُعاد استخدام هذا المفتاح أبدًا؛ يتم إنشاء مفتاح جديد مع كل رسالة، بما في ذلك إعادة الإرسال.
بيانات قسم العلامات بعد فك التشفير
يحتوي قسم العلامات على لا شيء. يكون دائمًا بطول 32 بايت، لأنه يجب أن يكون نفس الطول كمفتاح ثابت لرسائل New Session مع الربط. يحدد بوبي ما إذا كان مفتاحًا ثابتًا أو قسم علامات باختبار ما إذا كانت 32 بايت كلها أصفار.
هل هناك حاجة لأي علامات هنا؟ (TODO)
الحمولة
طول التشفير هو الباقي من البيانات. طول فك التشفير أقل بـ 16 بايت من طول التشفير. يجب أن تحتوي الحمولة على كتلة DateTime وعادةً ما تحتوي على كتلة أو أكثر من Garlic Clove. انظر قسم الحمولة أدناه للتنسيق والمتطلبات الإضافية.
1d) تنسيق لمرة واحدة (بدون ربط أو جلسة)
إذا كان من المتوقع إرسال رسالة واحدة فقط، لا يتطلب إعداد جلسة أو مفتاح ثابت.
الطول هو 96 + طول الحمولة. التنسيق المشفر:
+----+----+----+----+----+----+----+----+
| |
+ +
| Ephemeral Public Key |
+ 32 bytes +
| Encoded with Elligator2 |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ Flags Section +
| ChaCha20 encrypted data |
+ 32 bytes +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for above section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
| |
+ Payload Section +
| ChaCha20 encrypted data |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for Payload Section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
Public Key :: 32 bytes, little endian, Elligator2, cleartext
Flags Section encrypted data :: 32 bytes
Payload Section encrypted data :: remaining data minus 16 bytes
MAC :: Poly1305 message authentication code, 16 bytes
مفتاح لمرة واحدة جديد للجلسة
المفتاح لمرة واحدة بطول 32 بايت، مشفر باستخدام Elligator2، بتنسيق little endian. لا يُعاد استخدام هذا المفتاح أبدًا؛ يتم إنشاء مفتاح جديد مع كل رسالة، بما في ذلك إعادة الإرسال.
بيانات قسم العلامات بعد فك التشفير
يحتوي قسم العلامات على لا شيء. يكون دائمًا بطول 32 بايت، لأنه يجب أن يكون نفس الطول كمفتاح ثابت لرسائل New Session مع الربط. يحدد بوبي ما إذا كان مفتاحًا ثابتًا أو قسم علامات باختبار ما إذا كانت 32 بايت كلها أصفار.
هل هناك حاجة لأي علامات هنا؟ (TODO)
+----+----+----+----+----+----+----+----+
| |
+ +
| |
+ All zeros +
| 32 bytes |
+ +
| |
+----+----+----+----+----+----+----+----+
zeros:: All zeros, 32 bytes.
الحمولة
طول التشفير هو الباقي من البيانات. طول فك التشفير أقل بـ 16 بايت من طول التشفير. يجب أن تحتوي الحمولة على كتلة DateTime وعادةً ما تحتوي على كتلة أو أكثر من Garlic Clove. انظر قسم الحمولة أدناه للتنسيق والمتطلبات الإضافية.
1f) KDFs لرسالة New Session
KDF للمفتاح السلس الأولي (Initial ChainKey)
هذا هو NOISE القياسي لـ IK مع اسم بروتوكول معدل. لاحظ أننا نستخدم نفس المُهيئ لكل من نمط IK (الجلسات المرتبطة) ولنمط N (الجلسات غير المرتبطة).
يتم تعديل اسم البروتوكول لسببين. أولًا، للإشارة إلى أن المفاتيح المؤقتة مشفرة باستخدام Elligator2، وثانيًا، للإشارة إلى أن MixHash() يتم استدعاؤه قبل الرسالة الثانية لخلط قيمة العلامة.
هذا هو نمط الرسالة "e":
// Define protocol_name.
Set protocol_name = "Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"
(40 bytes, US-ASCII encoded, no NULL termination).
// Define Hash h = 32 bytes
h = SHA256(protocol_name);
Define ck = 32 byte chaining key. Copy the h data to ck.
Set chainKey = h
// MixHash(null prologue)
h = SHA256(h);
// up until here, can all be precalculated by Alice for all outgoing connections
KDF لمحتويات قسم العلامات/المفتاح الثابت المشفر
هذا هو نمط الرسالة "e":
// Bob's X25519 static keys
// bpk is published in leaseset
bsk = GENERATE_PRIVATE()
bpk = DERIVE_PUBLIC(bsk)
// Bob static public key
// MixHash(bpk)
// || below means append
h = SHA256(h || bpk);
// up until here, can all be precalculated by Bob for all incoming connections
// Alice's X25519 ephemeral keys
aesk = GENERATE_PRIVATE_ELG2()
aepk = DERIVE_PUBLIC(aesk)
// Alice ephemeral public key
// MixHash(aepk)
// || below means append
h = SHA256(h || aepk);
// h is used as the associated data for the AEAD in the New Session Message
// Retain the Hash h for the New Session Reply KDF
// eapk is sent in cleartext in the
// beginning of the New Session message
elg2_aepk = ENCODE_ELG2(aepk)
// As decoded by Bob
aepk = DECODE_ELG2(elg2_aepk)
End of "e" message pattern.
This is the "es" message pattern:
// Noise es
sharedSecret = DH(aesk, bpk) = DH(bsk, aepk)
// MixKey(DH())
//[chainKey, k] = MixKey(sharedSecret)
// ChaChaPoly parameters to encrypt/decrypt
keydata = HKDF(chainKey, sharedSecret, "", 64)
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, flags/static key section, ad)
End of "es" message pattern.
This is the "s" message pattern:
// MixHash(ciphertext)
// Save for Payload section KDF
h = SHA256(h || ciphertext)
// Alice's X25519 static keys
ask = GENERATE_PRIVATE()
apk = DERIVE_PUBLIC(ask)
End of "s" message pattern.
KDF لقسم الحمولة (مع مفتاح أليس الثابت)
This is the "ss" message pattern:
// Noise ss
sharedSecret = DH(ask, bpk) = DH(bsk, apk)
// MixKey(DH())
//[chainKey, k] = MixKey(sharedSecret)
// ChaChaPoly parameters to encrypt/decrypt
// chainKey from Static Key Section
Set sharedSecret = X25519 DH result
keydata = HKDF(chainKey, sharedSecret, "", 64)
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, payload, ad)
End of "ss" message pattern.
// MixHash(ciphertext)
// Save for New Session Reply KDF
h = SHA256(h || ciphertext)
KDF لقسم الحمولة (بدون مفتاح أليس الثابت)
لاحظ أن هذا نمط Noise “N”، ولكننا نستخدم نفس “IK” المُهيئ كما هو الحال للجلسات المرتبطة.
لا يمكن تحديد رسائل New Session على أنها تحتوي على مفتاح أليس الثابت أم لا حتى يتم فك تشفير المفتاح الثابت وفحصه لتحديد ما إذا كان يحتوي على أصفار فقط. لذلك، يجب على المستقبل استخدام آلة حالة “IK” لجميع رسائل New Session. إذا كان المفتاح الثابت عبارة عن أصفار فقط، يجب تخطي نمط “ss”.
chainKey = from Flags/Static key section
k = from Flags/Static key section
n = 1
ad = h from Flags/Static key section
ciphertext = ENCRYPT(k, n, payload, ad)
1g) تنسيق رد الجلسة الجديدة (New Session Reply)
يمكن إرسال رد جلسة جديدة واحد أو أكثر استجابةً لرسالة جلسة جديدة واحدة. يتم بادئة كل رد بعلامة، يتم إنشاؤها من مجموعة علامات للجلسة.
يتكون رد الجلسة الجديدة من جزأين. الجزء الأول هو إكمال عملية تبادل يد Noise IK مع علامة مسبوقة. طول الجزء الأول هو 56 بايت. الجزء الثاني هو حمولة مرحلة البيانات. طول الجزء الثاني هو 16 + طول الحمولة.
الطول الكلي هو 72 + طول الحمولة. التنسيق المشفر:
+----+----+----+----+----+----+----+----+
| Session Tag 8 bytes |
+----+----+----+----+----+----+----+----+
| |
+ Ephemeral Public Key +
| |
+ 32 bytes +
| Encoded with Elligator2 |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for Key Section (no data) +
| 16 bytes |
+----+----+----+----+----+----+----+----+
| |
+ Payload Section +
| ChaCha20 encrypted data |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for Payload Section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
Tag :: 8 bytes, cleartext
Public Key :: 32 bytes, little endian, Elligator2, cleartext
MAC :: Poly1305 message authentication code, 16 bytes
Note: The ChaCha20 plaintext data is empty (ZEROLEN)
Payload Section encrypted data :: remaining data minus 16 bytes
MAC :: Poly1305 message authentication code, 16 bytes
علامة الجلسة
تُنشأ العلامة في KDF لـ Session Tags، كما تم تهيئتها في KDF التهيئة DH أدناه. هذا يربط الرد بالجلسة. لا يُستخدم مفتاح الجلسة من التهيئة DH.
مفتاح مؤقت جديد لرد الجلسة الجديدة
مفتاح بوبي المؤقت. المفتاح المؤقت بطول 32 بايت، مشفر باستخدام Elligator2، بتنسيق little endian. لا يُعاد استخدام هذا المفتاح أبدًا؛ يتم إنشاء مفتاح جديد مع كل رسالة، بما في ذلك إعادة الإرسال.
الحمولة
طول التشفير هو الباقي من البيانات. طول فك التشفير أقل بـ 16 بايت من طول التشفير. عادةً ما تحتوي الحمولة على كتلة أو أكثر من Garlic Clove. انظر قسم الحمولة أدناه للتنسيق والمتطلبات الإضافية.
KDF لمجموعة علامات الرد
تُنشأ علامة أو أكثر من مجموعة العلامات، والتي يتم تهيئتها باستخدام KDF أدناه، باستخدام chainKey من رسالة New Session.
// Generate tagset
tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32)
tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey)
KDF لمحتويات قسم المفتاح المشفر في الرد
// Keys from the New Session message
// Alice's X25519 keys
// apk and aepk are sent in original New Session message
// ask = Alice private static key
// apk = Alice public static key
// aesk = Alice ephemeral private key
// aepk = Alice ephemeral public key
// Bob's X25519 static keys
// bsk = Bob private static key
// bpk = Bob public static key
// Generate the tag
tagsetEntry = tagset_nsr.GET_NEXT_ENTRY()
tag = tagsetEntry.SESSION_TAG
// MixHash(tag)
h = SHA256(h || tag)
This is the "e" message pattern:
// Bob's X25519 ephemeral keys
besk = GENERATE_PRIVATE_ELG2()
bepk = DERIVE_PUBLIC(besk)
// Bob's ephemeral public key
// MixHash(bepk)
// || below means append
h = SHA256(h || bepk);
// elg2_bepk is sent in cleartext in the
// beginning of the New Session message
elg2_bepk = ENCODE_ELG2(bepk)
// As decoded by Bob
bepk = DECODE_ELG2(elg2_bepk)
End of "e" message pattern.
This is the "ee" message pattern:
// MixKey(DH())
//[chainKey, k] = MixKey(sharedSecret)
// ChaChaPoly parameters to encrypt/decrypt
// chainKey from original New Session Payload Section
sharedSecret = DH(aesk, bepk) = DH(besk, aepk)
keydata = HKDF(chainKey, sharedSecret, "", 32)
chainKey = keydata[0:31]
End of "ee" message pattern.
This is the "se" message pattern:
// MixKey(DH())
//[chainKey, k] = MixKey(sharedSecret)
sharedSecret = DH(ask, bepk) = DH(besk, apk)
keydata = HKDF(chainKey, sharedSecret, "", 64)
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
End of "se" message pattern.
// MixHash(ciphertext)
h = SHA256(h || ciphertext)
chainKey is used in the ratchet below.
KDF لمحتويات قسم الحمولة المشفرة
هذا مشابه لأول رسالة Existing Session، بعد التقسيم، ولكن بدون علامة منفصلة. بالإضافة إلى ذلك، نستخدم التجزئة من الأعلى لربط الحمولة برسالة NSR.
// split()
keydata = HKDF(chainKey, ZEROLEN, "", 64)
k_ab = keydata[0:31]
k_ba = keydata[32:63]
tagset_ab = DH_INITIALIZE(chainKey, k_ab)
tagset_ba = DH_INITIALIZE(chainKey, k_ba)
// AEAD parameters for New Session Reply payload
k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
n = 0
ad = h
ciphertext = ENCRYPT(k, n, payload, ad)
ملاحظات
قد يتم إرسال رسائل NSR متعددة كرد، كل منها بمفاتيح مؤقتة فريدة، حسب حجم الاستجابة.
يُطلب من أليس وبوبي استخدام مفاتيح مؤقتة جديدة لكل رسالة NS وNSR.
يجب أن تستلم أليس إحدى رسائل NSR من بوبي قبل إرسال رسائل Existing Session (ES)، ويجب أن يستلم بوبي رسالة ES من أليس قبل إرسال رسائل ES.
يُستخدم chainKey و k من قسم حمولة NSR الخاص ببوبي
كمدخلات لترسات DH الأولية لـ ES (كلا الاتجاهين، انظر DH Ratchet KDF).
يجب أن يحتفظ بوبي فقط بجلسات ES للرسائل المستلمة من أليس. يجب تدمير أي جلسات واردة وصادرة أخرى (لعدة NSRs) فورًا بعد استلام أول رسالة ES من أليس لجلسة معينة.
1h) تنسيق الجلسة الحالية
Session tag (8 بايت) بيانات مشفرة وMAC (انظر القسم 3 أدناه)
التنسيق
مشفر:
+----+----+----+----+----+----+----+----+
| Session Tag |
+----+----+----+----+----+----+----+----+
| |
+ Payload Section +
| ChaCha20 encrypted data |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) +
| 16 bytes |
+----+----+----+----+----+----+----+----+
Session Tag :: 8 bytes, cleartext
Payload Section encrypted data :: remaining data minus 16 bytes
MAC :: Poly1305 message authentication code, 16 bytes
الحمولة
طول التشفير هو الباقي من البيانات. طول فك التشفير أقل بـ 16 بايت من طول التشفير. انظر قسم الحمولة أدناه للتنسيق والمتطلبات.
KDF
انظر قسم AEAD أدناه.
// AEAD parameters for Existing Session payload
k = The 32-byte session key associated with this session tag
n = The message number N in the current chain, as retrieved from the associated Session Tag.
ad = The session tag, 8 bytes
ciphertext = ENCRYPT(k, n, payload, ad)
2) ECIES-X25519
التنسيق: مفاتيح عامة وخاصة بطول 32 بايت، بتنسيق little-endian.
التبرير: مستخدم في NTCP2 .
2a) Elligator2
في عمليات تبادل اليد القياسية لـ Noise، تبدأ رسائل تبادل اليد الأولية في كل اتجاه بمفاتيح مؤقتة تُرسل بشكل واضح. بما أن مفاتيح X25519 الصالحة يمكن تمييزها عن البيانات العشوائية، قد يتمكن وسيط من التمييز بين هذه الرسائل ورسائل Existing Session التي تبدأ بعلامات عشوائية. في NTCP2 (اقتراح 111 )، استخدمنا دالة XOR منخفضة التكلفة باستخدام المفتاح الثابت خارج النطاق لإخفاء المفتاح. ومع ذلك، فإن نموذج التهديد هنا مختلف؛ لا نريد السماح لأي وسيط باستخدام أي وسيلة لتأكيد وجهة حركة المرور، أو التمييز بين رسائل تبادل اليد الأولية ورسائل Existing Session.
لذلك، يتم استخدام Elligator2 لتحويل المفاتيح المؤقتة في رسائل New Session وNew Session Reply لجعلها غير قابلة للتمييز عن سلاسل عشوائية موحدة.
التنسيق
مفاتيح عامة وخاصة بطول 32 بايت. المفاتيح المشفرة تكون بتنسيق little endian.
كما هو معرف في Elligator2 ، تكون المفاتيح المشفرة غير قابلة للتمييز عن 254 بت عشوائية. نطلب 256 بت عشوائية (32 بايت). لذلك، يتم تعريف التشفير والفك كالتالي:
الترميز:
ENCODE_ELG2() Definition
// Encode as defined in Elligator2 specification
encodedKey = encode(pubkey)
// OR in 2 random bits to MSB
randomByte = CSRNG(1)
encodedKey[31] |= (randomByte & 0xc0)
فك الترميز:
DECODE_ELG2() Definition
// Mask out 2 random bits from MSB
encodedKey[31] &= 0x3f
// Decode as defined in Elligator2 specification
pubkey = decode(encodedKey)
التبرير
مطلوب لمنع OBEP وIBGW من تصنيف حركة المرور.
ملاحظات
يُضاعف Elligator2 متوسط وقت توليد المفتاح، لأن نصف المفاتيح الخاصة تؤدي إلى مفاتيح عامة غير مناسبة للترميز باستخدام Elligator2. أيضًا، وقت توليد المفتاح غير محدود بتوزيع أسي، لأن المولد يجب أن يستمر في المحاولة حتى يجد زوج مفاتيح مناسب.
يمكن إدارة هذا العبء من خلال القيام بتوليد المفاتيح مسبقًا، في خيط منفصل، للحفاظ على مجموعة من المفاتيح المناسبة.
يقوم المولد بعمل دالة ENCODE_ELG2() لتحديد الملاءمة. لذلك، يجب أن يخزن المولد نتيجة ENCODE_ELG2() حتى لا تُحسب مرة أخرى.
بالإضافة إلى ذلك، يمكن إضافة المفاتيح غير المناسبة إلى مجموعة المفاتيح المستخدمة لـ NTCP2 ، حيث لا يُستخدم Elligator2. قضايا الأمان في القيام بذلك لم تُحدد بعد.
3) AEAD (ChaChaPoly)
AEAD باستخدام ChaCha20 وPoly1305، نفس ما في NTCP2 . هذا يتوافق مع RFC-7539 ، والذي يُستخدم بشكل مشابه في TLS RFC-7905 .
مدخلات New Session وNew Session Reply
مدخلات وظائف التشفير/فك التشفير لكتلة AEAD في رسالة New Session:
k :: 32 byte cipher key
See New Session and New Session Reply KDFs above.
n :: Counter-based nonce, 12 bytes.
n = 0
ad :: Associated data, 32 bytes.
The SHA256 hash of the preceding data, as output from mixHash()
data :: Plaintext data, 0 or more bytes
مدخلات الجلسة الحالية
مدخلات وظائف التشفير/فك التشفير لكتلة AEAD في رسالة Existing Session:
k :: 32 byte session key
As looked up from the accompanying session tag.
n :: Counter-based nonce, 12 bytes.
Starts at 0 and incremented for each message when transmitting.
For the receiver, the value
as looked up from the accompanying session tag.
First four bytes are always zero.
Last