مخطط توقيع APK v4.0

يدعم Android 11 نظام توقيع متوافق مع البث مع APK Signature Scheme v4. يعتمد توقيع الإصدار 4 على شجرة تجزئة Merkle المحسوبة على جميع وحدات البايت في ملف APK. إنه يتبع بنية شجرة التجزئة fs-verity تمامًا (على سبيل المثال، حشوة صفرية للملح وحشوة صفرية للكتلة الأخيرة). يقوم Android 11 بتخزين التوقيع في ملف منفصل، <apk name>.apk.idsig يتطلب توقيع v4 توقيع v2 أو v3 تكميلي.

تنسيق الملف

جميع الحقول الرقمية مكتوبة بخط endian الصغير. تشغل جميع الحقول عدد البايتات بالضبط مثل sizeof() ، دون إضافة أي حشوة أو محاذاة ضمنية.

يوجد أدناه هيكل مساعد لتبسيط التعريفات.

template <class SizeT>
struct sized_bytes {
        SizeT size;
        byte bytes[size];
};

محتوى الملف الرئيسي:

struct V4Signature {
        int32 version; // only version 2 is supported as of now
        sized_bytes<int32> hashing_info;
        sized_bytes<int32> signing_info;
        sized_bytes<int32> merkle_tree;  // optional
};

hashing_info هي المعلمات المستخدمة لإنشاء شجرة التجزئة + التجزئة الجذرية:

struct hashing_info.bytes {
    int32 hash_algorithm;    // only 1 == SHA256 supported
    int8 log2_blocksize;     // only 12 (block size 4096) supported now
    sized_bytes<int32> salt; // used exactly as in fs-verity, 32 bytes max
    sized_bytes<int32> raw_root_hash; // salted digest of the first Merkle tree page
};

signing_info هو البنية التالية:

struct signing_info.bytes {
    sized_bytes<int32> apk_digest;  // used to match with the corresponding APK
    sized_bytes<int32> x509_certificate; // ASN.1 DER form
    sized_bytes<int32> additional_data; // a free-form binary data blob
    sized_bytes<int32> public_key; // ASN.1 DER, must match the x509_certificate
    int32 signature_algorithm_id; // see the APK v2 doc for the list
    sized_bytes<int32> signature;
};
  • apk_digest مأخوذ من كتلة التوقيع v3 لـ APK، أو، إذا لم يكن موجودًا، من كتلة v2 (راجع apk_digest )

لإنشاء رمز signature والتحقق منه، يجب إجراء تسلسل للبيانات التالية في ثنائي ثنائي ثنائي وتمريرها إلى خوارزمية التوقيع/التحقق باعتبارها البيانات الموقعة :

struct V4DataForSigning {
        int32 size;
        int64 file_size; // the size of the file that's been hashed.
        hashing_info.hash_algorithm;
        hashing_info.log2_blocksize;
        hashing_info.salt;
        hashing_info.raw_root_hash;
        signing_info.apk_digest;
        signing_info.x509_certificate;
        signing_info.additional_data;
};
  1. merkle_tree هي شجرة Merkle الكاملة لملف APK، ويتم حسابها كما هو موضح في وثائق fs-verity .

المنتجين والمستهلكين

تقوم أداة apksigner Android SDK الآن بإنشاء ملف التوقيع v4 إذا قمت بتشغيله باستخدام المعلمات الافتراضية. يمكن تعطيل توقيع v4 بنفس طريقة تعطيل أنظمة التوقيع الأخرى. ويمكنه أيضًا التحقق مما إذا كان توقيع v4 صالحًا.

يتوقع adb أن يكون الملف .apk.idsig موجودًا بجوار .apk عند تشغيل الأمر adb install --incremental
وسيستخدم أيضًا ملف .idsig لمحاولة التثبيت التزايدي افتراضيًا، وسيعود إلى التثبيت العادي إذا كان مفقودًا أو غير صالح.

عند إنشاء جلسة تثبيت، تقبل واجهة برمجة تطبيقات التثبيت المتدفق الجديدة في PackageInstaller توقيع v4 الذي تم تجريده كوسيطة منفصلة عند إضافة ملف إلى الجلسة. عند هذه النقطة، يتم تمرير signing_info إلى incfs كنقطة كاملة. يقوم Incfs باستخراج تجزئة الجذر من النقطة.

عندما يتم الالتزام بجلسة التثبيت، يقوم PackageManagerService بإجراء ioctl لاسترداد التوقيع الثنائي الكبير من incfs، وتحليله والتحقق من التوقيع.

من المتوقع أن يقوم مكون أداة تحميل البيانات التزايدية بتدفق جزء شجرة Merkle من التوقيع من خلال واجهة برمجة التطبيقات الأصلية لمحمل البيانات.
يقبل أمر تثبيت خدمة الحزمة package install-incremental ملف توقيع v4 المجرد والمشفر كـ base64 كمعلمة لكل ملف مضاف. يجب إرسال شجرة Merkle المقابلة إلى الأمر stdin .

apk_digest

apk_digest هو أول ملخص محتوى متاح بالترتيب:

  1. V3، كتلة 1 ميجابايت، SHA2-512 (CONTENT_DIGEST_CHUNKED_SHA512)،
  2. V3، كتلة 4 كيلو بايت، SHA2-256 (CONTENT_DIGEST_VERITY_CHUNKED_SHA256)،
  3. V3، كتلة 1 ميجابايت، SHA2-256 (CONTENT_DIGEST_CHUNKED_SHA256)،
  4. V2، SHA2-512،
  5. V2، SHA2-256.

راجع التسلسل البادئ بالطول للتوقيعات البادئة بالطول في APK Signature Scheme v3.

عملية التحقق من APK v4
الشكل 1 : عملية التحقق من APK الإصدار 4

التحقق من الصحة والاختبار

التحقق من صحة التنفيذ باستخدام اختبارات وحدة الميزات وCTS.

  • CtsIncrementalInstallHostTestCases
    • /android/cts/hostsidetests/incrementalinstall

اختبار تنسيق التوقيع

لاختبار تنسيق التوقيع، قم بإعداد بيئة تطوير وإجراء الاختبارات اليدوية التالية:

$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest

اختبار تنسيق التوقيع باستخدام Android SDK (ADB وapksigner)

لاختبار تنسيق التوقيع باستخدام Android SDK، قم بإعداد بيئة تطوير وتأكد من إكمال تنفيذ IncFS . ثم قم بتثبيت الإصدار على جهاز فعلي أو محاكي مستهدف. تحتاج إلى إنشاء ملف APK موجود أو الحصول عليه ثم إنشاء مفتاح توقيع تصحيح الأخطاء . أخيرًا، قم بتوقيع وتثبيت ملف APK بتنسيق التوقيع v4 من مجلد أدوات البناء.

لافتة

$ ./apksigner sign --ks debug.keystore game.apk

ثَبَّتَ

$ ./adb install game.apk

أين يمكن العثور على هذه الاختبارات؟

/android/cts/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java