Menandatangani build untuk rilis

Image OS Android menggunakan tanda tangan kriptografi di dua tempat:

  1. Setiap file .apk di dalam image harus ditandatangani. Pengelola Paket Android menggunakan tanda tangan .apk dengan dua cara:
    • Saat aplikasi diganti, aplikasi tersebut harus ditandatangani dengan kunci yang sama seperti aplikasi lama agar dapat mengakses data aplikasi lama. Hal ini berlaku baik untuk memperbarui aplikasi pengguna dengan menimpa .apk, maupun untuk mengganti aplikasi sistem dengan versi yang lebih baru yang diinstal di bawah /data.
    • Jika dua aplikasi atau lebih ingin berbagi ID pengguna (sehingga dapat berbagi data, dll.), aplikasi tersebut harus ditandatangani dengan kunci yang sama.
  2. Paket update OTA harus ditandatangani dengan salah satu kunci yang diharapkan oleh sistem atau proses penginstalan akan menolaknya.

Kunci rilis

Tree Android menyertakan test-keys di bagian build/target/product/security. Mem-build image OS Android menggunakan make akan menandatangani semua file .apk menggunakan test-keys. Karena test-keys diketahui secara publik, siapa saja dapat menandatangani file .apk mereka sendiri dengan kunci yang sama, yang mungkin memungkinkan mereka mengganti atau membajak aplikasi sistem yang di-build ke dalam image OS Anda. Oleh karena itu, sangat penting untuk menandatangani image OS Android yang dirilis atau di-deploy secara publik dengan kumpulan release-keys khusus yang hanya dapat Anda akses.

Untuk membuat kumpulan release-keys unik Anda sendiri, jalankan perintah ini dari root tree Android Anda:

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 harus diubah untuk mencerminkan informasi organisasi Anda. Anda dapat menggunakan direktori apa pun, tetapi berhati-hatilah untuk memilih lokasi yang dicadangkan dan aman. Beberapa vendor memilih untuk mengenkripsi kunci pribadi mereka dengan frasa sandi yang kuat dan menyimpan kunci terenkripsi dalam kontrol sumber; vendor lainnya menyimpan kunci rilis mereka di tempat lain, seperti di komputer yang terisolasi.

Untuk membuat image rilis, gunakan:

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

Skrip sign_target_files_apks menggunakan target-files .zip sebagai input dan menghasilkan target-files .zip baru yang di dalamnya semua file .apk telah ditandatangani dengan kunci baru. Image yang baru ditandatangani dapat ditemukan di bagian IMAGES/ di signed-target_files.zip.

Menandatangani paket OTA

File zip target-files yang ditandatangani dapat dikonversi menjadi file zip update OTA yang ditandatangani menggunakan prosedur berikut:
ota_from_target_files \
-k  (--package_key) 
signed-target_files.zip \
signed-ota_update.zip

Tanda tangan dan sideloading

Sideloading tidak melewati mekanisme verifikasi tanda tangan paket normal pemulihan—sebelum menginstal paket, pemulihan akan memverifikasi bahwa paket tersebut ditandatangani dengan salah satu kunci pribadi yang cocok dengan kunci publik yang disimpan di partisi pemulihan, seperti halnya paket yang dikirimkan secara over-the-air.

Paket update yang diterima dari sistem utama biasanya diverifikasi dua kali: sekali oleh sistem utama, menggunakan metode RecoverySystem.verifyPackage() di API Android, dan sekali lagi oleh pemulihan. RecoverySystem API memeriksa tanda tangan terhadap kunci publik yang disimpan di sistem utama, dalam file /system/etc/security/otacerts.zip (secara default). Pemulihan memeriksa tanda tangan terhadap kunci publik yang disimpan di disk RAM partisi pemulihan, dalam file /res/keys.

Secara default, target-files .zip yang dihasilkan oleh build menetapkan sertifikat OTA agar cocok dengan kunci pengujian. Pada image yang dirilis, sertifikat yang berbeda harus digunakan agar perangkat dapat memverifikasi keaslian paket update. Meneruskan flag -o ke sign_target_files_apks, seperti yang ditunjukkan di bagian sebelumnya, akan mengganti sertifikat kunci pengujian dengan sertifikat kunci rilis dari direktori sertifikat Anda.

