Builds für den Release signieren

In Android OS-Images werden kryptografische Signaturen an zwei Stellen verwendet:

  1. Jede .apk-Datei im Bild 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 signiert werden wie der um auf die Daten der alten Anwendung zuzugreifen. Holds "true" sowohl für das Aktualisieren von Nutzer-Apps durch Überschreiben von .apk als auch für System-App überschreiben, unter der eine neuere Version installiert ist /data.
    • Wenn zwei oder mehr Anwendungen eine User-ID teilen möchten (damit sie Daten usw.), müssen sie mit demselben Schlüssel signiert werden.
  2. 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.

Führen Sie diese Befehle aus, um Ihre eigenen eindeutigen Release-Schlüssel zu generieren: der Stammstruktur Ihres Android-Baums:

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 beliebige Verzeichnis verwenden. Achten Sie jedoch darauf, die gesichert und geschützt ist. 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. Das neue signierte 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" gelieferten 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 legen die vom Build erstellten Zieldateien (.zip) den Parameter OTA-Zertifikat, das mit dem Testschlüssel übereinstimmt. Für ein veröffentlichtes Image ist muss verwendet werden, damit Geräte die Authentizität Update-Paket. Wenn Sie das Flag -o an sign_target_files_apks, wie im vorherigen Abschnitt gezeigt, das Testschlüsselzertifikat mit dem Releaseschlüsselzertifikat aus Ihren Zertifikaten -Verzeichnis.

Normalerweise speichern das System-Image und das Wiederherstellungs-Image denselben OTA-Satz. öffentlichen Schlüsseln. Wenn Sie nur dem Schlüssel für die Wiederherstellung einen Schlüssel hinzufügen, Pakete zu signieren, die nur per Sideloading installiert werden können (vorausgesetzt, der Downloadmechanismus für Updates des Hauptsystems funktioniert Überprüfung anhand von otacerts.zip). 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 auch der öffentliche Schlüssel vendor/yoyodyne/security/tardis/sideload.x509.pem in der Erholungsphase Schlüsseldatei, um signierte Pakete zu installieren. damit nichts. 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 wird zum Signieren eines Pakets benötigt. Der Schlüssel kann selbst durch ein Passwort geschützt sein. Das Zertifikat in enthält, enthält nur die öffentliche Hälfte des Schlüssels und kann weit verbreitet sind. 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:

Testschlüssel
Generischer Standardschlüssel für Pakete, die keinen Schlüssel angeben.
Plattform
Testschlüssel für Pakete, die zur Kernplattform gehören.
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.
NetworkStack
Testschlüssel für Pakete, die Teil des Netzwerksystems sind. Die Der Networkstack-Schlüssel wird zum Signieren von Binärdateien verwendet, die als Modulare Systemkomponenten Wenn Ihre Modulupdates separat erstellt und als vorkonfigurierte Updates integriert werden in Ihrem Gerätebild angezeigt wird, müssen Sie möglicherweise keinen Netzwerkstack-Schlüssel in der Android-Quellstruktur.

Für einzelne Pakete wird einer dieser Schlüssel durch Festlegen von LOCAL_CERTIFICATE angegeben in der Android.mk-Datei. (Wenn diese Variable nicht festgelegt ist, wird testkey verwendet.) Ich kann auch einen ganz anderen Schlüssel über den Pfadnamen 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

Austausch 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 Die bei der Erstellung verwendeten Schlüssel sind in den Zieldateien enthalten. Wenn Sie den Signaturskript zum Signieren für die Veröffentlichung, Signaturschlüssel können anhand des Schlüssels ersetzt werden Name oder APK-Name.

--key_mapping und --default_key_mappings verwenden Flags, um die Ersetzung von Schlüsseln auf Basis von 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 in build/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, behandelt das Skript die angegebenen APKs. vorsigniert.

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

Dann würden Sie alle Apps so signieren:

./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. Bevor Sie den Befehl ausführen, können Sie ANDROID_PW_FILE in einen temporären Dateinamen umgewandelt. die ruft das Skript Ihren Editor auf, damit Sie Passwörter für alle Schlüssel eingeben können. So lassen sich Passwörter einfacher eingeben.

Ersatz des APEX-Signaturschlüssels

Mit Android 10 APEX-Dateiformat für die Installation untergeordnete Systemmodule. Wie in den Mit der APEX-Signatur wird jede APEX-Datei mit zwei Schlüsseln signiert: einem für das Mini-Dateisystem-Image in einem APEX und dem für das gesamte APEX.

Beim Signieren für den Release werden die beiden Signaturschlüssel für eine APEX-Datei ersetzt mit den Releasetasten. Der Nutzlastschlüssel des Dateisystems wird mit dem Das Flag --extra_apex_payload und der gesamte Signaturschlüssel der APEX-Datei ist 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"

Und Sie haben die folgenden Dateien, die die Release-Tasten enthalten:

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 vorsigniert 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 Signaturskript sign_target_files_apks schreibt den Build neu Beschreibung und Fingerabdruck in den Build-Attributdateien darauf, dass der "build" ist ein signierter Build. Mit dem Flag --tag_changes wird gesteuert, welche Änderungen auf den Fingerabdruck. Führen Sie das Skript mit -h aus, um Dokumentation zu allen Flags.

Schlüssel manuell generieren

Android verwendet 2048-Bit-RSA-Schlüssel mit dem öffentlichen Exponenten 3. Sie können Zertifikat/private Schlüsselpaare mit dem openssl-Tool von 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

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 <ph type="x-smartling-placeholder"></ph> openssl-Dokumentation.

Die Zwischendatei „temp.pem“ enthält den privaten Schlüssel ohne Passwortschutz, bei der Veröffentlichung des Release Schlüssel. Insbesondere kann es sein, dass GNUshred nicht auf Netzwerk- oder Journaling-Dateisysteme. 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 du signed-target_files.zip hast, musst du Folgendes tun: erstellen Sie das Image, damit Sie es auf einem Gerät platzieren können. Führen Sie den folgenden Befehl aus, um das signierte Image aus den Zieldateien zu erstellen: Befehl aus dem Stammverzeichnis des Android- Baum:

img_from_target_files signed-target_files.zip signed-img.zip
Die resultierende Datei signed-img.zip enthält alle .img-Dateien. Um ein Image auf ein Gerät zu laden, verwenden Sie Fastboot als folgt:
fastboot update signed-img.zip