طرح امضای APK نسخه 4

اندروید ۱۱ از یک طرح امضای سازگار با استریمینگ با طرح امضای APK نسخه ۴ پشتیبانی می‌کند. امضای v4 بر اساس درخت هش مرکل محاسبه شده روی تمام بایت‌های APK است. این طرح دقیقاً از ساختار درخت هش fs-verity پیروی می‌کند (برای مثال، صفرگذاری salt و صفرگذاری آخرین بلوک). اندروید ۱۱ امضا را در یک فایل جداگانه، <apk name>.apk.idsig ذخیره می‌کند. امضای v4 به یک امضای مکمل v2 یا v3 نیاز دارد.

فرمت فایل

تمام فیلدهای عددی در little endian هستند. تمام فیلدها دقیقاً به اندازه sizeof() خود بایت اشغال می‌کنند، بدون اینکه هیچگونه padding یا ترازبندی ضمنی اضافه شود.

ساختار کمکی زیر تعاریف را ساده می‌کند:

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 از بلوک امضای نسخه ۳ فایل APK گرفته می‌شود. اگر این بلوک وجود نداشته باشد، از بلوک نسخه ۲ گرفته می‌شود (به 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;
};

merkle_tree کل درخت مرکل APK است که طبق توضیحات موجود در مستندات fs-verity محاسبه می‌شود.

تولیدکنندگان و مصرف‌کنندگان

ابزار apksigner Android SDK اگر آن را با پارامترهای پیش‌فرض اجرا کنید، فایل امضای v4 را تولید می‌کند. می‌توانید امضای v4 را مانند سایر طرح‌های امضا غیرفعال کنید. این ابزار همچنین می‌تواند تأیید کند که آیا امضای v4 معتبر است یا خیر.

adb انتظار دارد که هنگام اجرای دستور adb install --incremental فایل .apk.idsig در کنار فایل APK وجود داشته باشد. adb همچنین به طور پیش‌فرض از فایل IDSIG برای نصب تدریجی استفاده می‌کند و در صورت عدم وجود یا نامعتبر بودن آن، به نصب معمولی برمی‌گردد.

وقتی یک جلسه نصب ایجاد می‌شود، API نصب استریمینگ جدید در PackageInstaller هنگام اضافه کردن یک فایل به جلسه، امضای نسخه ۴ حذف‌شده را به عنوان یک آرگومان جداگانه می‌پذیرد. در این مرحله، signing_info به عنوان یک blob کامل به IncFS ارسال می‌شود. IncFS هش ریشه را از blob استخراج می‌کند.

وقتی جلسه نصب در حال انجام است، PackageManagerService یک فراخوانی ioctl انجام می‌دهد تا بلوک signing_info را از IncFS بازیابی کند، آن را تجزیه و امضا را تأیید کند.

کامپوننت Incremental Data Loader بخش درخت مرکل امضا را از طریق API بومی بارگذار داده، استریم می‌کند. دستور shell سرویس package install-incremental فایل امضای حذف‌شده v4 که به صورت Base64 کدگذاری شده است را به عنوان پارامتر برای هر فایل اضافه شده می‌پذیرد. درخت مرکل مربوطه باید به stdin دستور ارسال شود.

apk_digest

apk_digest اولین خلاصه محتوای موجود به ترتیب است:

  1. نسخه 3، بلوک 1 مگابایت، SHA2-512 ( CONTENT_DIGEST_CHUNKED_SHA512 )
  2. نسخه ۳، بلوک ۴ کیلوبایتی، SHA2-256 ( CONTENT_DIGEST_VERITY_CHUNKED_SHA256 )
  3. نسخه ۳، بلوک ۱ مگابایتی، SHA2-256 ( CONTENT_DIGEST_CHUNKED_SHA256 )
  4. نسخه ۲، SHA2-512
  5. نسخه ۲، SHA2-256

به توالی پیشوند طولی امضاکننده با پیشوند طولی در طرح امضای APK نسخه ۳ مراجعه کنید.

اعتبارسنجی و آزمایش

فرآیند اعتبارسنجی APK نسخه ۴ در شکل زیر نشان داده شده است:

فرآیند اعتبارسنجی APK نسخه ۴

شکل ۱. فرآیند اعتبارسنجی APK نسخه ۴.

اعتبارسنجی پیاده‌سازی با استفاده از تست‌های واحد ویژگی و CTS:

  • CtsIncrementalInstallHostTestCases
  • /android/cts/hostsidetests/incrementalinstall

قالب امضا را آزمایش کنید

برای آزمایش قالب امضا، یک محیط ساخت راه‌اندازی کنید و تست‌های دستی زیر را اجرا کنید:

$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest

قالب امضا را با Android SDK (ADB و apksigner) آزمایش کنید

با استفاده از این فرآیند، فرمت امضا را با Android SDK آزمایش کنید:

  1. یک محیط ساخت راه‌اندازی کنید و مطمئن شوید که پیاده‌سازی IncFS را تکمیل کرده‌اید.
  2. نسخه نهایی را روی یک دستگاه فیزیکی یا شبیه‌ساز هدف فلش کنید.
  3. یک APK موجود ایجاد یا دریافت کنید و سپس یک کلید امضای اشکال‌زدایی ایجاد کنید.
  4. فایل APK را با فرمت امضای v4 از پوشه build-tools امضا و نصب کنید.

    علامت
    $ ./apksigner sign --ks debug.keystore game.apk

    نصب
    $ ./adb install game.apk

    کجا می‌توان این آزمایش‌ها را پیدا کرد
    /android/cts/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java