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 Byte) -
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)
- X.509-
-
minSDK
(uint32) – dieser Unterzeichner sollte ignoriert werden, wenn die Plattformversion unter dieser Zahl 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
-
- Sequenz mit Längenpräfix von
-
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 übersigned data
-
-
public key
mit Längenpräfix (SubjectPublicKeyInfo, ASN.1 DER-Formular)
- Vorzeichenbehaftete
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
- X.509-
-
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 obensigned data
- längenpräfixierte
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)
- X.509-
- Sequenz von
signature algorithm IDs
(uint32) – eine für jedes Zertifikat aus dem vorherigen Satz, in derselben Reihenfolge.
- längenpräfixierte Folge von
-
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 obensigned 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.
Abbildung 1. Überprüfungsprozess der APK-Signatur
Überprüfung des APK-Signaturschemas v3
- Suchen Sie den APK-Signaturblock und überprüfen Sie Folgendes:
- Zwei Größenfelder des APK-Signaturblocks enthalten denselben Wert.
- ZIP Central Directory wird unmittelbar gefolgt von ZIP End of Central Directory-Datensatz.
- ZIP-Ende des zentralen Verzeichnisses folgen keine weiteren Daten.
- 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.
- Für jeden
signer
im APK-Signaturschema v3-Block mit einer minimalen und maximalen SDK-Version, die sich im Bereich der aktuellen Plattform befindet:- Wählen Sie die stärkste unterstützte
signature algorithm ID
aussignatures
. Die Reihenfolge der Stärke hängt von jeder Implementierungs-/Plattformversion ab. - Verifizieren Sie die entsprechende
signature
vonsignatures
gegensigned data
unter Verwendungpublic key
. (Es ist jetzt sicher,signed data
zu parsen.) - Vergewissern Sie sich, dass die minimalen und maximalen SDK-Versionen in den signierten Daten mit den für den
signer
angegebenen übereinstimmen. - Stellen Sie sicher, dass die geordnete Liste der Signaturalgorithmus-IDs in
digests
undsignatures
identisch ist. (Dies soll das Entfernen/Hinzufügen von Signaturen verhindern.) - Berechnen Sie den Digest von APK-Inhalten mit demselben Digest-Algorithmus wie der Digest-Algorithmus, der vom Signaturalgorithmus verwendet wird.
- Stellen Sie sicher, dass der berechnete Digest mit dem entsprechenden
digest
ausdigests
identisch ist. - Stellen Sie sicher, dass SubjectPublicKeyInfo des ersten
certificate
dercertificates
mit dempublic key
identisch ist. - Wenn das Proof-of-Rotation-Attribut für den
signer
vorhanden ist, überprüfen Sie, ob die Struktur gültig ist und diesersigner
das letzte Zertifikat in der Liste ist.
- Wählen Sie die stärkste unterstützte
- Die Überprüfung ist erfolgreich, wenn genau ein
signer
in Reichweite der aktuellen Plattform gefunden wurde und Schritt 3 für diesensigner
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/
.