APK-Signaturschema v3

Android 9 unterstützt die APK-Schlüsselrotation , was Apps die Möglichkeit gibt, ihren Signaturschlüssel im Rahmen eines APK-Updates zu ändern. Um die Rotation praktikabel zu machen, müssen APKs Vertrauensstufen zwischen dem neuen und dem alten Signaturschlüssel angeben. Um die Schlüsselrotation zu unterstützen, haben wir das APK-Signaturschema von Version 2 auf Version 3 aktualisiert, um die Verwendung der neuen und alten Schlüssel zu ermöglichen. V3 fügt dem APK-Signaturblock Informationen zu den unterstützten SDK-Versionen und eine Proof-of-Rotation-Struktur hinzu.

APK-Signaturblock

Um die Abwärtskompatibilität mit dem v1-APK-Format aufrechtzuerhalten, werden v2- und v3-APK-Signaturen in einem APK-Signaturblock gespeichert, der sich unmittelbar vor dem ZIP-Zentralverzeichnis befindet.

Das APK-Signaturblockformat der Version 3 ist dasselbe wie das Format der Version 2 . Die v3-Signatur des APK wird als ID-Wert-Paar mit der ID 0xf05368c0 gespeichert.

APK Signature Scheme v3 Block

Das v3-Schema ist so konzipiert, dass es dem v2-Schema sehr ähnlich ist. Es hat das gleiche allgemeine Format und unterstützt die gleichen Signaturalgorithmus-IDs , Schlüsselgrößen und EC-Kurven.

Das v3-Schema fügt jedoch Informationen zu den unterstützten SDK-Versionen und der Proof-of-Rotation-Struktur hinzu.

Format

Der APK Signature Scheme v3 Block wird im APK Signing Block unter der ID 0xf05368c0 gespeichert.

Das Format des APK Signature Scheme v3 Blocks folgt dem von v2:

  • Längenpräfixierte Sequenz des längenpräfixierten signer :
    • signed data mit Längenpräfix:
      • Längenpräfixierte Folge von digests mit Längenpräfix:
        • signature algorithm ID (4 Bytes)
        • digest (mit Längenpräfix)
      • Längenpräfixierte Sequenz von X.509- certificates :
        • X.509- certificate mit Längenpräfix (ASN.1 DER-Form)
      • minSDK (uint32) – dieser Unterzeichner sollte ignoriert werden, wenn die Plattformversion unter dieser Nummer liegt.
      • maxSDK (uint32) – dieser Unterzeichner sollte ignoriert werden, wenn die Plattformversion über dieser Nummer liegt.
      • Längenpräfixierte Folge von längenpräfixierten additional attributes :
        • ID (uint32)
        • value (Variablenlänge: Länge des zusätzlichen Attributs - 4 Bytes)
        • ID - 0x3ba06f8c
        • value - Proof-of-Rotation-Struktur
    • minSDK (uint32) – Duplikat des minSDK-Werts im signierten Datenabschnitt – wird verwendet, um die Überprüfung dieser Signatur zu überspringen, wenn die aktuelle Plattform nicht im Bereich liegt. Muss mit dem vorzeichenbehafteten Datenwert übereinstimmen.
    • maxSDK (uint32) – Duplikat des maxSDK-Werts im signierten Datenabschnitt – wird verwendet, um die Überprüfung dieser Signatur zu überspringen, wenn die aktuelle Plattform nicht im Bereich liegt. Muss mit dem vorzeichenbehafteten Datenwert übereinstimmen.
    • Längenpräfixierte Folge von längenpräfixierten signatures :
      • signature algorithm ID (uint32)
      • signature mit Längenpräfix über signed data
    • public key mit Längenpräfix (SubjectPublicKeyInfo, ASN.1 DER-Form)

Proof-of-Rotation und Self-Trusted-Old-Certs-Strukturen

Die Proof-of-Rotation-Struktur ermöglicht es Apps, ihr Signaturzertifikat zu rotieren, ohne für andere Apps, mit denen sie kommunizieren, blockiert zu werden. Um dies zu erreichen, enthalten App-Signaturen zwei neue Daten:

  • Zusicherung für Dritte, dass dem Signaturzertifikat der App überall dort vertraut werden kann, wo seinen Vorgängern vertraut wird
  • Die älteren Signaturzertifikate der App, denen die App selbst noch vertraut

