APK Signature Scheme v2 هو نظام توقيع ملف كامل يزيد من سرعة التحقق ويعزز ضمانات السلامة من خلال اكتشاف أي تغييرات في الأجزاء المحمية من APK.
يؤدي التوقيع باستخدام APK Signature Scheme v2 إلى إدراج كتلة تسجيل APK في ملف APK مباشرة قبل قسم ZIP Central Directory. داخل كتلة توقيع APK، يتم تخزين توقيعات v2 ومعلومات هوية المُوقع في كتلة APK Signature Scheme v2 Block .
الشكل 1. APK قبل وبعد التوقيع
تم تقديم APK Signature Scheme v2 في Android 7.0 (Nougat). لجعل APK قابلاً للتثبيت على Android 6.0 (Marshmallow) والأجهزة الأقدم، يجب توقيع APK باستخدام توقيع JAR قبل التوقيع باستخدام نظام v2.
للحفاظ على التوافق مع الإصدارات السابقة مع تنسيق 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 بواسطة واحد أو أكثر من الموقعين/الهويات، ويتم تمثيل كل منهم بمفتاح توقيع. يتم تخزين هذه المعلومات ككتلة 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
مسبوقة بالطول :-
signature algorithm ID
(uint32) -
digest
(بادئة بالطول) - راجع المحتويات المحمية بالتكامل
-
- تسلسل ذو بادئة طولية
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 من أربعة أقسام:
- محتويات إدخالات ZIP (من الإزاحة 0 حتى بداية حظر توقيع APK)
- حظر توقيع APK
- الرمز البريدي الدليل المركزي
- ZIP نهاية الدليل المركزي
الشكل 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. يتم حساب الملخص بطريقة مجزأة لتمكين تسريع الحساب من خلال موازنته.
الشكل 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.
الشكل 4. عملية التحقق من توقيع APK (الخطوات الجديدة باللون الأحمر)
- حدد موقع كتلة توقيع APK وتحقق مما يلي:
- يحتوي حقلا حجم APK Signing Block على نفس القيمة.
- يتبع ZIP Central Directory مباشرة سجل ZIP End of Central Directory.
- ZIP End of Central Directory لا يتبعه المزيد من البيانات.
- حدد موقع أول كتلة APK Signature Scheme v2 داخل كتلة توقيع APK. إذا كان حظر v2 موجودًا، فانتقل إلى الخطوة 3. وإلا فارجع إلى التحقق من APK باستخدام مخطط v1 .
- لكل
signer
في كتلة APK Signature Scheme v2:- اختر أقوى
signature algorithm ID
المدعوم منsignatures
. يعتمد ترتيب القوة على كل إصدار تنفيذ/نظام أساسي. - التحقق من
signature
المقابل منsignatures
مقابلsigned data
باستخدامpublic key
. (أصبح الآن من الآمن تحليلsigned data
.) - تأكد من أن القائمة المرتبة لمعرفات خوارزمية التوقيع في
digests
signatures
متطابقة. (هذا لمنع تجريد/إضافة التوقيع.) - قم بحساب ملخص محتويات APK باستخدام نفس خوارزمية الملخص مثل خوارزمية الملخص التي تستخدمها خوارزمية التوقيع.
- تأكد من أن الملخص المحسوب مطابق
digest
المقابل منdigests
. - تحقق من أن SubjectPublicKeyInfo
certificate
الأولىcertificates
مطابقpublic key
.
- اختر أقوى
- تنجح عملية التحقق إذا تم العثور على
signer
واحد على الأقل ونجحت الخطوة 3 لكلsigner
تم العثور عليه.
ملاحظة : يجب عدم التحقق من APK باستخدام نظام v1 في حالة حدوث فشل في الخطوة 3 أو 4.
ملف APK الموقّع بواسطة JAR هو ملف JAR موقّع قياسي ، والذي يجب أن يحتوي بالضبط على الإدخالات المدرجة في META-INF/MANIFEST.MF وحيث يجب توقيع جميع الإدخالات بواسطة نفس مجموعة الموقعين. ويتم التحقق من سلامتها على النحو التالي:
- يتم تمثيل كل موقّع بواسطة إدخال JAR META-INF/<signer>.SF وMETA-INF/<signer>.(RSA|DSA|EC).
- <signer>.(RSA|DSA|EC) هو PKCS #7 CMS ContentInfo مع بنية SignedData التي تم التحقق من توقيعها عبر ملف <signer>.SF.
- يحتوي ملف <signer>.SF على ملخص ملف كامل لـ META-INF/MANIFEST.MF وملخصات لكل قسم من META-INF/MANIFEST.MF. تم التحقق من ملخص الملف بالكامل لـ MANIFEST.MF. إذا فشل ذلك، فسيتم التحقق من ملخص كل مقطع MANIFEST.MF بدلاً من ذلك.
- يحتوي META-INF/MANIFEST.MF، لكل إدخال JAR محمي بالسلامة، على قسم مسمى يحتوي على ملخص محتويات الإدخال غير المضغوطة. يتم التحقق من كل هذه الملخصات.
- يفشل التحقق من APK إذا كان APK يحتوي على إدخالات JAR غير مدرجة في MANIFEST.MF وليست جزءًا من توقيع JAR.
وبالتالي فإن سلسلة الحماية هي <signer>.(RSA|DSA|EC) -> <signer>.SF -> MANIFEST.MF -> محتويات كل إدخال JAR محمي بالسلامة.