חתימת APK

הכלי apksigner, זמין בגרסה 24.0.3 ואילך של הכלי Android SDK Build Tools, מאפשר לחתום על חבילות APK ולאשר חתימת ה-APK תאומת בהצלחה בכל הגרסאות של Android הפלטפורמה שנתמכת על ידי אותו APK.

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

זהירות: אם חותמים על ה-APK באמצעות apksigner ולבצע שינויים נוספים ב-APK, וחתימת ה-APK לא תקפה יותר. אם משתמשים zipalign ליישור ה-APK שלך, יש להשתמש בו לפני חתימת ה-APK.

שימוש

חתימה על APK

התחביר לחתימת APK באמצעות הכלי apksigner הוא כפי ככה:

apksigner sign --ks keystore.jks |
  --key key.pk8 --cert cert.x509.pem
  [signer_options] app-name.apk

כשחותמים על APK באמצעות הכלי apksigner, צריך לספק את המפתח הפרטי והאישור הפרטי של החותם. אפשר לכלול את המידע הזה בשתי דרכים:

  • מציינים קובץ KeyStore באמצעות האפשרות --ks.
  • לציין את קובץ המפתח הפרטי ואת קובץ האישור בנפרד באמצעות אפשרויות של --key ו---cert, בהתאמה. קובץ המפתח הפרטי חייב להיות בפורמט PKCS #8, וקובץ האישור חייב להיות בפורמט X.509.

בדרך כלל, חותמים על APK באמצעות חותם אחד בלבד. אם צריך לחתום על APK בעזרת מספר חותמים, משתמשים באפשרות --next-signer להפריד את האפשרויות הכלליות יחולו על כל חותם:

apksigner sign [signer_1_options] --next-signer [signer_2_options] app-name.apk

אימות החתימה של APK

התחביר לאישור חתימת ה-APK שהתבצעה בהצלחה בפלטפורמות נתמכות:

apksigner verify [options] app-name.apk

רוטציה של מפתחות החתימה

התחביר לרוטציה של שושלת אישורים של חתימה או רצף חדש של כך נראה:

$ apksigner rotate --in /path/to/existing/lineage \
  --out /path/to/new/file \
  --old-signer --ks old-signer-jks \
  --new-signer --ks new-signer-jks

אפשרויות

הרשימות הבאות כוללות את קבוצת האפשרויות לכל אחת מהפקודות יש תמיכה בכלי apksigner.

חתימה על הפקודה

הפקודה apksigner כוללת את האפשרויות הבאות.

אפשרויות כלליות

האפשרויות הבאות מציינות הגדרות בסיסיות שצריך להחיל על חותם:

--out <apk-filename>
המיקום שבו תרצו לשמור את ה-APK החתום. אם האפשרות הזו לא צוין במפורש, חבילת ה-APK חתומה במקום, שמחליפה את קובץ ה-APK לקלט.
--min-sdk-version <integer>
רמת ה-API הנמוכה ביותר של framework של Android שבה apksigner משתמש כדי לאשר שחתימת ה-APK תאומת. ערכים גבוהים יותר מאפשרים כלי לשימוש בפרמטרים חזקים יותר של אבטחה בחתימה על האפליקציה, אבל להגביל זמינות ה-APK למכשירים שבהם פועלות גרסאות Android עדכניות יותר. כברירת מחדל, apksigner משתמש בערך של minSdkVersion מקובץ המניפסט של האפליקציה.
--max-sdk-version <integer>
רמת ה-API הגבוהה ביותר של Android framework שבה משתמש apksigner כדי לאשר שחתימת ה-APK תאומת. כברירת מחדל, הכלי משתמש ברמת ה-API הגבוהה ביותר האפשרית.
--rotation-min-sdk-version <integer>
רמת ה-API הנמוכה ביותר של חתימת הרוטציה של ה-APK יש להשתמש במפתח כדי ליצור את חתימת ה-APK. מפתח החתימה המקורי (ללא רוטציה) של ה-APK ישמש עבור כל בגרסאות הקודמות של הפלטפורמה. כברירת מחדל, מפתחות חתימה מסתובבים, שנתמכים במכשירים עם Android 13 (רמת API 33) ומעלה, נעשה שימוש עם בלוק החתימה v3.1.

