Firma le build per la release

Le immagini del sistema operativo Android utilizzano le firme crittografiche in due posizioni:

  1. Ogni file .apk all'interno dell'immagine deve essere firmato. Per Android Il gestore di pacchetti utilizza la firma .apk in due modi:
    • Quando un'applicazione viene sostituita, deve essere firmata dalla stessa chiave del la vecchia applicazione per ottenere l'accesso ai dati della vecchia applicazione. Questa conservazione true sia per l'aggiornamento delle app utente tramite la sovrascrittura di .apk sia per eseguire l'override di un'app di sistema con una versione più recente installata in /data.
    • Se due o più applicazioni desiderano condividere un ID utente (per poter condividere dati e così via), devono essere firmati con la stessa chiave.
  2. I pacchetti di aggiornamento OTA devono essere firmati con una delle chiavi previste dal o dal processo di installazione.

Tasti di rilascio

La struttura di Android include le chiavi di test in build/target/product/security. Creazione di un'immagine sistema operativo Android utilizzando make firmerà tutti i .apk file con di test. Poiché le chiavi di test sono note pubblicamente, chiunque può firmarne File .apk con le stesse chiavi, il che potrebbe consentire loro di sostituire o compromettere il sistema integrate nell'immagine del sistema operativo. Per questo motivo è fondamentale firmare qualsiasi l'immagine del sistema operativo Android rilasciata pubblicamente o di cui è stato eseguito il deployment con un set speciale chiavi di rilascio a cui hai accesso soltanto tu.

Per generare il tuo set univoco di chiavi di rilascio, esegui questi comandi da la radice dell'albero 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 deve essere modificato per riflettere la informazioni. Puoi usare qualsiasi directory, ma fai attenzione a scegliere posizione sicura e di cui viene eseguito il backup. Alcuni fornitori scelgono di criptare la propria chiave privata con una passphrase efficace e archiviare la chiave criptata nel controllo del codice sorgente; altre memorizzano le chiavi di rilascio in un'altra posizione, ad esempio su un computer con air gap.

Per generare un'immagine di release, usa:

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

Lo script sign_target_files_apks utilizza un file di destinazione .zip come input e produce un nuovo file di destinazione .zip in che tutti i .apk file sono stati firmati con nuove chiavi. Il nuovo è possibile trovare immagini firmate in IMAGES/ in signed-target_files.zip.

Firma pacchetti OTA

Un file ZIP di file di destinazione firmato può essere convertito in un file ZIP di aggiornamento OTA firmato utilizzando la seguente procedura:
ota_from_target_files \
-k  (--package_key) 
signed-target_files.zip \
signed-ota_update.zip

Firme e sideload

Il sideload non ignora la normale firma del pacchetto del ripristino meccanismo di verifica: prima di installare un pacchetto, il ripristino verifica che sia firmato con una delle chiavi private corrispondenti alle chiavi pubbliche archiviate la partizione di ripristino, proprio come per un pacchetto consegnato over-the-air.

I pacchetti di aggiornamento ricevuti dal sistema principale vengono generalmente verificati due volte: una volta dal sistema principale, utilizzando RecoverySystem.verifyPackage() nell'API Android e poi di nuovo e il ripristino di emergenza. L'API RecoverySystem controlla la firma in base alle chiavi pubbliche memorizzati nel sistema principale, nel file /system/etc/security/otacerts.zip (per impostazione predefinita). Il ripristino controlla la firma in base alle chiavi pubbliche archiviate nel disco RAM della partizione di ripristino, nel file /res/keys.

Per impostazione predefinita, i file di destinazione .zip prodotti dalla build impostano la certificato OTA corrispondente alla chiave di test. Su un'immagine rilasciata, per consentire ai dispositivi di verificare l'autenticità del di aggiornamento del pacchetto. Il passaggio del flag -o a sign_target_files_apks, come mostrato nella sezione precedente, sostituisce Il certificato della chiave di test con il certificato della chiave di rilascio dei tuoi certificati .

