APK-Signaturschema v3

Android 9 unterstützt die APK-Schlüsselrotation , wodurch Apps ihren Signaturschlüssel als Teil eines APK-Updates ändern können. Um die Rotation praktikabel zu machen, müssen APKs Vertrauensebenen zwischen dem neuen und dem alten Signaturschlüssel angeben. Um die Schlüsselrotation zu unterstützen, haben wir das APK-Signaturschema von v2 auf v3 aktualisiert, damit die neuen und alten Schlüssel verwendet werden können. 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 zentralen ZIP-Verzeichnis befindet.

Das v3-APK-Signaturblockformat ist das gleiche wie v2 . Die v3-Signatur des APK wird als ID-Wert-Paar mit der ID 0xf05368c0 gespeichert.

APK-Signaturschema v3-Block

Das v3-Schema ist dem v2-Schema sehr ähnlich. 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-Signaturschema-v3-Block ist im APK-Signaturblock unter der ID 0xf05368c0 .

Das Format des APK-Signaturschema-v3-Blocks folgt dem von v2:

  • Sequenz mit Längenpräfix von signer mit Längenpräfix :
    • Vorzeichenbehaftete signed data Längenpräfix:
      • Sequenz mit Längenpräfix von digests mit Längenpräfix:
        • signature algorithm ID (4 Bytes)
        • digest (mit Längenpräfix)
      • Sequenz mit Längenpräfix von X.509- certificates :
        • X.509- certificate mit Längenpräfix (ASN.1 DER-Formular)
      • 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 (variable-length: Länge des Zusatzattributs - 4 Bytes)
        • ID - 0x3ba06f8c
        • value - Rotationsnachweis-Struktur
    • minSDK (uint32) – Duplikat des minSDK-Werts im Abschnitt mit den signierten Daten – wird verwendet, um die Überprüfung dieser Signatur zu überspringen, wenn die aktuelle Plattform nicht in Reichweite ist. Muss mit dem signierten 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 in Reichweite ist. Muss mit dem signierten 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-Formular)

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

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

  • Behauptung 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 mit den signierten 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 geordnet, wobei das älteste Signaturzertifikat dem Stammknoten entspricht. Die Proof-of-Rotation-Datenstruktur wird aufgebaut, indem das Zertifikat in jedem Knoten das nächste in der Liste signiert und somit jeden neuen Schlüssel mit dem Beweis durchdringt, dass er genauso vertrauenswürdig sein sollte wie der/die ältere(n) Schlüssel.

Die Datenstruktur „Self-trusted-old-certs“ wird aufgebaut, indem jedem Knoten Flags hinzugefügt werden, die seine Mitgliedschaft und Eigenschaften in der Menge angeben. Beispielsweise kann ein Flag vorhanden sein, das angibt, dass dem Signaturzertifikat an einem bestimmten Knoten vertraut wird, um Android-Signaturberechtigungen zu erhalten. Dieses Flag ermöglicht anderen Apps, die mit dem älteren Zertifikat signiert wurden, weiterhin eine Signaturberechtigung zu gewähren, die von einer App definiert wird, die mit dem neuen Signaturzertifikat signiert ist. 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 . Sein Format ist:

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

Mehrere Zertifikate

Android behandelt derzeit ein mit mehreren Zertifikaten signiertes APK so, als hätte es eine eindeutige Signaturidentität, die von den umfassenden Zertifikaten getrennt ist. Somit bildet das Proof-of-Rotation-Attribut im Abschnitt mit den signierten 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 fügt der Proof-of-Rotation-Struktur zusätzliche Komplexität hinzu (Multi-Signer-Version unten). Insbesondere die Bestellung wird zu einem Problem. Darüber hinaus ist es nicht mehr möglich, APKs unabhängig voneinander zu signieren, da die Proof-of-Rotation-Struktur die alten Signaturzertifikate haben muss, die den neuen Satz von Zertifikaten signieren, anstatt sie einzeln zu signieren. Beispielsweise könnte ein von Schlüssel A signiertes APK, das von zwei neuen Schlüsseln B und C signiert werden möchte, der B-Unterzeichner nicht nur eine Signatur von A oder B hinzufügen lassen, da dies eine andere Signaturidentität als B und C ist. Dies würde bedeutet, dass sich die Unterzeichner vor dem Aufbau einer solchen Struktur koordinieren müssen.