הערה: אם האפליקציה חתומה על ידי חתימה מסובבת במכשיר שמותקנת בו גרסת Android 12L (רמת API 32) ומטה, חייב להשתמש ב---rotation-min-sdk-version 28 כדי להמשיך בחתימה האפליקציה באמצעות מפתח החתימה המסובב ל-Android 9 (רמת API 28).

--v1-signing-enabled <true | false>
המדיניות קובעת אם apksigner חותם על חבילת ה-APK הנתונה באמצעות סכמת החתימה המסורתית המבוססת על JAR. כברירת מחדל, הכלי משתמש הערכים של --min-sdk-version וגם --max-sdk-version כדי לקבוע מתי להחיל את החתימה הזו scheme.
--v2-signing-enabled <true | false>
המדיניות קובעת אם apksigner חותם על חבילת ה-APK הנתונה באמצעות APK Signature Scheme v2. כברירת מחדל, הכלי משתמש בערכים של --min-sdk-version ו---max-sdk-version כדי להחליט מתי להחיל את סכמת החתימה הזו.
--v3-signing-enabled <true | false>
המדיניות קובעת אם apksigner חותם על חבילת ה-APK הנתונה באמצעות APK Signature Scheme v3. כברירת מחדל, הכלי משתמש בערכים של --min-sdk-version ו---max-sdk-version כדי להחליט מתי להחיל את סכמת החתימה הזו.
--v4-signing-enabled <true | false | only>

המדיניות קובעת אם האפליקציה apksigner תחתום על חבילת ה-APK הנתונה באמצעות APK Signature Scheme v4. סכימה זו יוצרת חתימה בקובץ נפרד (apk-name.apk.idsig). אם true וה-APK לא חתומים, אז חתימת גרסה 2 או 3 נוצר על סמך הערכים של --min-sdk-version --max-sdk-version לאחר מכן הפקודה מפיקה קובץ .idsig על סמך התוכן של ה-APK החתום.

צריך להשתמש ב-only כדי ליצור רק את v4 בלי לשנות את ה-APK והחתימות שהיה לפני ההפעלה. הפעולה only תיכשל אם ה-APK לא כבר קיימת חתימת v2 או v3 או אם החתימה משתמשת במפתח אחר יותר מזה שסופק להפעלה הנוכחית.

כברירת מחדל, הכלי משתמש בערכים של --min-sdk-version ו---max-sdk-version כדי להחליט מתי להחיל את סכמת החתימה הזו.

-v, --verbose
להשתמש במצב פלט מפורט.

אפשרויות לכל חותם

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

--next-signer <signer-options>
משמשת לציון אפשרויות כלליות שונות לכל חותם.
--v1-signer-name <basename>
שם הבסיס של הקבצים שמרכיבים את החתימה המבוססת על JAR של החותם הנוכחי. כברירת מחדל, apksigner משתמש בכינוי המפתח של שם ה-KeyStore או שם הבסיס של קובץ המפתח בשביל החותם הזה.

אפשרויות של מפתחות ואישורים

האפשרויות הבאות מציינות את המפתח הפרטי והאישור של החותם:

--ks <filename>
המפתח הפרטי ושרשרת האישורים של החותם נמצאים קובץ KeyStore מבוסס-Java. אם שם הקובץ מוגדר ל-"NONE", ב-KeyStore שמכיל את המפתח והאישור לא נדרש קובץ שצוין, וזה המצב במקרה של חלק מ-PKCS #11 KeyStores.
--ks-key-alias <alias>
השם של כתובת האימייל החלופית שמייצגת את המפתח הפרטי של החותם, וגם נתוני אישור ב-KeyStore. אם ה-KeyStore משויך אל בעל החתימה מכיל כמה מפתחות, צריך לציין את האפשרות הזו.
--ks-pass <input-format>