Di solito l'immagine di sistema e l'immagine di ripristino memorizzano lo stesso insieme di OTA le chiavi pubbliche. L'aggiunta di una chiave solo al set di chiavi di recupero possibile firmare pacchetti che possono essere installati solo tramite sideload (supponendo che il meccanismo di download dell'aggiornamento del sistema principale funzioni correttamente verifica utilizzando otacerts.zip). Puoi specificare chiavi aggiuntive incluso solo nel recupero impostando l'attributo PRODUCT_EXTRA_RECOVERY_KEYS nella tua definizione di prodotto:

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

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

Include la chiave pubblica vendor/yoyodyne/security/tardis/sideload.x509.pem in recupero di chiavi in modo che possa installare pacchetti firmati con essa. La chiave in più non è però inclusa nel file otacerts.zip, che i sistemi che verificano correttamente i pacchetti scaricati non richiamano il ripristino per pacchetti firmati con questa chiave.

Certificati e chiavi private

Ogni chiave è disponibile in due file: il certificate, che contiene .x509.pem e la chiave privata con estensione .pk8. La chiave privata deve essere mantenuta segreta ed è necessaria per firmare un pacchetto. La chiave potrebbe essere a sua volta protetto da una password. Il certificato, in contiene solo la metà pubblica della chiave, quindi può essere distribuita ampiamente. Viene utilizzato per verificare che un pacchetto sia stato firmato dalla chiave privata.

La build Android standard utilizza cinque chiavi, che risiedono tutte in build/target/product/security:

chiave di prova
Chiave predefinita generica per pacchetti che non specificano una chiave in altro modo.
piattaforma
Chiave di test per pacchetti che fanno parte della piattaforma di base.
condiviso
Chiave di test per gli elementi condivisi durante la procedura relativa alla casa o ai contatti.
multimediale
Chiave di test per i pacchetti che fanno parte del sistema multimediale/di download.
pentola
Chiave di test per pacchetti che fanno parte del sistema di rete. La la chiave networktack viene usata per firmare file binari progettati come Componenti del sistema modulare . Se gli aggiornamenti dei moduli sono creati separatamente e integrati come strumenti predefiniti nell'immagine del dispositivo, potrebbe non essere necessario generare una chiave dell'inquadratura di rete Struttura delle origini Android.

I singoli pacchetti specificano una di queste chiavi impostando LOCAL_CERTIFICATE nel file Android.mk. (la chiave di test viene utilizzata se questa variabile non è impostata). Tu puoi anche specificare una chiave completamente diversa tramite il nome del percorso, ad esempio:

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

LOCAL_CERTIFICATE := device/yoyodyne/security/special

Ora la build usa il tasto device/yoyodyne/security/special.{x509.pem,pk8} per firmare SpecialApp.apk. La build può usare solo chiavi private non sono protette da password.

Opzioni di firma avanzate

Sostituzione della chiave di firma dell'APK

Lo script di firma sign_target_files_apks funziona nella destinazione generati per una build. Tutte le informazioni sui certificati e privato utilizzate in fase di creazione sono incluse nei file di destinazione. Quando esegui il comando script di firma per firmare per la release, le chiavi di firma possono essere sostituite in base alla chiave o il nome dell'APK.

Utilizza --key_mapping e --default_key_mappings per specificare la sostituzione delle chiavi in base ai nomi delle chiavi:

  • Il flag --key_mapping src_key=dest_key specifica la sostituzione di una chiave alla volta.
  • Il flag --default_key_mappings dir specifica un con cinque chiavi per sostituire tutte le chiavi build/target/product/security; equivale a utilizzare --key_mapping cinque volte per specificare le mappature.
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

Utilizza la --extra_apks apk_name1,apk_name2,...=key flag per specificare le sostituzioni delle chiavi di firma in base ai nomi degli APK. Se key è lasciato vuoto, lo script tratta gli APK specificati come prefirmato.

Per l'ipotetico prodotto tardis, sono necessarie sei chiavi protette da password: cinque per sostituire il cinque in build/target/product/security e uno per sostituire la chiave aggiuntiva device/yoyodyne/security/special come richiesto da SpecialApp nell'esempio precedente. Se le chiavi erano nei seguenti file:

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