Proof-of-Rotation-Attribut für mehrere Unterzeichner

  • längenpräfixierte Folge von längenpräfixierten sets :
    • signed data (vom vorherigen Satz - falls vorhanden)
      • längenpräfixierte Folge von certificates
        • X.509- certificate mit Längenpräfix (ASN.1 DER-Formular)
      • Sequenz von 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 sollte 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
      • signature mit Längenpräfix über den oben signed data

Mehrere Vorfahren in Proof-of-Rotation-Struktur

Das v3-Schema verarbeitet auch nicht zwei verschiedene Schlüssel, die für dieselbe App auf denselben Signaturschlüssel rotieren. Dies unterscheidet sich von dem Fall einer Akquisition, bei der das übernehmende Unternehmen die erworbene App verschieben möchte, um ihren Signaturschlüssel zum Teilen von Berechtigungen zu verwenden. Der Erwerb wird als unterstützter Anwendungsfall angesehen, da die neue App durch ihren Paketnamen unterschieden würde und eine eigene Proof-of-Rotation-Struktur enthalten könnte. Der nicht unterstützte Fall, dass dieselbe App zwei verschiedene Pfade hat, um zu demselben Zertifikat zu gelangen, bricht viele Annahmen, die im Schlüsselrotationsdesign getroffen wurden.

Überprüfung

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

APK-Signaturüberprüfungsprozess

Abbildung 1. Überprüfungsprozess der APK-Signatur

Überprüfung des APK-Signaturschemas v3

  1. Suchen Sie den APK-Signaturblock und überprüfen Sie Folgendes:
    1. Zwei Größenfelder des APK-Signaturblocks enthalten denselben Wert.
    2. ZIP Central Directory wird unmittelbar gefolgt von ZIP End of Central Directory-Datensatz.
    3. ZIP-Ende des zentralen Verzeichnisses folgen keine weiteren Daten.
  2. Suchen Sie den ersten APK-Signaturschema v3-Block innerhalb des APK-Signaturblocks. Wenn der v3-Block vorhanden ist, fahren Sie mit Schritt 3 fort. Andernfalls greifen Sie auf die Überprüfung des APK mit dem v2-Schema zurück.
  3. Für jeden signer im APK-Signaturschema v3-Block mit einer minimalen und maximalen SDK-Version, die sich im Bereich der aktuellen Plattform befindet:
    1. Wählen Sie die stärkste unterstützte signature algorithm ID aus signatures . Die Reihenfolge der Stärke hängt von jeder Implementierungs-/Plattformversion ab.
    2. Verifizieren Sie die entsprechende signature von signatures gegen signed data unter Verwendung public key . (Es ist jetzt sicher, signed data zu parsen.)
    3. Vergewissern Sie sich, dass die minimalen und maximalen SDK-Versionen in den signierten Daten mit den für den signer angegebenen übereinstimmen.
    4. Stellen Sie sicher, dass die geordnete Liste der Signaturalgorithmus-IDs in digests und signatures identisch ist. (Dies soll das Entfernen/Hinzufügen von Signaturen verhindern.)
    5. Berechnen Sie den Digest von APK-Inhalten mit demselben Digest-Algorithmus wie der 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, dass SubjectPublicKeyInfo des ersten certificate der certificates mit dem 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 in Reichweite 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 PkgInstallSignatureVerificationTest.java CTS-Tests in cts/hostsidetests/appsecurity/src/android/appsecurity/cts/ .