In Android OS-Images werden kryptografische Signaturen an zwei Stellen verwendet:
- Jede
.apk
-Datei im Image muss signiert sein. von Android Der Paketmanager verwendet eine.apk
-Signatur auf zwei Arten:- Wenn eine Anwendung ersetzt wird, muss sie mit demselben Schlüssel wie die alte Anwendung signiert werden, um Zugriff auf die Daten der alten Anwendung zu erhalten. Das gilt sowohl für das Aktualisieren von Nutzer-Apps durch Überschreiben der
.apk
als auch für das Überschreiben einer System-App durch eine neuere Version, die unter/data
installiert ist. - Wenn zwei oder mehr Anwendungen eine Nutzer-ID gemeinsam nutzen möchten (damit sie z. B. Daten teilen können), müssen sie mit demselben Schlüssel signiert sein.
- Wenn eine Anwendung ersetzt wird, muss sie mit demselben Schlüssel wie die alte Anwendung signiert werden, um Zugriff auf die Daten der alten Anwendung zu erhalten. Das gilt sowohl für das Aktualisieren von Nutzer-Apps durch Überschreiben der
- OTA-Updatepakete müssen mit einem der vom oder der Installationsprozess sie ablehnt.
Taste loslassen
Die Android-Struktur enthält test-keys unter
build/target/product/security
Android-Image erstellen
Mit make
werden alle .apk
-Dateien mit dem
Testschlüssel. Da die Testschlüssel öffentlich bekannt sind, kann jeder seine eigenen
APK-Dateien mit denselben Schlüsseln, wodurch das System möglicherweise ersetzt oder missbraucht werden kann
die in Ihr Betriebssystem-Image
integriert sind. Aus diesem Grund ist es wichtig,
veröffentlichten oder implementierten Android-Betriebssystem-Image
Release-Schlüssel, auf die nur Sie Zugriff haben.
Wenn Sie Ihre eigenen Release-Schlüssel generieren möchten, führen Sie die folgenden Befehle aus dem Stammverzeichnis Ihres Android-Baums aus:
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
sollte geändert werden, um die Anforderungen Ihrer Organisation widerzuspiegeln
Informationen. Sie können jedes Verzeichnis verwenden, achten Sie aber darauf, einen gesicherten Speicherort auszuwählen. Einige Anbieter verschlüsseln
ihren privaten Schlüssel mit einer starken Passphrase festlegen und den verschlüsselten Schlüssel speichern,
in der Versionsverwaltung andere speichern ihre
Lösetasten an einem anderen Ort.
etwa auf einem Computer mit Air Gap.
So erstellst du ein Release-Image:
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
Das Skript sign_target_files_apks
verwendet eine Zieldatei
.zip
als Eingabe und erzeugt eine neue Zieldatei .zip
in
Damit wurden alle .apk
-Dateien mit neuen Schlüsseln signiert. Die neu signierten Bilder finden Sie unter IMAGES/
in signed-target_files.zip
.
OTA-Pakete signieren
Eine signierte ZIP-Datei mit Zieldateien kann in eine signierte OTA-Update-ZIP-Datei konvertiert werden Gehen Sie dabei so vor:
ota_from_target_files \
-k (--package_key)
signed-target_files.zip \
signed-ota_update.zip
Signaturen und Sideloading
Beim Sideloading wird die normale Paketsignatur der Wiederherstellung nicht umgangen Bestätigungsmechanismus: Vor der Installation eines Pakets wird bei der Wiederherstellung Es ist mit einem der privaten Schlüssel signiert, die mit den öffentlichen Schlüsseln übereinstimmen, die in in die Wiederherstellungspartition, genau wie bei einem over-the-air zugestellten Paket.
Vom Hauptsystem empfangene Updatepakete werden in der Regel zweimal überprüft:
einmal vom Hauptsystem mit der Methode
RecoverySystem.verifyPackage()
in der Android API und dann wieder durch
Genesung. Die RecoverySystem API prüft die Signatur mit öffentlichen Schlüsseln
im Hauptsystem in der Datei /system/etc/security/otacerts.zip
(standardmäßig) gespeichert. Bei der Wiederherstellung wird die Signatur auf gespeicherte öffentliche Schlüssel geprüft
auf der RAM-Disk der Wiederherstellungspartition in der Datei /res/keys
.
Standardmäßig wird in den vom Build erstellten Zieldateien .zip
das OTA-Zertifikat so festgelegt, dass es mit dem Testschlüssel übereinstimmt. Bei einem veröffentlichten Image muss ein anderes Zertifikat verwendet werden, damit Geräte die Authentizität des Update-Pakets überprüfen können. Wenn Sie das Flag -o
an sign_target_files_apks
übergeben, wie im vorherigen Abschnitt gezeigt, wird das Testschlüsselzertifikat durch das Release-Schlüsselzertifikat aus Ihrem certs-Verzeichnis ersetzt.
Normalerweise werden im System- und im Wiederherstellungs-Image dieselben öffentlichen OTA-Schlüssel gespeichert. Wenn Sie einen Schlüssel nur dem Schlüsselsatz für die Wiederherstellung hinzufügen, können Sie Pakete signieren, die nur per Sideloading installiert werden können, vorausgesetzt, der Update-Downloadmechanismus des Hauptsystems führt die Überprüfung korrekt anhand von otacerts.zip durch. Sie können zusätzliche Schlüssel angeben, werden nur bei der Wiederherstellung berücksichtigt, indem Sie PRODUCT_EXTRA_RECOVERY_KEYS festlegen. Variable in Ihrer Produktdefinition:
vendor/yoyodyne/tardis/products/tardis.mk
[...] PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload
Dazu gehört der öffentliche Schlüssel vendor/yoyodyne/security/tardis/sideload.x509.pem
in der Datei „recoverykeys“, damit damit signierte Pakete installiert werden können. Da der zusätzliche Schlüssel nicht in otacerts.zip enthalten ist,
Systeme, die heruntergeladene Pakete korrekt verifizieren, führen keine Wiederherstellung für
mit diesem Schlüssel signierte Pakete.
Zertifikate und private Schlüssel
Jeder Schlüssel wird in zwei Dateien geliefert: dem Zertifikat mit dem die Erweiterung .x509.pem und den privaten Schlüssel mit der Erweiterung .pk8. Der private Schlüssel sollte geheim gehalten werden und ist zum Signieren eines Pakets erforderlich. Der Schlüssel kann selbst durch ein Passwort geschützt sein. Das Zertifikat enthält dagegen nur die öffentliche Hälfte des Schlüssels und kann daher weit verbreitet verteilt werden. Hiermit wird überprüft, ob ein Paket vom entsprechenden privaten Schlüssel enthält.
Im Standard-Android-Build werden fünf Schlüssel verwendet, die sich alle in
build/target/product/security
befinden:
- testkey
- Generischer Standardschlüssel für Pakete, die keinen Schlüssel angeben.
- Plattform
- Testschlüssel für Pakete, die Teil der Hauptplattform sind.
- geteilt
- Testschlüssel für Dinge, die im Zuhause/Kontakt-Prozess geteilt wurden
- Medien
- Testschlüssel für Pakete, die Teil des Medien-/Download-Systems sind.
Einzelne Pakete geben einen dieser Schlüssel an, indem sie LOCAL_CERTIFICATE in ihrer Android.mk-Datei festlegen. (Wenn diese Variable nicht festgelegt ist, wird testkey verwendet.) Sie können auch einen völlig anderen Schlüssel über den Pfad angeben, z. B.:
device/yoyodyne/apps/SpecialApp/Android.mk
[...] LOCAL_CERTIFICATE := device/yoyodyne/security/special
Jetzt verwendet der Build den Schlüssel device/yoyodyne/security/special.{x509.pem,pk8}
zum Signieren von SpecialApp.apk. Der Build kann nur private Schlüssel verwenden, die
sind nicht passwortgeschützt.
Erweiterte Signaturoptionen
Ersatz des APK-Signaturschlüssels
Das Signaturskript sign_target_files_apks
wird auf dem Ziel ausgeführt
-Dateien, die für einen Build generiert wurden. Alle Informationen zu Zertifikaten und privaten Schlüsseln, die zum Zeitpunkt des Builds verwendet wurden, sind in den Zieldateien enthalten. Wenn Sie das Signaturskript zum Signieren für die Veröffentlichung ausführen, können Signaturschlüssel basierend auf dem Schlüsselnamen oder APK-Namen ersetzt werden.
Verwenden Sie die Flags --key_mapping
und --default_key_mappings
, um die Schlüsselersetzung basierend auf Schlüsselnamen anzugeben:
- Das Flag
--key_mapping src_key=dest_key
gibt den Ersatz für jeweils einen Schlüssel an. - Das Flag
--default_key_mappings dir
gibt eine mit fünf Schlüsseln, um alle Schlüssel inbuild/target/product/security
; entspricht dies der Verwendung--key_mapping
, um die Zuordnungen anzugeben.
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
Verwenden Sie die Methode
--extra_apks apk_name1,apk_name2,...=key
-Flag
, um die Ersetzungen des Signaturschlüssels basierend auf den APK-Namen anzugeben. Wenn key
leer bleibt, werden die angegebenen APKs vom Script als vorab signiert behandelt.
Für das hypothetische Tardis-Produkt benötigen Sie sechs passwortgeschützte Schlüssel:
eine Fünf, um die fünf in build/target/product/security
zu ersetzen, und eine
zum Ersetzen des zusätzlichen Schlüssels device/yoyodyne/security/special
im obigen Beispiel für SpecialApp erforderlich. Wenn die Schlüssel in den folgenden
Dateien:
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
Anschließend signieren Sie alle Apps so:
./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
Daraufhin wird Folgendes angezeigt:
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.
Nachdem der Nutzer zur Eingabe von Passwörtern für alle passwortgeschützten Schlüssel aufgefordert wurde,
Das Skript signiert alle APK-Dateien im Eingabeziel .zip
neu mit dem
um die Tasten loszulassen. Vor dem Ausführen des Befehls können Sie die Umgebungsvariable ANDROID_PW_FILE
auch auf einen temporären Dateinamen festlegen. Das Script ruft dann Ihren Editor auf, damit Sie Passwörter für alle Schlüssel eingeben können. Dies ist möglicherweise eine praktischere Möglichkeit, Passwörter einzugeben.
Ersatz des APEX-Signaturschlüssels
Mit Android 10 wird das APEX-Dateiformat für die Installation von Systemmodulen der unteren Ebene eingeführt. Wie unter APEX-Signatur erläutert, wird jede APEX-Datei mit zwei Schlüsseln signiert: einer für das Mini-Dateisystem-Image in einer APEX-Datei und der andere für die gesamte APEX-Datei.
Beim Signieren für den Release werden die beiden Signaturschlüssel für eine APEX-Datei ersetzt
mit den Releasetasten. Der Schlüssel für die Dateisystemnutzlast wird mit dem Flag --extra_apex_payload
und der Schlüssel für die gesamte APEX-Dateisignatur mit dem Flag --extra_apks
angegeben.
Nehmen wir für das Tardis-Produkt an, dass Sie die folgende Schlüsselkonfiguration haben.
für com.android.conscrypt.apex
,
com.android.media.apex
und
com.android.runtime.release.apex
APEX-Dateien.
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"
Außerdem haben Sie die folgenden Dateien mit den Release-Schlüsseln:
vendor/yoyodyne/security/runtime_apex_container.x509.pem vendor/yoyodyne/security/runtime_apex_container.pk8 vendor/yoyodyne/security/runtime_apex_payload.pem
Der folgende Befehl überschreibt die Signaturschlüssel für
com.android.runtime.release.apex
und
com.android.tzdata.apex
während der Release-Signatur. Insbesondere
com.android.runtime.release.apex
ist signiert mit dem angegebenen
Release-Tasten (runtime_apex_container
für die APEX-Datei und
runtime_apex_payload
für die Nutzlast des Dateibilds.
com.android.tzdata.apex
wird als vorab signiert behandelt. Alle anderen APEX
-Dateien werden von der Standardkonfiguration verarbeitet, die in den Zieldateien aufgeführt ist.
./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
Wenn Sie den obigen Befehl ausführen, erhalten Sie folgende Logs:
[...] 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) [...]
Sonstige Optionen
Das sign_target_files_apks
-Signaturskript überschreibt die Build-Beschreibung und den Fingerabdruck in den Build-Eigenschaftsdateien, um anzugeben, dass es sich um einen signierten Build handelt. Das Flag --tag_changes
steuert, welche Änderungen am Fingerabdruck vorgenommen werden. Führen Sie das Script mit -h
aus, um die Dokumentation zu allen Flags aufzurufen.
Schlüssel manuell generieren
Android verwendet 2048-Bit-RSA-Schlüssel mit dem öffentlichen Exponenten 3. Sie können Zertifikats-/private Schlüsselpaare mit dem OpenSSL-Tool von openssl.org generieren:
# 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
Mit dem oben angegebenen Befehl „openssl pkcs8“ wird eine PK8-Datei mit dem Wert no erstellt.
Passwort, das für das Build-System geeignet ist. So erstellen Sie eine gesicherte PK8-Datei:
durch ein Passwort (was Sie für alle tatsächlichen Freigabetasten tun sollten), ersetzen Sie die
Argument -nocrypt
mit -passout stdin
; dann openssl
verschlüsselt den privaten Schlüssel mit einem Passwort, das aus der Standardeingabe gelesen wird. Nein
-Eingabeaufforderung wird ausgegeben. Wenn stdin das Terminal ist, scheint sich das Programm also aufzuhängen.
wenn er nur darauf wartet, dass Sie ein Passwort eingeben. Andere Werte können
wird für das Argument-passout verwendet, um das Passwort aus anderen Speicherorten auszulesen. für
finden Sie in der
openssl-Dokumentation.
Die Zwischendatei „temp.pem“ enthält den privaten Schlüssel ohne Passwortschutz. Entfernen Sie sie daher sorgfältig, wenn Sie Release-Schlüssel generieren. Insbesondere ist das GNUshred-Dienstprogramm möglicherweise nicht effektiv bei Netzwerk- oder protokollierten Dateisystemen. Sie können ein Arbeitsverzeichnis auf einer RAM-Disk verwenden (z. B. einer temporären Partition) beim Generieren von Schlüsseln, um sicherzustellen, dass die nicht versehentlich entblößt werden.
Bilddateien erstellen
Wenn Sie signed-target_files.zip
haben, müssen Sie das Image erstellen, damit Sie es auf ein Gerät übertragen können.
Führen Sie zum Erstellen des signierten Images aus den Zieldateien den folgenden Befehl im Stammverzeichnis des Android-Baums aus:
img_from_target_files signed-target_files.zip signed-img.zip
signed-img.zip
enthält alle .img
-Dateien.
So laden Sie ein Image auf ein Gerät:
fastboot update signed-img.zip