בתמונות ל-Android OS נעשה שימוש בחתימות קריפטוגרפיות בשני מקומות:
- כל קובץ
.apk
שנמצא בתמונה חייב להיות חתום. של Android Package Manager משתמש בחתימת.apk
בשתי דרכים:- כשמחליפים אפליקציה, צריך לחתום עליה באותו מפתח כמו
של האפליקציה הישנה כדי לקבל גישה לנתונים של האפליקציה הישנה. המשמעות היא
True גם לעדכון אפליקציות של משתמשים על ידי החלפה של
.apk
וגם החלפה של אפליקציית מערכת שמותקנת בה גרסה חדשה יותר/data
. - אם שתי אפליקציות או יותר רוצות לשתף מזהה משתמש (כדי שיוכלו לשתף וכו'), הם צריכים להיות חתומים באותו מפתח.
- כשמחליפים אפליקציה, צריך לחתום עליה באותו מפתח כמו
של האפליקציה הישנה כדי לקבל גישה לנתונים של האפליקציה הישנה. המשמעות היא
True גם לעדכון אפליקציות של משתמשים על ידי החלפה של
- חבילות עדכון OTA חייבות להיות חתומות עם אחד מהמפתחות הנדרשים על ידי המערכת או תהליך ההתקנה ידחה אותן.
מקשי הגרסה
עץ Android כולל מפתחות בדיקה בקטע
build/target/product/security
. יצירת קובץ אימג' ל-Android OS
באמצעות make
יחתום על כל .apk
הקבצים באמצעות
למפתחות בדיקה. מאחר שמפתחות הבדיקה ידועים לציבור, כל אחד יכול לחתום בעצמו
בקובצי .APK עם אותם מפתחות, דבר שעלול לאפשר להם להחליף את המערכת או לפרוץ אליה
אפליקציות מובנות בקובץ האימג' של מערכת ההפעלה. לכן חשוב לחתום על
תמונה של Android OS שהושקה באופן ציבורי או נפרסה עם קבוצה מיוחדת של
מפתחות הפצה שרק לכם יש גישה אליהם.
כדי ליצור קבוצה ייחודית של מפתחות הפצה, מריצים את הפקודות האלה השורש של עץ Android:
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
כקלט ומפיק קובצי יעד חדשים .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()
ב-API ל-Android, ואז שוב באמצעות
תהליך השחזור. ממשק ה-API של RecoverSystem API בודק את החתימה מול מפתחות ציבוריים
מאוחסנים במערכת הראשית, בקובץ /system/etc/security/otacerts.zip
(כברירת מחדל). השחזור בודק את החתימה מול מפתחות ציבוריים שמאוחסנים
בדיסק ה-RAM של מחיצת השחזור, בקובץ /res/keys
.
כברירת מחדל, קובצי היעד .zip
שה-build יוצר מגדירים
אישור OTA להתאמה למפתח הבדיקה. בתמונה שפורסמה,
כדי שמכשירים יוכלו לאמת את האותנטיות של
עדכון החבילה. העברת הדגל -o
אל
sign_target_files_apks
, כמו שמוצג בקטע הקודם, מחליף את
אישור של מפתח הבדיקה עם האישור של מפתח ההפצה מהאישורים שלך
בדרך כלל תמונת המערכת ותמונת השחזור מאחסנים את אותה קבוצה של OTA מפתחות ציבוריים. הוספת מפתח רק לקבוצת המפתחות לשחזור, לחתום על חבילות שאפשר להתקין רק באמצעות התקנה ממקור לא ידוע. (בהנחה שמנגנון הורדת העדכונים במערכת הראשית פועל כראוי לאימות מול otacerts.zip). אפשר לציין מפתחות נוספים שיהיו נכללות רק בשחזור על ידי הגדרה של PRODUCT_עביר_Recover_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 הרגילה של Android משתמשת בחמישה מפתחות, שכולם נמצאים ב-
build/target/product/security
:
- מפתח בדיקה
- מפתח ברירת מחדל גנרי לחבילות שלא מצוין בהן מפתח אחר.
- פלטפורמה
- מפתח בדיקה לחבילות שהן חלק מפלטפורמת הליבה.
- משותף
- מפתח בדיקה של דברים שמשותפים בתהליך הבית או אנשי הקשר.
- מדיה
- מפתח בדיקה של חבילות שהן חלק ממערכת המדיה/ההורדה.
חבילות בודדות מציינות אחד מהמפתחות האלה על ידי הגדרה של LOCAL_CERTIFICATE בקובץ Android.mk שלהם. (אם המשתנה הזה לא מוגדר, המערכת תשתמש במפתח בדיקה). שלך הוא יכול גם לציין מפתח שונה לגמרי לפי שם נתיב, לדוגמה:
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
פועל על היעד
שנוצרו עבור build. כל המידע על אישורים ופרטי
המפתחות שנמצאים בשימוש בזמן ה-build כלולים בקובצי היעד. כשמפעילים את
סקריפט לחתימה על הגרסה, ניתן להחליף את מפתחות החתימה בהתאם למפתח
השם או שם ה-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
נשאר ריק, הסקריפט מטפל בחבילות ה-APK שצוינו
כמו שנחתמו מראש.
למוצר ההיפותטי 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
Android 10 מציג את פורמט הקובץ APEX להתקנה למודולים של מערכת ברמה נמוכה יותר. כפי שמוסבר ב חתימת APEX, כל קובץ APEX חתומה באמצעות שני מפתחות: אחד לתמונה של מערכת הקבצים מיני בתוך APEX אחר עבור כל APEX.
כשחותמים על גרסה, שני מפתחות החתימה של קובץ APEX מוחלפים
באמצעות מקשי ההפצה. מפתח המטען הייעודי (payload) של מערכת הקבצים מצוין עם
הדגל --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
למטען הייעודי (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 הוא build חתום. הדגל --tag_changes
קובע אילו פעולות עריכה
לטביעת האצבע. מריצים את הסקריפט באמצעות -h
כדי לראות
תיעוד של כל הדגלים.
יצירת מפתחות באופן ידני
מערכת Android משתמשת במפתחות RSA של 2048 ביט עם מעריך ציבורי 3. אפשר ליצור אישור/זוג מפתחות פרטיים באמצעות הכלי opensl מ- openssl.org:
# generate RSA keyopenssl 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 keyopenssl 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 keyopenssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt
# securely delete the temp.pem fileshred --remove temp.pem
פקודת ה-Opensl pkcs8 שצוינה למעלה יוצרת קובץ .pk8 עם הערך no
סיסמה שמתאימה לשימוש עם מערכת ה-build. כדי ליצור קובץ .pk8 מאובטח
בסיסמה (שפעולה זו נדרשת עבור כל מפתחות ההפצה בפועל), מחליפים את
ארגומנט -nocrypt
עם -passout stdin
; לאחר מכן opensl
יצפין את המפתח הפרטי באמצעות סיסמה שתיקרא מהקלט הרגיל. לא
מודפסת, כך שאם stdin הוא הטרמינל, התוכנה תיראה תלויה
כשהוא רק מחכה שתכניסו את הסיסמה. ערכים אחרים יכולים להיות
משמש לארגומנט 'pass' כדי לקרוא את הסיסמה ממיקומים אחרים; עבור
פרטים נוספים, עיינו במאמר
תיעוד ה-Opensl.
קובץ הביניים temp.pem מכיל את המפתח הפרטי ללא כל סוג של הגנה באמצעות סיסמה, לכן יש להשליך אותה בזהירות בעת יצירת גרסה מקשי קיצור. בפרט, ייתכן שהכלי GNUshred לא יהיה יעיל ברשת מערכות קבצים שנרשמו ביומן. אפשר להשתמש בספריית עבודה שנמצאת בדיסק RAM (למשל מחיצת tmpfs) כשיוצרים מפתחות כדי להבטיח את זמני הביניים הם לא נחשפים בטעות.
יצירת קובצי תמונה
כשיש לך signed-target_files.zip
, עליך:
יוצרים את התמונה כדי שאפשר יהיה לשים אותה במכשיר.
כדי ליצור את התמונה החתומה מקובצי היעד, מריצים את הפקודה
הפקודה הבאה מהרמה הבסיסית (root) של Android
עץ:
img_from_target_files signed-target_files.zip signed-img.zipהקובץ שמתקבל,
signed-img.zip
, מכיל את כל הקבצים מסוג .img
.
כדי לטעון תמונה למכשיר, צריך להשתמש באתחול מהיר בתור
ככה:
fastboot update signed-img.zip