Das Proof-of-Rotation-Attribut im Abschnitt „Signierte Daten“ besteht aus einer einfach verknüpften Liste, wobei jeder Knoten ein Signaturzertifikat enthält, das zum Signieren früherer Versionen der App verwendet wurde. Dieses Attribut soll die konzeptionellen Proof-of-Rotation- und Self-Trusted-Old-Certs-Datenstrukturen enthalten. Die Liste ist nach Version sortiert, wobei das älteste Signaturzertifikat dem Stammknoten entspricht. Die Proof-of-Rotation-Datenstruktur wird dadurch aufgebaut, dass das Zertifikat in jedem Knoten das nächste in der Liste signiert und so jedem neuen Schlüssel den Beweis verleiht, dass er genauso vertrauenswürdig sein sollte wie der/die ältere(n) Schlüssel.

Die Datenstruktur „Self-Trusted-Old-Certs“ wird durch das Hinzufügen von Flags zu jedem Knoten erstellt, die seine Mitgliedschaft und Eigenschaften im Satz angeben. Beispielsweise kann ein Flag vorhanden sein, das angibt, dass das Signaturzertifikat an einem bestimmten Knoten für den Erhalt von Android-Signaturberechtigungen vertrauenswürdig ist. Dieses Flag ermöglicht es anderen Apps, die mit dem älteren Zertifikat signiert wurden, weiterhin eine Signaturberechtigung zu erhalten, die von einer App definiert wurde, die mit dem neuen Signaturzertifikat signiert wurde. Da sich das gesamte Proof-of-Rotation-Attribut im signierten Datenabschnitt des v3- signer befindet, ist es durch den Schlüssel geschützt, der zum Signieren der enthaltenden APK verwendet wird.

Dieses Format schließt mehrere Signaturschlüssel und die Konvergenz verschiedener Vorfahren-Signaturzertifikate zu einem aus (mehrere Startknoten zu einer gemeinsamen Senke).

Format

Der Rotationsnachweis wird im APK Signature Scheme v3 Block unter der ID 0x3ba06f8c gespeichert. Sein Format ist:

  • längenpräfixierte Folge von längenpräfixierten levels :
    • signed data mit Längenpräfix (vom vorherigen Zertifikat – falls vorhanden)
      • X.509- certificate mit Längenpräfix (ASN.1 DER-Form)
      • signature algorithm ID (uint32) – Algorithmus, der von cert in der vorherigen Ebene verwendet wurde
    • flags (uint32) – Flags, die angeben, ob dieses Zertifikat in der Struktur „self-trusted-old-certs“ enthalten sein soll und für welche Vorgänge.
    • signature algorithm ID (uint32) – muss mit der aus dem signierten Datenabschnitt in der nächsten Ebene übereinstimmen.
    • längenpräfixierte signature über den oben signed data

Mehrere Zertifikate

Android behandelt derzeit ein APK, das mit mehreren Zertifikaten signiert ist, so, als hätte es eine eindeutige Signaturidentität, die von den Zertifikaten, aus denen es besteht, getrennt ist. Somit bildet das Proof-of-Rotation-Attribut im Abschnitt mit vorzeichenbehafteten Daten einen gerichteten azyklischen Graphen, der besser als einfach verknüpfte Liste betrachtet werden könnte, wobei jeder Satz von Unterzeichnern für eine bestimmte Version einen Knoten darstellt. Dies erhöht die Komplexität der Proof-of-Rotation-Struktur (Version mit mehreren Unterzeichnern unten). Insbesondere die Bestellung wird zum Problem. Darüber hinaus ist es nicht mehr möglich, APKs unabhängig voneinander zu signieren, da in der Proof-of-Rotation-Struktur die alten Signaturzertifikate den neuen Satz von Zertifikaten signieren müssen, anstatt sie einzeln zu signieren. Beispielsweise könnte ein mit Schlüssel A signiertes APK, das mit zwei neuen Schlüsseln B und C signiert werden möchte, nicht dafür sorgen, dass der B-Unterzeichner einfach eine Signatur von A oder B einfügt, da dies eine andere Signaturidentität als B und C ist. Dies wäre der Fall bedeuten, dass sich die Unterzeichner vor dem Aufbau einer solchen Struktur abstimmen müssen.

