الإصدار 2 من مخطّط توقيع حزمة APK

APK Signature Scheme v2 هو نظام توقيع ملف كامل يزيد من سرعة التحقق ويعزز ضمانات السلامة من خلال اكتشاف أي تغييرات في الأجزاء المحمية من APK.

يؤدي التوقيع باستخدام APK Signature Scheme v2 إلى إدراج كتلة تسجيل APK في ملف APK مباشرة قبل قسم ZIP Central Directory. داخل كتلة توقيع APK، يتم تخزين توقيعات v2 ومعلومات هوية المُوقع في كتلة APK Signature Scheme v2 Block .

APK قبل وبعد التوقيع

الشكل 1. APK قبل وبعد التوقيع

تم تقديم APK Signature Scheme v2 في Android 7.0 (Nougat). لجعل APK قابلاً للتثبيت على Android 6.0 (Marshmallow) والأجهزة الأقدم، يجب توقيع APK باستخدام توقيع JAR قبل التوقيع باستخدام نظام v2.

حظر توقيع APK

للحفاظ على التوافق مع الإصدارات السابقة مع تنسيق v1 APK، يتم تخزين توقيعات v2 وAPK الأحدث داخل كتلة توقيع APK، وهي حاوية جديدة تم تقديمها لدعم APK Signature Scheme v2. في ملف APK، توجد كتلة توقيع APK مباشرةً قبل دليل ZIP المركزي، والذي يقع في نهاية الملف.

تحتوي الكتلة على أزواج قيمة معرف ملفوفة بطريقة تجعل من السهل تحديد موقع الكتلة في APK. يتم تخزين توقيع v2 لـ APK كزوج قيمة معرف بالمعرف 0x7109871a.

شكل

تنسيق كتلة توقيع APK هو كما يلي (جميع الحقول الرقمية ذات نهاية صغيرة):

  • size of block بالبايت (باستثناء هذا الحقل) (uint64)
  • تسلسل أزواج قيمة المعرف ذات البادئة الطول uint64:
    • ID (uint32)
    • value (طول متغير: طول الزوج - 4 بايت)
  • size of block بالبايت - نفس الحقل الأول (uint64)
  • magic "APK Sig Block 42" (16 بايت)

يتم تحليل APK من خلال العثور أولاً على بداية دليل ZIP المركزي (من خلال العثور على سجل ZIP End of Central Directory في نهاية الملف، ثم قراءة إزاحة بداية الدليل المركزي من السجل). توفر القيمة magic طريقة سريعة لإثبات أن ما يسبق الدليل المركزي هو على الأرجح حظر توقيع APK. يشير size of block بكفاءة إلى بداية الكتلة في الملف.

يجب تجاهل أزواج قيمة المعرف ذات المعرفات غير المعروفة عند تفسير الكتلة.

كتلة مخطط توقيع APK v2

يتم توقيع APK بواسطة واحد أو أكثر من الموقعين/الهويات، ويتم تمثيل كل منهم بمفتاح توقيع. يتم تخزين هذه المعلومات ككتلة APK Signature Scheme v2 Block. يتم تخزين المعلومات التالية لكل موقع:

  • (خوارزمية التوقيع، الملخص، التوقيع) الصفوف. يتم تخزين الملخص لفصل التحقق من التوقيع عن التحقق من سلامة محتويات APK.
  • سلسلة شهادات X.509 تمثل هوية المُوقع.
  • سمات إضافية كأزواج قيمة المفتاح.

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

شكل

يتم تخزين كتلة APK Signature Scheme v2 داخل كتلة توقيع APK تحت المعرف 0x7109871a .

تنسيق APK Signature Scheme v2 Block هو كما يلي (جميع القيم الرقمية ذات نهاية صغيرة، وجميع الحقول ذات البادئة الطول تستخدم uint32 للطول):

  • تسلسل مسبوق بالطول signer ذي البادئة الطول :
    • signed data ذات البادئة الطولية:
      • تسلسل مسبوق بالطول من digests مسبوقة بالطول :
      • تسلسل ذو بادئة طولية certificates X.509 :
        • certificate X.509 ذات بادئة طولية (نموذج ASN.1 DER)
      • تسلسل مسبوق بالطول additional attributes مسبوقة بالطول :
        • ID (uint32)
        • value (طول متغير: طول السمة الإضافية - 4 بايت)
    • تسلسل مسبوق بالطول من signatures مسبوقة بالطول :
      • signature algorithm ID (uint32)
      • signature ببادئة الطول على signed data
    • public key ذو البادئة الطولية (SubjectPublicKeyInfo، نموذج ASN.1 DER)

