بث AE-GCM-HKDF AEAD

يحدّد هذا المستند بشكل رسمي الدالة الرياضية التي تمثلها مفاتيح بث AES-GCM-HKDF، والمرمّزة بتنسيق Proto على النحو التالي: type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey.

يستند هذا التشفير بشكل غير دقيق إلى HRRV151. لتحليل الأمان، نشير إلى HS202.

المفتاح والمعلمات

يتم وصف المفاتيح بالأجزاء التالية (جميع الأحجام في هذا المستند بالبايت):

  • \(\mathrm{KeyValue}\)، سلسلة بايت.
  • \(\mathrm{CiphertextSegmentSize} \in \{1, 2, \ldots, 2^{31}-1\}\).
  • \(\mathrm{DerivedKeySize} \in \{16, 32\}\).
  • \(\mathrm{HkdfHashType} \in \{\mathrm{SHA1}, \mathrm{SHA256}, \mathrm{SHA512}\}\).

بالإضافة إلى ذلك، تستوفي المفاتيح الصالحة السمات التالية:

  • \(\mathrm{len}(\mathrm{KeyValue}) \geq \mathrm{DerivedKeySize}\).
  • \(\mathrm{CiphertextSegmentSize} > \mathrm{DerivedKeySize} + 24\) (يساوي ذلك \(\mathrm{len}(\mathrm{Header}) + 16\) كما هو موضّح لاحقًا).

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

دالة التشفير

لتشفير رسالة \(\mathrm{Msg}\) باستخدام البيانات المرتبطة بها \(\mathrm{AssociatedData}\)، ننشئ عنوانًا، ونقسم الرسالة إلى أقسام، ونشفّر كل مقطع، ثم ننشئ تسلسلاً للأجزاء المشفَّرة.

إنشاء العنوان

فنحن نختار خيطًا عشوائيًا موحَّدًا \(\mathrm{Salt}\) طوله \(\mathrm{DerivedKeySize}\) وسلسلة عشوائية موحّدة \(\mathrm{NoncePrefix}\) بطول 7.

ثم نضبط \(\mathrm{Header} := \mathrm{len}(\mathrm{Header}) \| \mathrm{Salt} \| \mathrm{NoncePrefix}\)، حيث يتم ترميز طول العنوان كبايت واحد. يُرجى العِلم أنّ \(\mathrm{len}(\mathrm{Header}) \in \{24, 40\}\).

بعد ذلك، نستخدم دالة HKDF3 مع دالة التجزئة التي يوفّرها \(\mathrm{HkdfHashType}\) والمدخلات \(\mathrm{ikm} := \mathrm{KeyValue}\)و \(\mathrm{salt} := \mathrm{Salt}\)و \(\mathrm{info} := \mathrm{AssociatedData}\)مع طول الإخراج \(\mathrm{DerivedKeySize}\). نطلق على النتيجة \(\mathrm{DerivedKey}\).

تقسيم الرسالة

سيتم تقسيم الرسالة \(\mathrm{Msg}\) إلى أجزاء: \(\mathrm{Msg} = M_0 \| M_1 \| \cdots \| M_{n-1}\).

وتم اختيار طولها لتلبية:

  • \(\mathrm{len}(M_0) \in \{0,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{len}(\mathrm{Header}) - \mathrm{16}\}\).
  • إذا \(n>1\)، ثم \(\mathrm{len}(M_1), \ldots, \mathrm{len}(M_{n-1}) \in \{1,\ldots, \mathrm{CiphertextSegmentSize} - \mathrm{16}\}\).
  • إذا كانت قيمة \(n>1\)، \(\mathrm{len}(M_{0}), \ldots, \mathrm{len}(M_{n-2})\) يجب أن تتضمّن الحد الأقصى للطول وفقًا لما سبق وفقًا للقيود.

\(n\) قد يكون الحد الأقصى \(2^{32}\). وإلا، سيتعذّر التشفير.

تشفير الوحدات

