Le immagini del sistema operativo Android utilizzano le firme crittografiche in due posizioni:
- 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 con la stessa chiave dell'app precedente per poter accedere ai dati dell'app precedente. 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 vogliono condividere un ID utente (in modo da poter condividere dati e così via), devono essere firmate con la stessa chiave.
- Quando un'applicazione viene sostituita, deve essere firmata con la stessa chiave dell'app precedente per poter accedere ai dati dell'app precedente. Questa conservazione
true sia per l'aggiornamento delle app utente tramite la sovrascrittura di
- I pacchetti di aggiornamento OTA devono essere firmati con una delle chiavi previste dal o dal processo di installazione.
Chiavi di rilascio
La struttura di Android include test-keys inbuild/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ò firmare i propri file .apk con le stesse chiavi, il che potrebbe consentire di sostituire o compromettere le app di sistema integrate nell'immagine del sistema operativo. Per questo motivo, è fondamentale firmare qualsiasi immagine del sistema operativo Android rilasciata o implementata pubblicamente con un insieme speciale di release-keys a cui solo tu hai accesso.
Per generare il tuo insieme univoco di release-keys, esegui questi comandi dalla radice della struttura 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 utilizzare qualsiasi directory, ma assicurati di scegliere una posizione di cui è stato eseguito il backup e che sia sicura. 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
prende come input un file target-files
.zip
e produce un nuovo file target-files .zip
in
cui tutti i file .apk
sono stati firmati con nuove chiavi. Il nuovo
è possibile trovare immagini firmate in IMAGES/
in
signed-target_files.zip
.
Firmare i pacchetti OTA
Un file ZIP dei file di destinazione firmato può essere convertito in un file ZIP di aggiornamento OTA firmato mediante 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 in 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 rispetto alle chiavi pubbliche memorizzate 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. In un'immagine rilasciata, deve essere utilizzato un certificato diverso in modo che i dispositivi possano verificare l'autenticità del pacchetto di aggiornamento. Se passi il flag -o
a
sign_target_files_apks
, come mostrato nella sezione precedente, il
certificato della chiave di test viene sostituito con il
certificato della chiave di rilascio della directory dei certificati.
Di solito l'immagine di sistema e l'immagine di ripristino memorizzano lo stesso insieme di OTA le chiavi pubbliche. Aggiungendo una chiave solo al set di chiavi di recupero, è possibile firmare i pacchetti che possono essere installati solo tramite sideload (supponendo che il meccanismo di download dell'aggiornamento del sistema principale esegua correttamente la verifica rispetto a otacerts.zip). Puoi specificare chiavi aggiuntive da includere solo nel recupero 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
Include la chiave pubblica
vendor/yoyodyne/security/tardis/sideload.x509.pem
in recupero
di chiavi in modo che possa installare pacchetti firmati
con essa. Tuttavia, la chiave aggiuntiva non è inclusa in otacerts.zip, pertanto i sistemi che verificano correttamente i pacchetti scaricati non richiamano il recupero per i pacchetti firmati con questa chiave.
Certificati e chiavi private
Ogni chiave è disponibile in due file: il certificato, con estensione .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 utilizzata per verificare che un pacchetto sia stato firmato dalla corrispondente chiave privata.
La build Android standard utilizza cinque chiavi, tutte presenti in
build/target/product/security
:
- testkey
- 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
- Testa la chiave per gli elementi condivisi nella procedura di casa/contatti.
- multimediale
- Chiave di test per i pacchetti che fanno parte del sistema multimediale/di download.
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 compilazione utilizza la chiave device/yoyodyne/security/special.{x509.pem,pk8}
per firmare SpecialApp.apk. La compilazione può utilizzare solo chiavi private che 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. Tutti i dati su certificati e chiavi private utilizzati in fase di compilazione sono inclusi nei file di destinazione. Quando esegui lo script di firma per la release, le chiavi di firma possono essere sostituite in base al nome della chiave o al nome dell'APK.
Utilizza i flag --key_mapping
e --default_key_mappings
per specificare la sostituzione delle chiavi in base ai relativi nomi:
- 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 chiavibuild/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 le cinque in build/target/product/security
e una
per sostituire la chiave aggiuntiva device/yoyodyne/security/special
richiesta 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
tasti di rilascio. Prima di eseguire il comando, puoi anche impostare la variabile di ambiente ANDROID_PW_FILE
su un nome file temporaneo. Lo script richiama quindi l'editor per consentirti di inserire le password per tutte le chiavi (questo potrebbe essere un modo più pratico per inserire le password).
Sostituzione della chiave di firma APEX
Android 10 introduce il formato file APEX per l'installazione di moduli di sistema di livello inferiore. Come spiegato in Firma APEX, ogni file APEX è firmato con due chiavi: una per l'immagine del mini file system all'interno di un APEX e l'altra 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 che tu abbia la seguente configurazione delle chiavi per i file APEX com.android.conscrypt.apex
, com.android.media.apex
e 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"
Inoltre, 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 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 file APEX vengono gestiti dalla configurazione predefinita indicata 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 genera 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 le modifiche 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 coppie di certificati/chiavi private utilizzando lo strumento openssl di 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
Il comando openssl pkcs8 riportato sopra crea un file .pk8 con nessuna password, adatto all'utilizzo 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 sui file system di rete o con log. Quando generi le chiavi, puoi utilizzare una home directory situata in un disco RAM (ad esempio una partizione tmpfs) per assicurarti che le chiavi intermedie non vengano esposte inavvertitamente.
Creare file immagine
Quando hai signed-target_files.zip
, devi creare l'immagine in modo da poterla inserire su un dispositivo.
Per creare l'immagine firmata dai file di destinazione, esegui il seguente comando dalla radice dell'albero Android:
img_from_target_files signed-target_files.zip signed-img.zip
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