Biasanya, image sistem dan image pemulihan menyimpan kumpulan kunci publik OTA yang sama. Dengan menambahkan kunci ke kumpulan kunci pemulihan saja, paket yang hanya dapat diinstal melalui sideloading dapat ditandatangani (dengan asumsi mekanisme download update sistem utama melakukan verifikasi dengan benar terhadap otacerts.zip). Anda dapat menentukan kunci tambahan yang hanya akan disertakan dalam pemulihan dengan menetapkan variabel PRODUCT_EXTRA_RECOVERY_KEYS dalam definisi produk Anda:

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

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

Hal ini mencakup kunci publik vendor/yoyodyne/security/tardis/sideload.x509.pem dalam file kunci pemulihan sehingga dapat menginstal paket yang ditandatangani dengannya. Namun, kunci tambahan tidak disertakan dalam otacerts.zip, sehingga sistem yang memverifikasi paket yang didownload dengan benar tidak memanggil pemulihan untuk paket yang ditandatangani dengan kunci ini.

Sertifikat dan kunci pribadi

Setiap kunci hadir dalam dua file: sertifikat, yang memiliki ekstensi .x509.pem, dan kunci pribadi, yang memiliki ekstensi .pk8. Kunci pribadi harus dirahasiakan dan diperlukan untuk menandatangani paket. Kunci itu sendiri dapat dilindungi dengan sandi. Sebaliknya, sertifikat hanya berisi bagian publik dari kunci, sehingga dapat didistribusikan secara luas. Sertifikat digunakan untuk memverifikasi bahwa paket telah ditandatangani oleh kunci pribadi yang sesuai.

Build Android standar menggunakan lima kunci, yang semuanya berada di build/target/product/security:

testkey
Kunci default generik untuk paket yang tidak menentukan kunci lain.
platform
Kunci pengujian untuk paket yang merupakan bagian dari platform inti.
shared
Kunci pengujian untuk hal-hal yang dibagikan dalam proses rumah/kontak.
media
Kunci pengujian untuk paket yang merupakan bagian dari sistem media/download.
networkstack
Kunci pengujian untuk paket yang merupakan bagian dari sistem jaringan. Kunci networkstack digunakan untuk menandatangani biner yang dirancang sebagai Komponen Sistem Modular . Jika update modul Anda di-build secara terpisah dan diintegrasikan sebagai prebuilt dalam image perangkat Anda, Anda mungkin tidak perlu membuat kunci networkstack di tree sumber Android.

Setiap paket menentukan salah satu kunci ini dengan menetapkan LOCAL_CERTIFICATE dalam file Android.mk. (testkey digunakan jika variabel ini tidak ditetapkan.) Anda juga dapat menentukan kunci yang sama sekali berbeda berdasarkan nama jalur, misalnya:

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

LOCAL_CERTIFICATE := device/yoyodyne/security/special

Sekarang build menggunakan kunci device/yoyodyne/security/special.{x509.pem,pk8} untuk menandatangani SpecialApp.apk. Build hanya dapat menggunakan kunci pribadi yang tidak dilindungi sandi.

Opsi penandatanganan lanjutan

Penggantian kunci penandatanganan APK

Skrip penandatanganan sign_target_files_apks berfungsi pada file target yang dihasilkan untuk build. Semua informasi tentang sertifikat dan kunci pribadi yang digunakan pada waktu build disertakan dalam file target. Saat menjalankan skrip penandatanganan untuk menandatangani rilis, kunci penandatanganan dapat diganti berdasarkan nama kunci atau nama APK.

Gunakan flag --key_mapping dan --default_key_mappings untuk menentukan penggantian kunci berdasarkan nama kunci:

  • Flag --key_mapping src_key=dest_key menentukan penggantian untuk satu kunci dalam satu waktu.
  • Flag --default_key_mappings dir menentukan direktori dengan lima kunci untuk mengganti semua kunci di build/target/product/security; hal ini setara dengan menggunakan --key_mapping lima kali untuk menentukan pemetaan.
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

Gunakan flag --extra_apks apk_name1,apk_name2,...=keyuntuk menentukan penggantian kunci penandatanganan berdasarkan nama APK. Jika key dibiarkan kosong, skrip akan memperlakukan APK yang ditentukan sebagai APK yang telah ditandatangani sebelumnya.

Untuk produk tardis hipotetis, Anda memerlukan enam kunci yang dilindungi sandi: lima untuk mengganti lima kunci di build/target/product/security, dan satu untuk mengganti kunci tambahan device/yoyodyne/security/special yang diperlukan oleh SpecialApp dalam contoh di atas. Jika kunci berada dalam file berikut:

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

Kemudian, Anda akan menandatangani semua aplikasi seperti ini:

