Firma delle build per il rilascio

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

  1. Ogni .apk file di dentro l'immagine deve essere firmato. Package Manager di Android utilizza un .apk firma in due modi:
    • Quando un'applicazione viene sostituita, deve essere firmata con la stessa chiave della vecchia applicazione per poter accedere ai dati della vecchia applicazione. Questo vale sia per l'aggiornamento di applicazioni utente sovrascrivendo la .apk , e per superiori un'applicazione di sistema con una versione più recente installato sotto /data .
    • Se due o più applicazioni desiderano condividere un ID utente (in modo che possano condividere dati, ecc.), devono essere firmate con la stessa chiave.
  2. I pacchetti di aggiornamento OTA devono essere firmati con una delle chiavi previste dal sistema o il processo di installazione li rifiuterà.

Tasti di rilascio

L'albero Android include test-chiavi sotto build/target/product/security . La costruzione di un'immagine del sistema operativo Android utilizzando make firmerà tutti i .apk file utilizzando i tasti di prova. Poiché le chiavi di prova sono note pubblicamente, chiunque può firmare i propri file .apk con le stesse chiavi, il che potrebbe consentire loro di sostituire o dirottare le app di sistema integrate nell'immagine del sistema operativo. Per questo motivo è fondamentale per firmare qualsiasi immagine rilasciato o distribuito pubblicamente sistema operativo Android con un set speciale di rilascio-chiavi che solo si ha accesso.

Per generare il tuo set unico di chiavi di rilascio, esegui questi comandi dalla radice del tuo 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 in modo da riflettere le informazioni della vostra organizzazione. Puoi utilizzare qualsiasi directory, ma fai attenzione a scegliere una posizione di cui sia stato eseguito il backup e sicuro. Alcuni fornitori scelgono di crittografare la propria chiave privata con una passphrase complessa e di archiviare la chiave crittografata nel controllo del codice sorgente; altri memorizzano le chiavi di rilascio da qualche altra parte, ad esempio su un computer air gap.

Per generare un'immagine di rilascio, utilizzare:

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

Il sign_target_files_apks script prende un obiettivo a file .zip come input e produce un nuovo obiettivo-files .zip in cui tutti i .apk sono stati firmati i file con nuove chiavi. Le immagini appena firmati possono essere trovati sotto IMAGES/ a signed-target_files.zip .

Firmare pacchetti OTA

Un obiettivo a zip file firmati possono essere convertiti in un firmato OTA update zip 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 il normale meccanismo di verifica della firma del pacchetto di ripristino: prima di installare un pacchetto, il ripristino verificherà che sia firmato con una delle chiavi private corrispondenti alle chiavi pubbliche memorizzate nella partizione di ripristino, proprio come farebbe per un pacchetto consegnato -aria.

Pacchetti di aggiornamento ricevute dal sistema principale sono tipicamente verificati due volte: una volta dal sistema principale, utilizzando il RecoverySystem.verifyPackage() metodo nella API Android, e poi nuovamente ripresa. I controlli RecoverySystem API la firma contro le chiavi pubbliche memorizzate nel sistema principale, nel file /system/etc/security/otacerts.zip (per impostazione predefinita). Controlli di recupero la firma contro le chiavi pubbliche memorizzate nel disco RAM partizione di ripristino nel file /res/keys .

Per impostazione predefinita, l'obiettivo a file .zip prodotte dai gruppi di compilazione del certificato di OTA per abbinare il tasto di prova. Su un'immagine rilasciata, è necessario utilizzare un certificato diverso in modo che i dispositivi possano verificare l'autenticità del pacchetto di aggiornamento. Passando il -o bandiera per sign_target_files_apks , come illustrato nella sezione precedente, sostituisce il certificato di chiave di prova con il certificato chiave di sblocco dalla directory certs.

