ב-Android 11 יש תמיכה בסכימת חתימה שתואמת לסטרימינג באמצעות APK Signature Scheme v4. החתימה בגרסה 4 מבוססת על עץ גיבוב Merkle שמחושב על כל הבייטים של קובץ ה-APK. הוא עוקב בדיוק אחרי המבנה של עץ הגיבוב של fs-verity (לדוגמה, הוספת אפסים למלח והוספת אפסים לבלוק האחרון). ב-Android 11 החתימה מאוחסנת בקובץ נפרד, <apk name>.apk.idsig
חתימה בגרסה 4 מחייבת חתימה משלימה בגרסה 2 או 3.
תבנית קובץ
כל השדות המספריים הם בפורמט little 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
נלקח מבלוק החתימה של גרסה 3 של ה-APK, או, אם הוא לא קיים, מבלוק הגרסה 2 (ראו apk_digest)
כדי ליצור ולאמת קוד signature
, צריך לסדר את הנתונים הבאים ברצף ב-blob בינארי ולהעביר אותו לאלגוריתם החתימה או האימות בתור הנתונים החתומים:
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
הוא עץ Merkle המלא של ה-APK, שמחושב כפי שמתואר במסמכי העזרה של fs-verity.
יצרנים וצרכנים
apksigner
הכלי של Android SDK יוצר עכשיו את קובץ החתימה של V4 אם מפעילים אותו עם פרמטרים שמוגדרים כברירת מחדל. אפשר להשבית את החתימה של V4 באותו אופן שבו משביתים את שיטות החתימה האחרות. הוא יכול גם לאמת אם החתימה של V4 תקינה.
adb
מצפה שהקובץ apk.idsig יופיע לצד הקובץ apk כשמריצים את הפקודה adb install --incremental
הוא ישתמש גם בקובץ idsig. כברירת מחדל כדי לנסות התקנה מצטברת, ויעבור להתקנה רגילה אם הקובץ חסר או לא תקין.
כשיוצרים סשן התקנה, ה-API החדש להתקנה בסטרימינג ב-PackageInstaller
מקבל את החתימה של גרסה 4 ללא הנתונים הלא רלוונטיים כארגומנטים נפרדים כשמוסיפים קובץ לסשן.
בשלב הזה, signing_info
מועבר ל-incfs כ-blob שלם. Incfs מחלץ את גיבוב השורש מה-blob.
כשסשן ההתקנה מחויב, השירות PackageManagerService מבצע ioctl כדי לאחזר את ה-blob של signing_info
מ-incfs, לנתח אותו ולאמת את החתימה.
המרכיב של הטעינה המצטברת של נתונים אמור להעביר את החלק של עץ Merkle בחתימת ה-API המקורי של הטעינה של הנתונים.
package
הפקודה של מעטפת השירות install-incremental
מקבלת את קובץ החתימה של גרסה 4 שהוסר ממנו הקוד בקידוד base64, כפרמטר לכל קובץ שנוסף. יש לשלוח את עץ Merkle התואם ל-stdin
של הפקודה.
apk_digest
apk_digest
הוא סיכום התוכן הראשון שזמין בסדר הבא:
- V3, 1MB block, SHA2-512 (CONTENT_DIGEST_CHUNKED_SHA512),
- V3, בלוק של 4KB, SHA2-256 (CONTENT_DIGEST_VERITY_CHUNKED_SHA256),
- V3, בלוק של 1MB, SHA2-256 (CONTENT_DIGEST_CHUNKED_SHA256),
- V2, SHA2-512,
- V2, SHA2-256.
מידע נוסף זמין במאמר רצף עם קידומת אורך של חתימות עם קידומת אורך בסכמת החתימה של APK v3.

אימות ובדיקה
מאמתים את ההטמעה באמצעות בדיקות יחידה של תכונות ובדיקות CTS.
CtsIncrementalInstallHostTestCases
- /android/cts/hostsidetests/incrementalinstall
בדיקת הפורמט של החתימה
כדי לבדוק את פורמט החתימה, מגדירים סביבה לפיתוח ומריצים את הבדיקות הידניות הבאות:
$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest
בדיקת פורמט החתימה באמצעות Android SDK (ADB ו-apksigner)
כדי לבדוק את פורמט החתימה באמצעות Android SDK, צריך להגדיר סביבת פיתוח ולוודא שהשלמתם את ההטמעה של IncFS. לאחר מכן, מבצעים את הפלאש של ה-build במכשיר פיזי או במהדמה של היעד. צריך ליצור או לקבל קובץ APK קיים, ואז ליצור מפתח חתימה לניפוי באגים. לבסוף, חותמים על קובץ ה-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