שלט בונה לשחרור

תמונות של מערכת ההפעלה אנדרואיד משתמשות בחתימות קריפטוגרפיות בשני מקומות:

  1. כל קובץ .apk בתוך התמונה חייב להיות חתום. מנהל החבילות של אנדרואיד משתמש בחתימת .apk בשתי דרכים:
    • כאשר אפליקציה מוחלפת, יש לחתום עליה באותו מפתח כמו האפליקציה הישנה על מנת לקבל גישה לנתוני האפליקציה הישנה. זה נכון הן לעדכון אפליקציות משתמש על ידי החלפת .apk והן לעקיפה של אפליקציית מערכת עם גרסה חדשה יותר המותקנת תחת /data .
    • אם שתי יישומים או יותר רוצים לשתף מזהה משתמש (כדי שיוכלו לשתף נתונים וכו'), יש לחתום עליהם עם אותו מפתח.
  2. חבילות עדכון OTA חייבות להיות חתומות באחד מהמפתחות שהמערכת צפויה להן, אחרת תהליך ההתקנה ידחה אותן.

שחרר את המקשים

עץ האנדרואיד כולל מפתחות בדיקה תחת build/target/product/security . בניית תמונת מערכת הפעלה אנדרואיד באמצעות make תחתום על כל קבצי .apk באמצעות מקשי הבדיקה. מכיוון שמפתחות הבדיקה ידועים בציבור, כל אחד יכול לחתום על קבצי apk משלו עם אותם מפתחות, מה שעשוי לאפשר לו להחליף או לחטוף אפליקציות מערכת המובנות בתמונת מערכת ההפעלה שלך. מסיבה זו, חיוני לחתום על כל תמונת מערכת הפעלה אנדרואיד שפורסמה או פרוסה בפומבי עם סט מיוחד של מפתחות שחרור שרק לך יש גישה אליהם.

כדי ליצור קבוצה ייחודית משלך של מפתחות שחרור, הפעל את הפקודות האלה מהשורש של עץ האנדרואיד שלך:

subject='/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
mkdir ~/.android-certs
for x in releasekey platform shared media networkstack; do \
    ./development/tools/make_key ~/.android-certs/$x "$subject"; \
  done

יש לשנות את $subject כדי לשקף את המידע של הארגון שלך. אתה יכול להשתמש בכל ספרייה, אבל היזהר לבחור מיקום מגובה ומאובטח. חלק מהספקים בוחרים להצפין את המפתח הפרטי שלהם עם ביטוי סיסמה חזק ולאחסן את המפתח המוצפן בבקרת המקור; אחרים מאחסנים את מפתחות השחרור שלהם במקום אחר לגמרי, כמו במחשב עם רווח אוויר.

כדי ליצור תמונת שחרור, השתמש ב:

make dist
sign_target_files_apks \
-o \    # explained in the next section
--default_key_mappings ~/.android-certs out/dist/*-target_files-*.zip \
signed-target_files.zip

הסקריפט sign_target_files_apks לוקח קובץ .zip של target כקלט ומייצר קובץ .zip של יעד חדש שבו כל קבצי ה- .apk נחתמו עם מפתחות חדשים. ניתן למצוא את התמונות החדשות שנחתמו תחת IMAGES/ ב- signed-target_files.zip .

חתום על חבילות OTA

ניתן להמיר zip של קבצי יעד חתום ל-zip חתום של עדכון OTA באמצעות ההליך הבא:
ota_from_target_files \
-k  (--package_key) 
signed-target_files.zip \
signed-ota_update.zip

חתימות והעמסת צד

טעינת צד אינה עוקפת את מנגנון אימות חתימת החבילה הרגיל של השחזור - לפני התקנת חבילה, השחזור יוודא שהיא חתומה עם אחד המפתחות הפרטיים התואמים למפתחות הציבוריים המאוחסנים במחיצת השחזור, בדיוק כפי שהיה קורה לחבילה שנמסרה מעל -אוויר.

חבילות עדכון המתקבלות מהמערכת הראשית מאומתות בדרך כלל פעמיים: פעם אחת על ידי המערכת הראשית, באמצעות שיטת RecoverySystem.verifyPackage() ב-Android API, ולאחר מכן שוב על ידי שחזור. ה-API של RecoverySystem בודק את החתימה מול מפתחות ציבוריים המאוחסנים במערכת הראשית, בקובץ /system/etc/security/otacerts.zip (כברירת מחדל). Recovery בודק את החתימה מול מפתחות ציבוריים המאוחסנים בדיסק RAM של מחיצת השחזור, בקובץ /res/keys .

כברירת מחדל, קובץ ה- .zip של המטרה שהופק על ידי ה-build מגדיר את אישור ה-OTA כך שיתאים למפתח הבדיקה. בתמונה שפורסמה, יש להשתמש באישור אחר כדי שמכשירים יוכלו לאמת את האותנטיות של חבילת העדכון. העברת הדגל -o ל- sign_target_files_apks , כפי שמוצג בסעיף הקודם, מחליפה את אישור מפתח הבדיקה באישור מפתח השחרור מספריית האישורים שלך.

בדרך כלל תמונת המערכת ותמונת השחזור מאחסנות את אותה קבוצה של מפתחות ציבוריים של OTA. על ידי הוספת מפתח רק לקבוצת מפתחות השחזור, ניתן לחתום על חבילות שניתן להתקין רק באמצעות טעינת צד (בהנחה שמנגנון הורדת העדכונים של המערכת הראשית מבצע אימות נכון מול otacerts.zip). אתה יכול לציין מפתחות נוספים שייכללו רק בשחזור על ידי הגדרת המשתנה PRODUCT_EXTRA_RECOVERY_KEYS בהגדרת המוצר שלך:

vendor/yoyodyne/tardis/products/tardis.mk
 [...]

PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload

זה כולל את vendor/yoyodyne/security/tardis/sideload.x509.pem בקובץ מפתחות השחזור כדי שיוכל להתקין חבילות חתומות איתו. עם זאת, המפתח הנוסף אינו כלול ב-otacerts.zip, כך שמערכות המאמתות כהלכה חבילות שהורדו אינן מפעילות שחזור עבור חבילות שנחתמו עם מפתח זה.

תעודות ומפתחות פרטיים

כל מפתח מגיע בשני קבצים: האישור , בעל הסיומת .x509.pem, והמפתח הפרטי , בעל הסיומת .pk8. המפתח הפרטי צריך להישמר בסוד ויש צורך לחתום על חבילה. המפתח עצמו עשוי להיות מוגן באמצעות סיסמה. התעודה, לעומת זאת, מכילה רק את המחצית הציבורית של המפתח, כך שניתן להפיץ אותה ברחבה. הוא משמש כדי לוודא שחבילה נחתמה על ידי המפתח הפרטי המתאים.

המבנה הסטנדרטי של אנדרואיד משתמש בחמישה מפתחות, שכולם נמצאים build/target/product/security :

מפתח בדיקה
מפתח ברירת מחדל כללי עבור חבילות שאינן מציינות מפתח אחרת.
פּלַטפוֹרמָה
מפתח בדיקה עבור חבילות שהן חלק מפלטפורמת הליבה.
מְשׁוּתָף
מפתח בדיקה עבור דברים המשותפים בתהליך הבית/אנשי הקשר.
כְּלֵי תִקְשׁוֹרֶת
מפתח בדיקה עבור חבילות שהן חלק ממערכת המדיה/הורדה.
מחסנית רשת
מפתח בדיקה עבור חבילות שהן חלק ממערכת הרשת. מפתח networkstack משמש לחתימה על קבצים בינאריים המעוצבים כרכיבי מערכת מודולריים . אם עדכוני המודול שלך בנויים בנפרד ומשולבים כמובנים מראש בתמונת המכשיר שלך, ייתכן שלא תצטרך ליצור מפתח Networkstack בעץ המקור של Android.

חבילות בודדות מציינות אחד מהמפתחות הללו על ידי הגדרת LOCAL_CERTIFICATE בקובץ Android.mk שלהם. (מפתח test משמש אם משתנה זה לא מוגדר.) אתה יכול גם לציין מפתח שונה לחלוטין לפי שם נתיב, למשל:

device/yoyodyne/apps/SpecialApp/Android.mk
 [...]

LOCAL_CERTIFICATE := device/yoyodyne/security/special

כעת ה-build משתמש במפתח device/yoyodyne/security/special.{x509.pem,pk8} כדי לחתום על SpecialApp.apk. ה-build יכול להשתמש רק במפתחות פרטיים שאינם מוגנים באמצעות סיסמה.

אפשרויות חתימה מתקדמות

החלפת מפתח חתימת APK

סקריפט החתימה sign_target_files_apks פועל על קבצי היעד שנוצרו עבור בנייה. כל המידע על אישורים ומפתחות פרטיים שבהם נעשה שימוש בזמן הבנייה כלול בקבצי היעד. בעת הפעלת סקריפט החתימה כדי לחתום לשחרור, ניתן להחליף מפתחות חתימה על סמך שם המפתח או שם ה-APK.

השתמש בדגלים --key_mapping ו --default_key_mappings כדי לציין החלפת מפתח על סמך שמות מפתח:

  • הדגל --key_mapping src_key = dest_key מציין את ההחלפה של מפתח אחד בכל פעם.
  • דגל --default_key_mappings dir מציין ספרייה עם חמישה מפתחות כדי להחליף את כל המפתחות ב- build/target/product/security ; זה שווה ערך לשימוש --key_mapping חמש פעמים כדי לציין את המיפויים.
build/target/product/security/testkey      = dir/releasekey
build/target/product/security/platform     = dir/platform
build/target/product/security/shared       = dir/shared
build/target/product/security/media        = dir/media
build/target/product/security/networkstack = dir/networkstack

השתמש בדגל --extra_apks apk_name1,apk_name2,... = key כדי לציין את החלפות מפתח החתימה על סמך שמות APK. אם key נשאר ריק, הסקריפט מתייחס ל-APKs שצוינו כחתומים מראש.

עבור מוצר tardis ההיפותטי, אתה צריך שישה מפתחות מוגני סיסמה: חמישה כדי להחליף את החמישה ב- build/target/product/security , ואחד כדי להחליף את device/yoyodyne/security/special נוסף הנדרש על-ידי SpecialApp בדוגמה למעלה. אם המפתחות היו בקבצים הבאים:

vendor/yoyodyne/security/tardis/releasekey.x509.pem
vendor/yoyodyne/security/tardis/releasekey.pk8
vendor/yoyodyne/security/tardis/platform.x509.pem
vendor/yoyodyne/security/tardis/platform.pk8
vendor/yoyodyne/security/tardis/shared.x509.pem
vendor/yoyodyne/security/tardis/shared.pk8
vendor/yoyodyne/security/tardis/media.x509.pem
vendor/yoyodyne/security/tardis/media.pk8
vendor/yoyodyne/security/tardis/networkstack.x509.pem
vendor/yoyodyne/security/tardis/networkstack.pk8
vendor/yoyodyne/security/special.x509.pem
vendor/yoyodyne/security/special.pk8           # NOT password protected
vendor/yoyodyne/security/special-release.x509.pem
vendor/yoyodyne/security/special-release.pk8   # password protected

אז תחתום על כל האפליקציות כך:

./build/make/tools/releasetools/sign_target_files_apks \
    --default_key_mappings vendor/yoyodyne/security/tardis \
    --key_mapping vendor/yoyodyne/security/special=vendor/yoyodyne/security/special-release \
    --extra_apks PresignedApp= \
    -o tardis-target_files.zip \
    signed-tardis-target_files.zip

זה מעלה את הדברים הבאים:

Enter password for vendor/yoyodyne/security/special-release key>
Enter password for vendor/yoyodyne/security/tardis/networkstack key>
Enter password for vendor/yoyodyne/security/tardis/media key>
Enter password for vendor/yoyodyne/security/tardis/platform key>
Enter password for vendor/yoyodyne/security/tardis/releasekey key>
Enter password for vendor/yoyodyne/security/tardis/shared key>
    signing: Phone.apk (vendor/yoyodyne/security/tardis/platform)
    signing: Camera.apk (vendor/yoyodyne/security/tardis/media)
    signing: NetworkStack.apk (vendor/yoyodyne/security/tardis/networkstack)
    signing: Special.apk (vendor/yoyodyne/security/special-release)
    signing: Email.apk (vendor/yoyodyne/security/tardis/releasekey)
        [...]
    signing: ContactsProvider.apk (vendor/yoyodyne/security/tardis/shared)
    signing: Launcher.apk (vendor/yoyodyne/security/tardis/shared)
NOT signing: PresignedApp.apk
        (skipped due to special cert string)
rewriting SYSTEM/build.prop:
  replace:  ro.build.description=tardis-user Eclair ERC91 15449 test-keys
     with:  ro.build.description=tardis-user Eclair ERC91 15449 release-keys
  replace: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/test-keys
     with: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/release-keys
    signing: framework-res.apk (vendor/yoyodyne/security/tardis/platform)
rewriting RECOVERY/RAMDISK/default.prop:
  replace:  ro.build.description=tardis-user Eclair ERC91 15449 test-keys
     with:  ro.build.description=tardis-user Eclair ERC91 15449 release-keys
  replace: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/test-keys
     with: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/release-keys
using:
    vendor/yoyodyne/security/tardis/releasekey.x509.pem
for OTA package verification
done.

לאחר בקשת המשתמש להזין סיסמאות עבור כל המפתחות המוגנים באמצעות סיסמה, הסקריפט חותם מחדש את כל קבצי ה-APK ב- .zip היעד הקלט עם מפתחות השחרור. לפני הפעלת הפקודה, תוכל גם להגדיר את משתנה הסביבה ANDROID_PW_FILE לשם קובץ זמני; לאחר מכן, הסקריפט מפעיל את העורך שלך כדי לאפשר לך להזין סיסמאות עבור כל המפתחות (זו עשויה להיות דרך נוחה יותר להזין סיסמאות).

החלפת מפתח חתימה של APEX

אנדרואיד 10 מציגה את פורמט הקובץ APEX להתקנת מודולי מערכת ברמה נמוכה יותר. כפי שהוסבר בחתימת APEX , כל קובץ APEX חתום עם שני מפתחות: אחד עבור תמונת מערכת הקבצים המיני בתוך APEX והשני עבור APEX כולו.

בעת חתימה לשחרור, שני מפתחות החתימה עבור קובץ APEX מוחלפים במפתחות שחרור. מפתח המטען של מערכת הקבצים מצוין עם הדגל --extra_apex_payload ומפתח החתימה של קובץ APEX כולו מצוין עם הדגל --extra_apks .

עבור מוצר tardis, הנח שיש לך את תצורת המפתח הבאה עבור קבצי com.android.conscrypt.apex , com.android.media.apex ו- com.android.runtime.release.apex APEX.

name="com.android.conscrypt.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED"
name="com.android.media.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED"
name="com.android.runtime.release.apex" public_key="vendor/yoyodyne/security/testkeys/com.android.runtime.avbpubkey" private_key="vendor/yoyodyne/security/testkeys/com.android.runtime.pem" container_certificate="vendor/yoyodyne/security/testkeys/com.google.android.runtime.release_container.x509.pem" container_private_key="vendor/yoyodyne/security/testkeys/com.google.android.runtime.release_container.pk8"

ויש לך את הקבצים הבאים המכילים את מפתחות השחרור:

vendor/yoyodyne/security/runtime_apex_container.x509.pem
vendor/yoyodyne/security/runtime_apex_container.pk8
vendor/yoyodyne/security/runtime_apex_payload.pem

הפקודה הבאה עוקפת את מפתחות החתימה עבור com.android.runtime.release.apex ו- com.android.tzdata.apex במהלך חתימת השחרור. במיוחד, com.android.runtime.release.apex חתום עם מפתחות השחרור שצוינו ( runtime_apex_container עבור קובץ APEX, ו- runtime_apex_payload עבור מטען תמונת הקובץ). com.android.tzdata.apex מטופל כחתימה מראש. כל שאר קבצי APEX מטופלים על ידי תצורת ברירת המחדל כפי שמופיעה בקובצי היעד.

./build/make/tools/releasetools/sign_target_files_apks \
    --default_key_mappings   vendor/yoyodyne/security/tardis \
    --extra_apks             com.android.runtime.release.apex=vendor/yoyodyne/security/runtime_apex_container \
    --extra_apex_payload_key com.android.runtime.release.apex=vendor/yoyodyne/security/runtime_apex_payload.pem \
    --extra_apks             com.android.media.apex= \
    --extra_apex_payload_key com.android.media.apex= \
    -o tardis-target_files.zip \
    signed-tardis-target_files.zip

הפעלת הפקודה לעיל נותנת את היומנים הבאים:

        [...]
    signing: com.android.runtime.release.apex                  container (vendor/yoyodyne/security/runtime_apex_container)
           : com.android.runtime.release.apex                  payload   (vendor/yoyodyne/security/runtime_apex_payload.pem)
NOT signing: com.android.conscrypt.apex
        (skipped due to special cert string)
NOT signing: com.android.media.apex
        (skipped due to special cert string)
        [...]

אפשרויות אחרות

סקריפט החתימה sign_target_files_apks משכתב את תיאור ה-build וטביעת האצבע בקבצי מאפייני ה-build כדי לשקף שה-build הוא מבנה חתום. הדגל --tag_changes שולט באילו עריכות מתבצעות בטביעת האצבע. הפעל את הסקריפט עם -h כדי לראות תיעוד על כל הדגלים.

צור מפתחות באופן ידני

אנדרואיד משתמש במפתחות RSA של 2048 סיביות עם אקספוננט ציבורי 3. אתה יכול ליצור צמדי אישורים/מפתחות פרטיים באמצעות הכלי openssl מ- openssl.org :

# generate RSA key
openssl genrsa -3 -out temp.pem 2048
Generating RSA private key, 2048 bit long modulus
....+++
.....................+++
e is 3 (0x3)

# create a certificate with the public part of the key
openssl req -new -x509 -key temp.pem -out releasekey.x509.pem -days 10000 -subj '/C=US/ST=California/L=San Narciso/O=Yoyodyne, Inc./OU=Yoyodyne Mobility/CN=Yoyodyne/emailAddress=yoyodyne@example.com'

# create a PKCS#8-formatted version of the private key
openssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt

# securely delete the temp.pem file
shred --remove temp.pem

הפקודה openssl pkcs8 שניתנה למעלה יוצרת קובץ .pk8 ללא סיסמה, מתאים לשימוש עם מערכת ה-build. כדי ליצור .pk8 מאובטח עם סיסמה (מה שעליך לעשות עבור כל מפתחות השחרור בפועל), החלף את הארגומנט -nocrypt ב- -passout stdin ; ואז openssl יצפין את המפתח הפרטי עם סיסמה הנקראת מקלט רגיל. לא מודפסת הנחיה, כך שאם stdin הוא הטרמינל, התוכנית תיראה תקועה כשהיא באמת רק מחכה שתזין סיסמה. ניתן להשתמש בערכים אחרים עבור ארגומנט-passout כדי לקרוא את הסיסמה ממקומות אחרים; לפרטים, עיין בתיעוד openssl .

קובץ הביניים temp.pem מכיל את המפתח הפרטי ללא כל סוג של הגנה באמצעות סיסמה, לכן יש להשליך אותו מתוך מחשבה בעת יצירת מפתחות שחרור. בפרט, ייתכן שתוכנית השירות GNUshred לא תהיה יעילה ברשת או במערכות קבצים מתועדות. אתה יכול להשתמש בספריית עבודה הממוקמת בדיסק RAM (כגון מחיצת tmpfs) בעת יצירת מפתחות כדי להבטיח שאמצעי הביניים לא ייחשפו בטעות.

צור קבצי תמונה

לאחר signed-target_files.zip , עליך ליצור את התמונה כדי שתוכל להכניס אותה למכשיר. כדי ליצור את התמונה החתומה מקבצי היעד, הפעל את הפקודה הבאה מהשורש של עץ האנדרואיד:

img_from_target_files signed-target_files.zip signed-img.zip
הקובץ המתקבל, signed-img.zip , מכיל את כל קובצי ה- .img . כדי לטעון תמונה למכשיר, השתמש ב-fastboot באופן הבא:
fastboot update signed-img.zip