معرفات خوارزمية التوقيع

  • 0x0101 — RSASSA-PSS مع ملخص SHA2-256، SHA2-256 MGF1، 32 بايت من الملح، مقطورة: 0xbc
  • 0x0102 — RSASSA-PSS مع ملخص SHA2-512، SHA2-512 MGF1، 64 بايت من الملح، مقطورة: 0xbc
  • 0x0103 — RSASSA-PKCS1-v1_5 مع ملخص SHA2-256. هذا مخصص لأنظمة البناء التي تتطلب توقيعات حتمية.
  • 0x0104 — RSASSA-PKCS1-v1_5 مع ملخص SHA2-512. هذا مخصص لأنظمة البناء التي تتطلب توقيعات حتمية.
  • 0x0201—ECDSA مع ملخص SHA2-256
  • 0x0202—ECDSA مع ملخص SHA2-512
  • 0x0301 — DSA مع ملخص SHA2-256

يتم دعم جميع خوارزميات التوقيع المذكورة أعلاه بواسطة نظام Android الأساسي. قد تدعم أدوات التوقيع مجموعة فرعية من الخوارزميات.

أحجام المفاتيح المدعومة ومنحنيات EC:

  • آر إس إيه: 1024، 2048، 4096، 8192، 16384
  • المفوضية الأوروبية: نيست P-256، P-384، P-521
  • دسا: 1024، 2048، 3072

محتويات محمية بالنزاهة

لأغراض حماية محتويات APK، يتكون APK من أربعة أقسام:

  1. محتويات إدخالات ZIP (من الإزاحة 0 حتى بداية حظر توقيع APK)
  2. حظر توقيع APK
  3. الرمز البريدي الدليل المركزي
  4. ZIP نهاية الدليل المركزي

أقسام APK بعد التوقيع

الشكل 2. أقسام APK بعد التوقيع

يحمي APK Signature Scheme v2 سلامة الأقسام 1 و3 و4 وكتل signed data في كتلة APK Signature Scheme v2 الموجودة داخل القسم 2.

تتم حماية سلامة الأقسام 1 و3 و4 من خلال ملخص واحد أو أكثر لمحتوياتها المخزنة في كتل signed data والتي تكون بدورها محمية بتوقيع واحد أو أكثر.

يتم حساب الملخص على الأقسام 1 و3 و4 على النحو التالي، على غرار شجرة Merkle ذات المستويين. يتم تقسيم كل قسم إلى أجزاء متتالية بحجم 1 ميجابايت ( 220 بايت). قد تكون القطعة الأخيرة في كل قسم أقصر. يتم حساب ملخص كل قطعة عبر تسلسل البايتة 0xa5 وطول القطعة بالبايت (uint32-endian الصغير) ومحتويات القطعة. يتم حساب ملخص المستوى الأعلى من خلال تسلسل البايت 0x5a وعدد القطع (النهاية الصغيرة uint32) وتسلسل ملخصات القطع بالترتيب الذي تظهر به القطع في APK. يتم حساب الملخص بطريقة مجزأة لتمكين تسريع الحساب من خلال موازنته.

ملخص APK

الشكل 3. ملخص APK

حماية القسم 4 (ZIP End of Central Directory) معقدة بسبب القسم الذي يحتوي على إزاحة ZIP Central Directory. تتغير الإزاحة عندما يتغير حجم كتلة توقيع APK، على سبيل المثال، عند إضافة توقيع جديد. وبالتالي، عند حساب الملخص عبر ZIP End of Central Directory، يجب التعامل مع الحقل الذي يحتوي على إزاحة ZIP Central Directory على أنه يحتوي على إزاحة كتلة توقيع APK.

الحماية من التراجع