הסיסמה ל-KeyStore שמכילה את המפתח הפרטי של בעל החתימה וגם אישור. כדי לפתוח KeyStore, עליך להזין סיסמה. הכלי apksigner תומך בפורמטים הבאים:

  • pass:<password> – הסיסמה סופקה בתוך השורה יחד עם שאר הפקודה apksigner sign.
  • env:<name> – הסיסמה מאוחסנת במסגרת במשתנה הסביבה.
  • file:<filename> – הסיסמה נשמרת בתור בשורה אחת בקובץ הנתון.
  • stdin – הסיסמה מסופקת כשורה אחת ב- לזרם הקלט הסטנדרטי. זאת התנהגות ברירת המחדל --ks-pass

הערה: אם כוללים כמה סיסמאות באותה אפליקציה עליך לציין אותן בשורות נפרדות. הכלי apksigner משייכת סיסמאות לחותמים על APK לפי הסדר שבו אתם מציינים את החותמים. אם סיפקתם שתי סיסמאות לחותם, apksigner מפרש את הסיסמה הראשונה כ-KeyStore ואת הסיסמה השנייה כסיסמה למפתח.

--pass-encoding <charset>
כולל את קידודי התווים שצוינו, כמו ibm437 או utf-8, כשמנסים יטופלו סיסמאות שמכילות תווים שאינם ASCII.