./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

Hal ini akan menampilkan hal berikut:

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.

Setelah meminta sandi kepada pengguna untuk semua kunci yang dilindungi sandi, skrip akan menandatangani ulang semua file APK dalam target .zip input dengan kunci rilis. Sebelum menjalankan perintah, Anda juga dapat menetapkan variabel lingkungan ANDROID_PW_FILE ke nama file sementara; skrip kemudian akan memanggil editor Anda untuk memungkinkan Anda memasukkan sandi untuk semua kunci (ini mungkin cara yang lebih mudah untuk memasukkan sandi).

Penggantian kunci penandatanganan APEX

Android 10 memperkenalkan format file APEX untuk menginstal modul sistem tingkat bawah. Seperti yang dijelaskan dalam Penandatanganan APEX, setiap file APEX ditandatangani dengan dua kunci: satu untuk image sistem file mini dalam APEX dan yang lainnya untuk seluruh APEX.

Saat menandatangani rilis, dua kunci penandatanganan untuk file APEX diganti dengan kunci rilis. Kunci payload sistem file ditentukan dengan flag --extra_apex_payload dan kunci penandatanganan file APEX secara keseluruhan ditentukan dengan flag --extra_apks.

Untuk produk tardis, asumsikan bahwa Anda memiliki konfigurasi kunci berikut untuk file APEX com.android.conscrypt.apex, com.android.media.apex, dan com.android.runtime.release.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"

Dan Anda memiliki file berikut yang berisi kunci rilis:

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

Perintah berikut akan mengganti kunci penandatanganan untuk com.android.runtime.release.apex dan com.android.tzdata.apex selama penandatanganan rilis. Secara khusus, com.android.runtime.release.apex ditandatangani dengan kunci rilis yang ditentukan (runtime_apex_container untuk file APEX, dan runtime_apex_payload untuk payload image file). com.android.tzdata.apex diperlakukan sebagai APK yang telah ditandatangani sebelumnya. Semua file APEX lainnya ditangani oleh konfigurasi default seperti yang tercantum dalam file target.

./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

Menjalankan perintah di atas akan memberikan log berikut:

        [...]
    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)
        [...]

Opsi lain

Skrip penandatanganan sign_target_files_apks menulis ulang deskripsi build dan sidik jari dalam file properti build untuk mencerminkan bahwa build adalah build yang ditandatangani. Flag --tag_changes mengontrol pengeditan yang dilakukan pada sidik jari. Jalankan skrip dengan -h untuk melihat dokumentasi tentang semua flag.

Membuat kunci secara manual

Android menggunakan kunci RSA 2048-bit dengan eksponen publik 3. Anda dapat membuat pasangan kunci pribadi/sertifikat menggunakan alat openssl dari 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

Perintah openssl pkcs8 yang diberikan di atas membuat file .pk8 tanpa sandi, yang cocok untuk digunakan dengan sistem build. Untuk membuat .pk8 yang diamankan dengan sandi (yang harus Anda lakukan untuk semua kunci rilis sebenarnya), ganti argumen -nocrypt dengan -passout stdin; lalu openssl akan mengenkripsi kunci pribadi dengan sandi yang dibaca dari input standar. Tidak ada perintah yang dicetak, jadi jika stdin adalah terminal, program akan tampak berhenti saat sebenarnya hanya menunggu Anda memasukkan sandi. Nilai lain dapat di gunakan untuk argumen -passout guna membaca sandi dari lokasi lain; untuk mengetahui detailnya, lihat dokumentasi openssl.

File perantara temp.pem berisi kunci pribadi tanpa perlindungan sandi apa pun, jadi buang file tersebut dengan hati-hati saat membuat kunci rilis. Secara khusus, utilitas GNUshred mungkin tidak efektif pada sistem file jaringan atau yang dicatat dalam jurnal. Anda dapat menggunakan direktori kerja yang terletak di disk RAM (seperti partisi tmpfs) saat membuat kunci untuk memastikan perantara tidak terekspos secara tidak sengaja.

Membuat file image

Jika Anda memiliki signed-target_files.zip, Anda harus membuat image agar dapat menempatkannya di perangkat. Untuk membuat image yang ditandatangani dari file target, jalankan perintah berikut dari root tree Android:

img_from_target_files signed-target_files.zip signed-img.zip
File yang dihasilkan, signed-img.zip, berisi semua file .img. Untuk memuat image ke perangkat, gunakan fastboot sebagai berikut:
fastboot update signed-img.zip