Quindi, dovrai firmare tutte le app nel seguente modo:

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

Viene visualizzato quanto segue:

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.

Dopo aver richiesto all'utente le password per tutte le chiavi protette da password, il lo script firma nuovamente tutti i file APK nella destinazione di input .zip con lo script i tasti di rilascio. Prima di eseguire il comando, puoi anche impostare ANDROID_PW_FILE in un nome file temporaneo; il richiama quindi l'editor per consentirti di inserire le password per tutte le chiavi (questo potrebbe essere un modo più comodo per inserire le password).

Sostituzione della chiave di firma APEX

Android 10 introduce Formato file APEX per l'installazione moduli di sistema di livello inferiore. Come spiegato nella sezione Firma APEX, ogni file APEX viene firmato con due chiavi: una per l'immagine del file system mini all'interno di un APEX e altre per l'intero APEX.

Quando firmi la release, le due chiavi di firma del file APEX vengono sostituite usando i tasti di rilascio. La chiave payload del file system viene specificata con --extra_apex_payload e l'intera chiave di firma del file APEX è specificato con il flag --extra_apks.

Per il prodotto tardis, supponiamo di avere la seguente configurazione chiave per com.android.conscrypt.apex, com.android.media.apex e com.android.runtime.release.apex file 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"

I seguenti file contengono i tasti di rilascio:

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

Il seguente comando esegue l'override delle chiavi di firma per com.android.runtime.release.apex e com.android.tzdata.apex durante la firma della release. In particolare, com.android.runtime.release.apex è firmato con tasti di rilascio (runtime_apex_container per il file APEX e runtime_apex_payload per il payload del file immagine). com.android.tzdata.apex viene considerato come prefirmato. Tutti gli altri APEX vengono gestiti con la configurazione predefinita come indicato nei file di destinazione.

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

L'esecuzione del comando riportato sopra fornisce i seguenti log:

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

Altre opzioni

Lo script di firma sign_target_files_apks riscrive la build descrizione e fingerprint nei file delle proprietà della build per indicare che è una build firmata. Il flag --tag_changes controlla quali modifiche vengono apportate all'impronta. Esegui lo script con -h per visualizzare documentazione su tutti i flag.

Generare manualmente le chiavi

Android utilizza chiavi RSA a 2048 bit con esponente pubblico 3. Puoi generare di chiavi private/certificate mediante lo strumento opensl da 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

Il comando Opensl pkcs8 indicato in precedenza crea un file .pk8 con no. una password, adatta all'uso con il sistema di compilazione. Per creare un file protetto .pk8 con una password (operazione consigliata per tutti i tasti di rilascio effettivi), sostituisci Argomento -nocrypt con -passout stdin; poi apre sl cripterà la chiave privata con una password letta dall'input standard. No , quindi se stdin è il terminale il programma si blocca solo quando devi inserire la password. Altri valori possono essere utilizzato per l'argomento-passout per leggere la password da altre posizioni; della vedi i dettagli. documentazione di Opensl.

Il file intermedio temp.pem contiene la chiave privata senza alcun tipo di protezione tramite password, quindi smaltiscila con cura quando generi una release chiave. In particolare, l'utilità GNUshred potrebbe non essere efficace sulla rete o i file system inseriti nel journal. Puoi usare una directory di lavoro situata in un disco RAM (ad esempio una partizione tmpfs) durante la generazione di chiavi per garantire che gli intermedi non sono inavvertitamente esposti.

Creare file immagine

Quando hai signed-target_files.zip, devi creare l'immagine per poterla mettere su un dispositivo. Per creare l'immagine firmata dai file di destinazione, esegui il seguente comando dalla directory radice dell'app albero:

img_from_target_files signed-target_files.zip signed-img.zip
Il file risultante, signed-img.zip, contiene tutti i file .img. Per caricare un'immagine su un dispositivo, usa fastboot come che segue:
fastboot update signed-img.zip