لتشفير شريحة \(M_i\)، نحسب \(\mathrm{IV}_i := \mathrm{NoncePrefix} \| \mathrm{i} \| b\)، حيث تكون \(\mathrm{i}\) هي 4 بايت بترميز واسع النطاق والبايت $b$ يساوي 0x00 إذا كانت $i < n-1$ أو 0x01 بخلاف ذلك.

بعد ذلك، يتم التشفير \(M_i\) باستخدام AES-GCM4، حيث يكون المفتاح \(\mathrm{DerivedKey}\)ومتّجه الإعداد \(\mathrm{IV}_i\)، وتكون البيانات المرتبطة به السلسلة الفارغة. \(C_i\) هي نتيجة هذا التشفير (أي تسلسل \(C\) و \(T\) في القسم 5.2.1.2 من مرجع AES-GCM المرتبط).

إنشاء سلسلة للأجزاء المشفّرة

وأخيرًا، يتم إجراء تسلسل لكل المقاطع على النحو \(\mathrm{Header} \| C_0 \| \cdots \| C_{n-1}\)، وهو النص المشفر النهائي.

فك التشفير

يعمل فك التشفير على عكس التشفير. ونستخدم العنوان للحصول على \mathrm{NoncePrefix}$$، وفك تشفير كل قطاع من النص المشفر على حدة.

قد تسمح واجهات برمجة التطبيقات (وعادةً ما تتيح) بالوصول العشوائي أو الوصول إلى بداية الملف بدون فحص نهاية الملف. هذا مقصود، لأنه من الممكن فك تشفير \(M_i\) من \(C_i\)، بدون فك تشفير جميع كتل النص المشفر السابقة والمتبقية.

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

تسلسل وتحليل المفاتيح

لإنشاء تسلسل لمفتاح بتنسيق "Tink Proto"، نربط أولاً المعلمات بالطريقة الواضحة بالنموذج الأوّلي المقدَّم في aes_gcm_hkdf_streaming.proto. يجب ضبط الحقل version على 0. بعد ذلك، ننشئ تسلسلاً لذلك باستخدام تسلسل أولي عادي، ونضمّن السلسلة الناتجة في قيمة حقل نموذج KeyData. نُعيِّن الحقل type_url على type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey. وقد ضبطنا العلامة key_material_type على SYMMETRIC ونضمّنها في مجموعة مفاتيح. نضبط عادةً قيمة output_prefix_type على RAW. والاستثناء هو أنه إذا تم تحليل المفتاح مع ضبط قيمة مختلفة لـ output_prefix_type، قد يكتب Tink إما RAW أو القيمة السابقة.

لتحليل مفتاح، نعكس العملية المذكورة أعلاه (بالطريقة المعتادة عند تحليل النماذج الأوّلية). يتم تجاهل الحقل key_material_type. ويمكن تجاهل قيمة output_prefix_type، أو يمكن رفض المفاتيح التي تتضمّن output_prefix_type مختلفة عن RAW. يجب رفض المفاتيح التي تحتوي على قيمة version مختلفة عن 0.

المشاكل المعروفة

ليس من المتوقع أن تكون عمليات تنفيذ وظيفة التشفير المذكورة أعلاه آمنة تمامًا. يُرجى الاطّلاع على سلامة الشوكة.

المراجع


  1. هوانغ، ريهانيتابار، روغاواي، فيزار، 2015. التشفير الذي تمت مصادقته على الإنترنت ومقاومته لإساءة الاستخدام غير القابلة لإعادة الاستخدام مستند CRYPTO 2015. https://eprint.iacr.org/2015/189 

  2. هوانغ، شين، 2020. أمان تشفير البث في مكتبة تينك من Google. https://eprint.iacr.org/2020/1019 

  3. RFC 5869. دالة اشتقاق المفاتيح المستندة إلى بروتوكول HMAC وتوسيع نطاقها (HKDF). https://www.rfc-editor.org/rfc/rfc5869 

  4. معيار NIST SP 800-38D. اقتراح لحظر أوضاع التشفير: Galois/الوضع المضاد (GCM) وGMAC. https://csrc.nist.gov/pubs/sp/800/38/d/final