بث 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 بايت بترميز big-endian و البايت $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"، نربط أولاً المَعلمات بالطريقة الواضحة في ملف proto الوارد في aes_gcm_hkdf_streaming.proto. يجب ضبط الحقل version على 0. بعد ذلك، نُسلسل هذا باستخدام تسلسل proto العادي، ونُضمِّن السلسلة الناتجة في قيمة حقل KeyData proto. لقد ضبطنا الحقل type_url على type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey. بعد ذلك، نضبط key_material_type على SYMMETRIC، ونضمّنه في مجموعة مفاتيح. نضبط عادةً output_prefix_type على RAW. ويُستثنى من ذلك إذا تم تحليل المفتاح مع ضبط قيمة مختلفة لـ output_prefix_type، قد يكتب Tink إما RAW أو القيمة السابقة.

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

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

من غير المتوقّع أن تكون عمليات تنفيذ دالة التشفير أعلاه آمنة من التشعب. راجِع مقالة أمان الإصدارات المشتقة.

المراجع


  1. Hoang, Reyhanitabar, Rogaway, Vizar, 2015. التشفير المُعتمَد على الإنترنت ومقاومة إساءة استخدام إعادة استخدام المفتاح المؤقت CRYPTO 2015. https://eprint.iacr.org/2015/189 

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

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

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