Rotationsnachweisattribut für mehrere Unterzeichner

  • längenpräfixierte Folge von längenpräfixierten sets :
    • signed data (nach vorherigem Satz – falls vorhanden)
      • längenpräfixierte Folge von certificates
        • X.509- certificate mit Längenpräfix (ASN.1 DER-Form)
      • Reihenfolge der signature algorithm IDs (uint32) – eine für jedes Zertifikat aus dem vorherigen Satz, in derselben Reihenfolge.
    • flags (uint32) – Flags, die angeben, ob dieser Satz von Zertifikaten in der Struktur „self-trusted-old-certs“ enthalten sein soll und für welche Vorgänge.
    • Längenpräfixierte Folge von längenpräfixierten signatures :
      • signature algorithm ID (uint32) – muss mit der aus dem signierten Datenabschnitt übereinstimmen
      • längenpräfixierte signature über den oben signed data

Mehrere Vorfahren in der Proof-of-Rotation-Struktur

Das v3-Schema verarbeitet auch nicht zwei verschiedene Schlüssel, die zu demselben Signaturschlüssel für dieselbe App rotieren. Dies unterscheidet sich vom Fall einer Akquisition, bei der das erwerbende Unternehmen die erworbene App so verschieben möchte, dass sie ihren Signaturschlüssel zum Teilen von Berechtigungen verwendet. Die Übernahme wird als unterstützter Anwendungsfall angesehen, da sich die neue App durch ihren Paketnamen unterscheiden würde und eine eigene Proof-of-Rotation-Struktur enthalten könnte. Der nicht unterstützte Fall, dass dieselbe App zwei unterschiedliche Pfade hat, um zum selben Zertifikat zu gelangen, verstößt gegen viele der im Schlüsselrotationsdesign getroffenen Annahmen.

Überprüfung

In Android 9 und höher können APKs gemäß dem APK-Signaturschema v3, v2-Schema oder v1-Schema überprüft werden. Ältere Plattformen ignorieren v3-Signaturen und versuchen, v2-Signaturen und dann v1 zu überprüfen.

APK-Signaturüberprüfungsprozess

Abbildung 1. APK-Signaturüberprüfungsprozess

Überprüfung des APK Signature Scheme v3

  1. Suchen Sie den APK-Signaturblock und überprüfen Sie Folgendes:
    1. Zwei Größenfelder des APK-Signaturblocks enthalten denselben Wert.
    2. Auf „ZIP Central Directory“ folgt unmittelbar der Eintrag „ZIP End of Central Directory“.
    3. Auf das ZIP-Ende des zentralen Verzeichnisses folgen keine weiteren Daten.
  2. Suchen Sie den ersten APK Signature Scheme v3-Block im APK-Signaturblock. Wenn der v3-Block vorhanden ist, fahren Sie mit Schritt 3 fort. Andernfalls greifen Sie auf die Überprüfung des APK mithilfe des v2-Schemas zurück.
  3. Für jeden signer im APK Signature Scheme v3-Block mit einer minimalen und maximalen SDK-Version, die im Bereich der aktuellen Plattform liegt:
    1. Wählen Sie aus signatures die stärkste unterstützte signature algorithm ID aus. Die Reihenfolge der Stärke hängt von der jeweiligen Implementierung/Plattformversion ab.
    2. Überprüfen Sie die entsprechende signature von signatures anhand signed data mithilfe public key . (Es ist jetzt sicher, signed data zu analysieren.)
    3. Stellen Sie sicher, dass die minimalen und maximalen SDK-Versionen in den signierten Daten mit denen übereinstimmen, die für den signer angegeben wurden.
    4. Stellen Sie sicher, dass die geordnete Liste der Signaturalgorithmus-IDs in digests und signatures identisch ist. (Dies dient dazu, das Entfernen/Hinzufügen von Signaturen zu verhindern.)
    5. Berechnen Sie den Digest von APK-Inhalten mit demselben Digest-Algorithmus wie dem Digest-Algorithmus, der vom Signaturalgorithmus verwendet wird.
    6. Stellen Sie sicher, dass der berechnete Digest mit dem entsprechenden digest aus digests identisch ist.
    7. Stellen Sie sicher certificates dass SubjectPublicKeyInfo des ersten certificate mit public key identisch ist.
    8. Wenn das Proof-of-Rotation-Attribut für den signer vorhanden ist, überprüfen Sie, ob die Struktur gültig ist und dieser signer das letzte Zertifikat in der Liste ist.
  4. Die Überprüfung ist erfolgreich, wenn genau ein signer im Bereich der aktuellen Plattform gefunden wurde und Schritt 3 für diesen signer erfolgreich war.

Validierung

Um zu testen, ob Ihr Gerät v3 ordnungsgemäß unterstützt, führen Sie die CTS-Tests PkgInstallSignatureVerificationTest.java in cts/hostsidetests/appsecurity/src/android/appsecurity/cts/ aus.