مجموعات مفاتيح

يستخدم Tink مجموعات المفاتيح لتفعيل دوران المفاتيح. رسميًا، تكون مجموعة المفاتيح عبارة عن قائمة غير فارغة1 من المفاتيح يتم فيها تحديد مفتاح واحد كمفتاح أساسي (المفتاح الذي يتم استخدامه على سبيل المثال لتوقيع نصوص عادية جديدة وتشفيرها). بالإضافة إلى ذلك، تحصل المفاتيح في مجموعة المفاتيح على معرّف فريد2 وحالة مفتاح تسمح بإيقاف المفاتيح بدون إزالتها من مجموعة المفاتيح.

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

مثال: AEAD

فكر في مجموعة مفاتيح AEAD، والتي تحتوي على مفاتيح متعددة للنموذج الأساسي AEAD. كما شرحنا في السابق، يحدّد كل مفتاح دالتَين بشكل فريد: \(\mathrm{Enc}\) و \(\mathrm{Dec}\). تحدد مجموعة المفاتيح الآن دالتَين جديدتَين: \(\mathrm{Enc}\) و \(\mathrm{Dec}\) - \(\mathrm{Enc}\) ببساطة تساوي وظيفة \(\mathrm{Enc}\) المفتاح الأساسي لمجموعة المفاتيح، بينما تحاول الدالة \(\mathrm{Dec}\) فك تشفير جميع المفاتيح، من خلال المرور بها بترتيب معيّن (انظر أدناه لمعرفة كيفية تحسين Tink لأداء هذه المفاتيح).

من المهم ملاحظة أن مجموعات المفاتيح هي مفاتيح كاملة: وهي تصف وصفًا كاملاً للدوال \(\mathrm{Enc}\) و\(\mathrm{Dec}\) المستخدمة. وهذا يعني أنه يمكن للمستخدمين كتابة فئة تأخذ KeysetHandle كتعبير عن فكرة أنّ الفئة بحاجة إلى وصف كامل للكائنات \(\mathrm{Enc}\) و \(\mathrm{Dec}\) لتعمل بشكل صحيح. يتيح ذلك للمستخدم كتابة واجهات برمجة تطبيقات توضِّح ما يلي: لاستخدام هذا الفئة، عليك تقديم وصف أول للتشفير.

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

لنفترض أن أحد مستخدمي Tink يكتب برنامجًا يحصل أولاً على مجموعة مفاتيح من KMS، ثم ينشئ كائن AEAD من مجموعة المفاتيح هذه، وفي النهاية يستخدم هذا الكائن لتشفير النصوص المشفَّرة وفك تشفيرها.

يتم إعداد مثل هذا المستخدم تلقائيًا لتدوير المفاتيح؛ والتبديل بين الخوارزميات في حالة عدم تلبية اختياره الحالي للمعيار بعد الآن.

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

معرّفات المفاتيح في النصوص المشفرة

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

ولهذا السبب، يسمح Tink ببادئة النصوص المشفرة بسلسلة 5 بايت مشتقة من المعرف. ووفقًا لفلسفة "المفاتيح الكاملة" أعلاه، تُعَدّ هذه البادئة جزءًا من المفتاح، ويجب أن تحتوي جميع النصوص المشفَّرة التي تم اشتقاقها مع هذا المفتاح على هذه البادئة. عندما ينشئ المستخدمون المفاتيح، يمكنهم اختيار ما إذا كان ينبغي استخدام المفتاح مثل هذه البادئة، أو ما إذا كان يجب استخدام تنسيق النص المُشفر بدونه.

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

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


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

  2. للتوافق مع مكتبة Google الداخلية، يسمح Tink بوجود مجموعات مفاتيح يتم تكرار المعرفات فيها. ستتم إزالة هذا الدعم في المستقبل.