قد يحاول أحد المهاجمين التحقق من ملف APK المُوقع بواسطة v2 باعتباره ملف APK المُوقع بواسطة v1 على أنظمة Android الأساسية التي تدعم التحقق من APK المُوقع بواسطة v2. للتخفيف من هذا الهجوم، يجب أن تحتوي ملفات APK الموقعة بواسطة v2 والتي تم توقيعها أيضًا بواسطة v1 على سمة X-Android-APK-Signed في القسم الرئيسي لملفات META-INF/*.SF الخاصة بها. قيمة السمة عبارة عن مجموعة مفصولة بفواصل من معرفات نظام توقيع APK (معرف هذا المخطط هو 2). عند التحقق من توقيع v1، يلزم أداة التحقق من APK لرفض ملفات APK التي لا تحتوي على توقيع لنظام توقيع APK الذي يفضله أداة التحقق من هذه المجموعة (على سبيل المثال، مخطط v2). تعتمد هذه الحماية على حقيقة أن محتويات ملفات META-INF/*.SF محمية بتوقيعات v1. راجع القسم الخاص بالتحقق من APK الموقّع بواسطة JAR .

قد يحاول أحد المهاجمين إزالة التوقيعات الأقوى من كتلة APK Signature Scheme v2 Block. للتخفيف من هذا الهجوم، يتم تخزين قائمة معرفات خوارزمية التوقيع التي تم توقيع APK بها في كتلة signed data والمحمية بواسطة كل توقيع.

تَحَقّق

في Android 7.0 والإصدارات الأحدث، يمكن التحقق من ملفات APK وفقًا لنظام توقيع APK الإصدار 2+ أو توقيع JAR (مخطط الإصدار 1). تتجاهل الأنظمة الأساسية الأقدم توقيعات v2 وتتحقق فقط من توقيعات v1.

عملية التحقق من توقيع APK

الشكل 4. عملية التحقق من توقيع APK (الخطوات الجديدة باللون الأحمر)

التحقق من نظام توقيع APK v2

  1. حدد موقع كتلة توقيع APK وتحقق مما يلي:
    1. يحتوي حقلا حجم APK Signing Block على نفس القيمة.
    2. يتبع ZIP Central Directory مباشرة سجل ZIP End of Central Directory.
    3. ZIP End of Central Directory لا يتبعه المزيد من البيانات.
  2. حدد موقع أول كتلة APK Signature Scheme v2 داخل كتلة توقيع APK. إذا كان حظر v2 موجودًا، فانتقل إلى الخطوة 3. وإلا فارجع إلى التحقق من APK باستخدام مخطط v1 .
  3. لكل signer في كتلة APK Signature Scheme v2:
    1. اختر أقوى signature algorithm ID المدعوم من signatures . يعتمد ترتيب القوة على كل إصدار تنفيذ/نظام أساسي.
    2. التحقق من signature المقابل من signatures مقابل signed data باستخدام public key . (أصبح الآن من الآمن تحليل signed data .)
    3. تأكد من أن القائمة المرتبة لمعرفات خوارزمية التوقيع في digests signatures متطابقة. (هذا لمنع تجريد/إضافة التوقيع.)
    4. قم بحساب ملخص محتويات APK باستخدام نفس خوارزمية الملخص مثل خوارزمية الملخص التي تستخدمها خوارزمية التوقيع.
    5. تأكد من أن الملخص المحسوب مطابق digest المقابل من digests .
    6. تحقق من أن SubjectPublicKeyInfo certificate الأولى certificates مطابق public key .
  4. تنجح عملية التحقق إذا تم العثور على signer واحد على الأقل ونجحت الخطوة 3 لكل signer تم العثور عليه.

ملاحظة : يجب عدم التحقق من APK باستخدام نظام v1 في حالة حدوث فشل في الخطوة 3 أو 4.

التحقق من ملف APK المُوقع بواسطة JAR (مخطط الإصدار 1)

ملف APK الموقّع بواسطة JAR هو ملف JAR موقّع قياسي ، والذي يجب أن يحتوي بالضبط على الإدخالات المدرجة في META-INF/MANIFEST.MF وحيث يجب توقيع جميع الإدخالات بواسطة نفس مجموعة الموقعين. ويتم التحقق من سلامتها على النحو التالي:

  1. يتم تمثيل كل موقّع بواسطة إدخال JAR META-INF/<signer>.SF وMETA-INF/<signer>.(RSA|DSA|EC).
  2. <signer>.(RSA|DSA|EC) هو PKCS #7 CMS ContentInfo مع بنية SignedData التي تم التحقق من توقيعها عبر ملف <signer>.SF.
  3. يحتوي ملف <signer>.SF على ملخص ملف كامل لـ META-INF/MANIFEST.MF وملخصات لكل قسم من META-INF/MANIFEST.MF. تم التحقق من ملخص الملف بالكامل لـ MANIFEST.MF. إذا فشل ذلك، فسيتم التحقق من ملخص كل مقطع MANIFEST.MF بدلاً من ذلك.
  4. يحتوي META-INF/MANIFEST.MF، لكل إدخال JAR محمي بالسلامة، على قسم مسمى يحتوي على ملخص محتويات الإدخال غير المضغوطة. يتم التحقق من كل هذه الملخصات.
  5. يفشل التحقق من APK إذا كان APK يحتوي على إدخالات JAR غير مدرجة في MANIFEST.MF وليست جزءًا من توقيع JAR.

وبالتالي فإن سلسلة الحماية هي <signer>.(RSA|DSA|EC) -> <signer>.SF -> MANIFEST.MF -> محتويات كل إدخال JAR محمي بالسلامة.