APK Signature Scheme v2 היא סכימת חתימה של קובץ שלם שמגבירה את מהירות האימות ומחזקת ערבויות שלמות על ידי זיהוי כל שינוי בחלקים המוגנים של ה-APK.
חתימה באמצעות APK Signature Scheme v2 מכניסה בלוק חתימת APK לקובץ ה-APK מיד לפני הקטע של ZIP Central Directory. בתוך בלוק החתימה של APK, חתימות v2 ופרטי זהות החותם מאוחסנים ב- APK Signature Scheme v2 Block .
APK Signature Scheme v2 הוצג באנדרואיד 7.0 (Nougat). כדי להפוך APK להתקנה במכשירי אנדרואיד 6.0 (Marshmallow) ומעלה, יש לחתום על ה-APK באמצעות חתימת JAR לפני החתימה עם ערכת v2.
חסימת חתימת APK
כדי לשמור על תאימות לאחור עם פורמט ה-APK v1, חתימות APK v2 וחדש יותר מאוחסנות בתוך בלוק חתימת 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 Central Directory (על ידי מציאת רשומת ZIP End of Central Directory בסוף הקובץ, ולאחר מכן קריאת היסט ההתחלה של ה-Central Directory מהרשומה). ערך magic
מספק דרך מהירה לקבוע שמה שקודם ל-Central Directory הוא כנראה בלוק החתימה של APK. size of block
מצביע אז ביעילות על תחילת הבלוק בקובץ.
יש להתעלם מצמדי ערך מזהה עם מזהים לא ידועים בעת פירוש החסימה.
APK Signature Scheme v2 Block
APK חתום על ידי חתם/זהות אחד או יותר, כל אחד מיוצג על ידי מפתח חתימה. מידע זה מאוחסן כ-APK Signature Scheme v2 Block. עבור כל חותם, המידע הבא מאוחסן:
- (אלגוריתם חתימה, תקציר, חתימה) tuples. התקציר מאוחסן כדי לנתק את אימות החתימה מבדיקת תקינות התוכן של ה-APK.
- שרשרת תעודות X.509 המייצגת את זהותו של החותם.
- מאפיינים נוספים כצמדי מפתח-ערך.
עבור כל חותם, ה-APK מאומת באמצעות חתימה נתמכת מהרשימה המסופקת. מתעלמים מהחתימות עם אלגוריתמי חתימה לא ידועים. זה תלוי בכל יישום לבחור באיזו חתימה להשתמש כאשר נתקלים במספר חתימות נתמכות. זה מאפשר הכנסת שיטות חתימה חזקות יותר בעתיד באופן תואם לאחור. הגישה המוצעת היא לאמת את החתימה החזקה ביותר.
פוּרמָט
APK Signature Scheme v2 Block מאוחסן בתוך בלוק החתימה APK תחת המזהה 0x7109871a
.
הפורמט של בלוק ה-APK Signature Scheme v2 הוא כדלקמן (כל הערכים המספריים הם Little-endian, כל השדות עם קידומת אורך משתמשים ב-uint32 עבור האורך):
- רצף עם קידומת אורך של
signer
עם קידומת אורך:-
signed data
עם קידומת אורך:- רצף עם קידומת אורך של
digests
עם קידומת אורך:-
signature algorithm ID
(uint32) - (עם קידומת אורך)
digest
- ראה תוכן מוגן בשלמות
-
- רצף עם קידומת אורך של
certificates
X.509 :-
certificate
X.509 עם קידומת אורך (טופס DER ASN.1)
-
- רצף עם קידומת אורך של
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 digest, SHA2-256 MGF1, 32 בייטים של מלח, טריילר: 0xbc
- 0x0102—RSASSA-PSS עם SHA2-512 digest, 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
כל אלגוריתמי החתימה לעיל נתמכים על ידי פלטפורמת אנדרואיד. כלי חתימה עשויים לתמוך בתת-קבוצה של האלגוריתמים.
גדלי מפתחות נתמכים ועקומות EC:
- RSA: 1024, 2048, 4096, 8192, 16384
- EC: NIST P-256, P-384, P-521
- DSA: 1024, 2048, 3072
תוכן מוגן בשלמות
למטרות הגנה על תוכן APK, APK מורכב מארבעה חלקים:
- התוכן של ערכי ZIP (מהיסט 0 עד תחילת חסימת ה-APK)
- חסימת חתימת APK
- מדריך ZIP מרכזי
- ZIP סוף של ספרייה מרכזית
APK Signature Scheme v2 מגן על שלמות סעיפים 1, 3, 4, ובלוקי signed data
של בלוק APK Signature Scheme v2 הכלולים בסעיף 2.
תקינותם של סעיפים 1, 3 ו-4 מוגנת על ידי תקציר אחד או יותר של תוכנם המאוחסן בבלוק signed data
אשר, בתורם, מוגנים על ידי חתימה אחת או יותר.
התקציר על סעיפים 1, 3 ו-4 מחושב באופן הבא, בדומה לעץ מרקל דו-מפלסי. כל קטע מחולק לנתחים רצופים של 1 MB (2 20 בתים). הנתח האחרון בכל חלק עשוי להיות קצר יותר. התקציר של כל נתח מחושב על פני השרשור של byte 0xa5
, אורך הנתח בבתים (Uint32-little-endian), ותוכן הנתח. התקציר ברמה העליונה מחושב על-פי השרשור של byte 0x5a
, מספר הנתחים (ליטל-endian uint32), והשרשור של תקצירים של הנתחים לפי סדר הופעת הנתחים ב-APK. התקציר מחושב בצורה חתוכה כדי לאפשר להאיץ את החישוב על ידי הקבלה שלו.
ההגנה על סעיף 4 (ZIP End of Central Directory) מסובכת על ידי הסעיף המכיל את ההיסט של ZIP Central Directory. ההיסט משתנה כאשר גודל בלוק החתימה APK משתנה, למשל, כאשר מתווספת חתימה חדשה. לפיכך, כאשר מחשבים תקציר דרך ZIP End של Central Directory, יש להתייחס לשדה המכיל את ההיסט של ZIP Central Directory כמכיל את ההיסט של בלוק החתימה של APK.
הגנות לאחור
תוקף יכול לנסות לאמת APK עם חתימת v2 כ-APK עם חתימת v1 בפלטפורמות אנדרואיד התומכות באימות 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 Signature Scheme v2+ או חתימת JAR (סכימת v1). פלטפורמות ישנות יותר מתעלמות מחתימות v2 ומאמתות רק חתימות v1.
אימות APK Signature Scheme v2
- אתר את בלוק החתימה של APK וודא ש:
- שני שדות בגודל של APK Signing Block מכילים את אותו ערך.
- ZIP Central Directory מלווה מיד ב-ZIP End של רשומת ה-Central Directory.
- ZIP End of Central Directory אינו מלווה במידע נוסף.
- אתר את בלוק ה-APK Signature Scheme v2 הראשון בתוך בלוק החתימה APK. אם החסימה של v2 אם קיימת, המשך לשלב 3. אחרת, חזור לאימות ה-APK באמצעות סכימת v1 .
- עבור כל
signer
ב-APK Signature Scheme v2 Block:- בחר את
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 (סכימת v1)
ה-APK החתום על JAR הוא JAR חתום סטנדרטי , שחייב להכיל בדיוק את הערכים הרשומים ב- META-INF/MANIFEST.MF ושם כל הערכים חייבים להיות חתומים על ידי אותה קבוצה של חותמים. תקינותו מאומתת באופן הבא:
- כל חותם מיוצג על ידי ערך META-INF/<חותם>.SF ו- META-INF/<חותם>.(RSA|DSA|EC) JAR.
- <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 מוגן בשלמות.