לעיתים קרובות, כלי Keytool מצפין מאגרי מפתחות על ידי המרת הסיסמה באמצעות ברירת המחדל של המסוף charset. כברירת מחדל, apksigner מנסה לפענח באמצעות כמה צורות של סיסמה:

  • הטופס ב-Unicode
  • הטופס מקודד באמצעות ערכת התווים המוגדרת כברירת מחדל ל-JVM
  • ב-Java 8 ובגרסאות קודמות, הטופס קודד באמצעות ערכת התווים המוגדרת כברירת מחדל במסוף
  • ב-Java 9, apksigner לא יכול לזהות את ערכת התווים של המסוף. ייתכן שתצטרכו לציין את הערך --pass-encoding כאשר נעשה שימוש בסיסמה שאינה ASCII. יכול להיות שתצטרכו לציין את האפשרות הזאת גם במאגרי מפתחות כלי מקשים שנוצר במערכת הפעלה אחרת או באזור אחר.

    --key-pass <input-format>

    הסיסמה למפתח הפרטי של בעל החתימה, שנדרשת אם המפתח הפרטי מוגן בסיסמה. הכלי apksigner תומך בפורמטים הבאים:

    • pass:<password> – הסיסמה סופקה בתוך השורה יחד עם שאר הפקודה apksigner sign.
    • env:<name> – הסיסמה מאוחסנת במסגרת במשתנה הסביבה.
    • file:<filename> – הסיסמה נשמרת בתור בשורה אחת בקובץ הנתון.
    • stdin – הסיסמה מסופקת כשורה אחת ב- לזרם הקלט הסטנדרטי. זאת התנהגות ברירת המחדל --key-pass
    --ks-type <algorithm>
    הסוג או האלגוריתם המשויכים ל-KeyStore שמכילים את את המפתח הפרטי והאישור שלו. כברירת מחדל, apksigner משתמש בסוג המוגדר כקבוע keystore.type בפונקציה קובץ מאפייני אבטחה.
    --ks-provider-name <name>
    השם של ספק ה-JCA לשימוש בבקשת ה-KeyStore של החותם יישום בפועל. כברירת מחדל, apksigner משתמש הספק עם העדיפות הגבוהה ביותר.
    --ks-provider-class <class-name>
    שם המחלקה המלאה (JCA) של ספק ה-JCA לשימוש בבקשה הטמעת KeyStore של החותם. האפשרות הזו משמשת כחלופה עבור --ks-provider-name. כברירת מחדל, apksigner משתמש בספק שצוין עם --ks-provider-name כאפשרות.
    --ks-provider-arg <value>
    ערך מחרוזת שיועבר כארגומנט של ה-constructor של ה-JCA סיווג הספק; המחלקה עצמה מוגדרת עם אפשרות --ks-provider-class. כברירת מחדל, apksigner משתמש בבנאי אפס ארגומנטים של המחלקה.
    --key <filename>
    שם הקובץ שמכיל את המפתח הפרטי של החותם. הקובץ הזה חייבים להשתמש בפורמט PKCS #8 DER. אם המפתח מוגן באמצעות סיסמה, apksigner מבקש את הסיסמה באמצעות קלט רגיל אלא אם תציינו סוג אחר של פורמט קלט באמצעות אפשרות --key-pass.
    --cert <filename>
    שם הקובץ שמכיל את שרשרת האישורים של החותם. הזה חייב להיות בפורמט X.509 PEM או DER.

    אימות הפקודה

    פקודת האימות apksigner כוללת את האפשרויות הבאות.

    --print-certs
    הצגת מידע על אישורי החתימה של ה-APK.
    --min-sdk-version <integer>
    רמת ה-API הנמוכה ביותר של framework של Android שבה apksigner משתמש כדי לאשר שחתימת ה-APK תאומת. ערכים גבוהים יותר מאפשרים כלי לשימוש בפרמטרים חזקים יותר של אבטחה בחתימה על האפליקציה, אבל להגביל זמינות ה-APK למכשירים שבהם פועלות גרסאות Android עדכניות יותר. כברירת מחדל, apksigner משתמש בערך של minSdkVersion מקובץ המניפסט של האפליקציה.
    --max-sdk-version <integer>
    רמת ה-API הגבוהה ביותר של Android framework שבה משתמש apksigner כדי לאשר שחתימת ה-APK תאומת. כברירת מחדל, הכלי משתמש ברמת ה-API הגבוהה ביותר האפשרית.
    -v, --verbose
    להשתמש במצב פלט מפורט.
    -Werr
    צריך להתייחס לאזהרות כאל שגיאות.

    דוגמאות

    בהמשך מופיעות דוגמאות לשימוש ב-apksigner.

    חתימה על APK

    לחתום על APK באמצעות release.jks, שהוא המפתח היחיד ב- מאגר מפתחות:

    $ apksigner sign --ks release.jks app.apk
    

    חותמים על APK באמצעות מפתח פרטי ואישור ששמורים כקבצים נפרדים:

    $ apksigner sign --key release.pk8 --cert release.x509.pem app.apk
    

    חתימה על APK באמצעות שני מפתחות:

    $ apksigner sign --ks first-release-key.jks --next-signer --ks second-release-key.jks app.apk
    

    חותמים על APK באמצעות מפתח חתימה מסובב והרוטציה שמטרגטת את ה-SDK בגרסה 28 ואילך:

    $ apksigner sign --ks release.jks --next-signer --ks release2.jks \
      --lineage /path/to/signing/history/lineage app.apk \
      --rotation-min-sdk-version 28
    

    חותמים על APK באמצעות מפתח חתימה מסובב והרוטציה שמטרגטת את ה-SDK בגרסה 33 ואילך:

    $ apksigner sign --ks release.jks --next-signer --ks release2.jks \
      --lineage /path/to/signing/history/lineage app.apk
    

    אימות החתימה של APK

    בדקו אם חתימות ה-APK יאושרו ב- את כל פלטפורמות Android שה-APK תומך בהן:

    $ apksigner verify app.apk
    

    בדקו אם חתימות ה-APK יאושרו ב- Android 4.0.3 (רמת API 15) ואילך:

    $ apksigner verify --min-sdk-version 15 app.apk
    

    רוטציה של מפתחות החתימה

    הפעלת שושלת של אישור חתימה שתומכת ברוטציית מפתחות:

    $ apksigner rotate --out /path/to/new/file --old-signer \
        --ks release.jks --new-signer --ks release2.jks

    סיבוב מחדש של מפתחות החתימה:

    $ apksigner rotate --in /path/to/existing/lineage \
      --out /path/to/new/file --old-signer --ks release2.jks \
      --new-signer --ks release3.jks