Normalmente l'immagine di sistema e l'immagine di ripristino memorizzano lo stesso set di chiavi pubbliche OTA. Con l'aggiunta di una chiave per solo il set di recupero di chiavi, è possibile firmare i pacchetti che possono essere installati solo tramite sideloading (supponendo meccanismo di aggiornamento di download del sistema principale sia correttamente facendo verifica contro otacerts.zip). Puoi specificare chiavi extra da includere solo nel ripristino impostando la variabile PRODUCT_EXTRA_RECOVERY_KEYS nella definizione del prodotto:

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

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

Questo include la chiave pubblica vendor/yoyodyne/security/tardis/sideload.x509.pem nel file chiavi di ripristino in modo da poter installare i pacchetti firmati con esso. La chiave in più non è incluso nel però otacerts.zip, in modo da sistemi che verificano correttamente i pacchetti scaricati non lo fanno invoke recupero per i pacchetti firmati con questa chiave.

Certificati e chiavi private

Ogni tasto è disponibile in due file: il certificato, che ha la .x509.pem estensione, e la chiave privata, che ha la .pk8 estensione. La chiave privata deve essere tenuta segreta ed è necessaria per firmare un pacchetto. La chiave stessa può essere protetta da una password. Il certificato, al contrario, contiene solo la metà pubblica della chiave, quindi può essere ampiamente distribuito. Viene utilizzato per verificare che un pacchetto sia stato firmato dalla chiave privata corrispondente.

La build di Android standard utilizza cinque tasti, ognuno dei quali risiedono in build/target/product/security :

chiave di prova
Chiave predefinita generica per i pacchetti che non specificano altrimenti una chiave.
piattaforma
Chiave di test per i pacchetti che fanno parte della piattaforma principale.
condiviso
Chiave di prova per gli elementi condivisi nel processo home/contatti.
media
Chiave di prova per i pacchetti che fanno parte del sistema multimediale/download.
stack di rete
Chiave di test per i pacchetti che fanno parte del sistema di rete. La chiave networkstack viene utilizzata per firmare i binari progettati come componenti modulari del sistema . Se gli aggiornamenti del modulo vengono compilati separatamente e integrati come predefiniti nell'immagine del dispositivo, potrebbe non essere necessario generare una chiave dello stack di rete nell'albero dei sorgenti di Android.

I singoli pacchetti specificano una di queste chiavi impostando LOCAL_CERTIFICATE nel loro file Android.mk. (testkey viene utilizzato se questa variabile non è impostata.) È inoltre possibile specificare una chiave completamente diversa per percorso, ad esempio:

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

LOCAL_CERTIFICATE := device/yoyodyne/security/special

Ora la build usa il device/yoyodyne/security/special.{x509.pem,pk8} chiave per firmare SpecialApp.apk. La build può utilizzare solo le chiavi private che non sono protetti da password.

Opzioni di firma avanzate

Sostituzione della chiave di firma dell'APK

La firma di script sign_target_files_apks lavora sui file di destinazione generati per una generazione. Tutte le informazioni sui certificati e le chiavi private utilizzate in fase di compilazione sono incluse nei file di destinazione. Quando si esegue lo script di firma per firmare per il rilascio, le chiavi di firma possono essere sostituite in base al nome della chiave o al nome dell'APK.

Utilizzare i --key_mapping e --default_key_mappings bandiere per specificare la sostituzione chiave sulla base di nomi chiave:

  • Lo --key_mapping src_key = dest_key flag specifica la sostituzione per un tasto alla volta.
  • Il --default_key_mappings dir flag specifica una directory con cinque tasti per sostituire tutte le chiavi in build/target/product/security ; è equivalente all'utilizzo --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

Utilizzare la --extra_apks apk_name1,apk_name2,... = key bandiera per specificare le sostituzioni chiave di firma in base ai nomi APK. Se key viene lasciato vuoto, lo script tratta l'APK specificate come pre-firmato.

Per il prodotto TARDIS ipotetica, è necessario sei tasti protetti da password: cinque a sostituire i cinque in build/target/product/security , e uno per sostituire l'ulteriore chiave di device/yoyodyne/security/special richieste dal SpecialApp nell'esempio di cui sopra. Se le chiavi fossero 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 firmerai tutte le app in questo 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

Questo fa apparire 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 richiede all'utente per le password per tutti i tasti protetti da password, lo script di ri-segni tutti i file APK nel target di ingresso .zip con le chiavi di rilascio. Prima di eseguire il comando, è possibile anche impostare ANDROID_PW_FILE variabile di ambiente a un nome di file temporanei; lo script quindi richiama il tuo editor per consentirti di inserire le password per tutte le chiavi (questo potrebbe essere un modo più conveniente per inserire le password).

Sostituzione della chiave di firma APEX

Android 10 introduce il formato di file APEX per l'installazione di moduli del sistema di livello inferiore. Come spiegato nel APEX firma , ogni file APEX è firmato con due chiavi: una per l'immagine del file system all'interno di un mini APEX e l'altro per l'intera APEX.

Quando si firma per il rilascio, le due chiavi di firma per un file APEX vengono sostituite con chiavi di rilascio. La chiave di payload file system è specificato con il --extra_apex_payload bandiera e l'intera chiave del file di firma APEX è specificato con l' --extra_apks bandiera.

Per il prodotto TARDIS, supporre che si ha la seguente configurazione chiave per la 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"

E hai i seguenti file che contengono le chiavi 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 sostituisce le chiavi di firma per com.android.runtime.release.apex e com.android.tzdata.apex durante la firma di rilascio. In particolare, com.android.runtime.release.apex è firmato con le chiavi di rilascio specificati ( runtime_apex_container per il file APEX, e runtime_apex_payload per il file di immagine payload). com.android.tzdata.apex è trattata come pre-firmato. Tutti gli altri file APEX sono gestiti dalla configurazione predefinita come elencato 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 precedente fornisce i seguenti registri:

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

I sign_target_files_apks firma riscritture di script la descrizione di compilazione e di impronte digitali nei file costruzioni Proprietà a riflettere sul fatto che la build è una build firmato. Il --tag_changes controlli bandiera ciò che le modifiche apportate alla impronte digitali. Eseguire lo script con -h per vedere documentazione su tutte le bandiere.

Generazione manuale delle chiavi

Utilizza Android chiavi RSA a 2048 bit con esponente pubblico 3. È possibile generare certificati / coppie di chiavi private tramite funzione OpenSSL 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 openssl PKCS8 dato sopra crea un file .pk8 senza password, adatto per l'uso con il sistema di compilazione. Per creare un .pk8 protetto con una password (che si dovrebbe fare per tutte le chiavi di sblocco effettivi), sostituire il -nocrypt discussione con -passout stdin ; quindi openssl crittograferà la chiave privata con una password letta dall'input standard. Non viene stampato alcun prompt, quindi se stdin è il terminale, il programma sembrerà bloccato quando in realtà sta solo aspettando che tu inserisca una password. Altri valori possono essere usati per l'argomento-passout per leggere la password da altre posizioni; Per i dettagli, consultare la documentazione di OpenSSL .

Il file intermedio temp.pem contiene la chiave privata senza alcun tipo di protezione tramite password, quindi eliminala con attenzione durante la generazione delle chiavi di rilascio. In particolare, l'utilità GNUshred potrebbe non essere efficace su file system di rete o journaled. È possibile utilizzare una directory di lavoro situata in un disco RAM (come una partizione tmpfs) durante la generazione delle chiavi per garantire che gli intermedi non vengano esposti inavvertitamente.

Creazione di file di immagine

Dopo aver firmato-target-files.zip, devi creare l'immagine in modo da poterla inserire su un dispositivo. Per creare l'immagine firmata dai file di destinazione, eseguire il comando seguente dalla radice dell'albero Android:

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, uso fastboot come segue:
fastboot update signed-img.zip