Android 9 obsługuje rotację klucza APK, która umożliwia aplikacjom zmianę klucza podpisywania w ramach aktualizacji pliku APK. Aby rotacja była praktyczna, pliki APK muszą wskazywać poziomy zaufania między nowym a starym kluczem podpisywania. Aby umożliwić rotację kluczy, zaktualizowaliśmy schemat podpisywania plików APK z wersji 2 na 3, aby umożliwić używanie nowych i starych kluczy. Wersja 3 zawiera informacje o obsługiwanych wersjach pakietu SDK oraz strukturę dowodu rotacji, które są dodawane do bloku podpisywania pliku APK.
Blok podpisywania pliku APK
Aby zachować zgodność wsteczną z formatem pliku APK w wersji 1, podpisy plików APK w wersji 2 i 3 są przechowywane w bloku podpisywania pliku APK, który znajduje się tuż przed katalogiem głównym ZIP.
Format bloku podpisywania APK w wersji 3 jest taki sam jak w wersji 2. Podpis w wersji 3 pliku APK jest przechowywany jako para identyfikator–wartość z identyfikatorem 0xf05368c0.
Blok schematu podpisu APK w wersji 3
Schemat v3 jest bardzo podobny do schematu v2. Ma ten sam ogólny format i obsługuje te same identyfikatory algorytmów podpisu, rozmiary kluczy i krzywe EC.
Schemat v3 zawiera jednak informacje o obsługiwanych wersjach pakietu SDK oraz strukturę proof-of-rotation.
Format
Blok schematu podpisu APK w wersji 3 jest przechowywany w bloku podpisywania APK pod identyfikatorem 0xf05368c0
.
Format bloku schematu podpisu APK w wersji 3 jest zgodny z formatem w wersji 2:
- sekwencja z przedrostkiem długości zawierająca
signer
z przedrostkiem długości:signed data
z preiksem długości:- sekwencja z przedrostkiem długości zawierająca
digests
z przedrostkiem długości:signature algorithm ID
(4 bajty)digest
(z preiksem długości)
- sekwencja X.509 z preiksem długości:
certificates
:- X.509 z prefiksem długości
certificate
(format ASN.1 DER)
- X.509 z prefiksem długości
minSDK
(uint32) – ten podpisujący powinien zostać zignorowany, jeśli wersja platformy jest niższa od tego numeru.maxSDK
(uint32) – ten podpis powinien zostać zignorowany, jeśli wersja platformy jest większa od tego numeru.- sekwencja z przedrostkiem długości zawierająca
additional attributes
z przedrostkiem długości:ID
(uint32)value
(długość zmienna: długość dodatkowego atrybutu – 4 bajty)ID - 0x3ba06f8c
value -
Struktura potwierdzenia rotacji
- sekwencja z przedrostkiem długości zawierająca
minSDK
(uint32) – duplikat wartości minSDK w sekcji podpisanych danych – służy do pominięcia weryfikacji tego podpisu, jeśli bieżąca platforma nie mieści się w zakresie. Musi być zgodna z wartością danych ze znakiem.maxSDK
(uint32) – duplikat wartości maxSDK w sekcji danych podpisanych – służy do pominięcia weryfikacji tego podpisu, jeśli bieżąca platforma nie mieści się w zakresie. Musi być zgodna z wartością danych ze znakiem.- sekwencja z przedrostkiem długości zawierająca
signatures
z przedrostkiem długości:signature algorithm ID
(uint32)- długość z preiksem
signature
nadsigned data
public key
z prefiksem długości (format SubjectPublicKeyInfo, ASN.1 DER)
Struktury potwierdzenia rotacji i starych certyfikatów z własnym zaufaniem
Struktura dowodząca rotacji umożliwia aplikacjom rotację certyfikatu podpisywania bez blokowania innych aplikacji, z którymi się komunikują. Aby to osiągnąć, podpisy aplikacji zawierają 2 nowe rodzaje danych:
- oświadczenie dla osób trzecich, że certyfikat podpisywania aplikacji jest wiarygodny wszędzie tam, gdzie są zaufane jego poprzednie wersje.
- starsze certyfikaty podpisywania aplikacji, którym aplikacja nadal ufa;
Atrybut proof-of-rotation w sekcji signed-data składa się z pojedynczo połączonej listy, w której każdy węzeł zawiera certyfikat podpisywania używany do podpisywania poprzednich wersji aplikacji. Ten atrybut ma zawierać struktury danych proof-of-rotation i self-trusted-old-certs. Lista jest uporządkowana według wersji, a najstarszy certyfikat podpisu odpowiada węzłowi głównemu. Struktura danych dowodu rotacji jest tworzona przez certyfikat w każdym węźle, który podpisuje następny na liście, a tym samym nadaje każdemu nowemu kluczowi dowody na to, że powinien być tak samo zaufany jak starsze klucze.
Struktura danych self-trusted-old-certs jest tworzona przez dodawanie do każdego węzła flag wskazujących na przynależność i właściwości w zbiorze. Może na przykład występować flaga wskazująca, że certyfikat podpisywania w danym węźle jest zaufany do uzyskiwania uprawnień do podpisywania w Androidzie. Ten parametr umożliwia innym aplikacjom podpisanym przez starszy certyfikat przyznanie uprawnienia do podpisywania zdefiniowanego przez aplikację podpisaną nowym certyfikatem podpisywania. Ponieważ cały atrybut proof-of-rotation znajduje się w sekcji podpisanych danych w polu v3signer
, jest chroniony przez klucz użyty do podpisania pliku APK.
Ten format wyklucza wiele kluczy podpisujących i zbliżanie się różnych certyfikatów podpisujących do jednego (wiele węzłów początkowych do wspólnego miejsca docelowego).
Format
Potwierdzenie rotacji jest przechowywane w bloku schematu podpisu APK w wersji 3 pod identyfikatorem 0x3ba06f8c
. Ma on format:
- sekwencja z przedrostkiem długości zawierająca
levels
z przedrostkiem długości:- z prefiksem długości
signed data
(z poprzedniego certyfikatu – jeśli istnieje)- X.509 z prefiksem długości
certificate
(format ASN.1 DER) signature algorithm ID
(uint32) – algorytm użyty przez certyfikat na poprzednim poziomie.
- X.509 z prefiksem długości
flags
(uint32) – flagi wskazujące, czy certyfikat powinien znajdować się w strukturze self-trusted-old-certs i w jakich operacjach.signature algorithm ID
(uint32) – musi być zgodny z danymi z sekcji danych podpisanych na następnym poziomie.- z prefiksem długości
signature
nadsigned data
- z prefiksem długości
Wiele certyfikatów
Nie obsługujemy wielu podpisujących, a Google Play nie publikuje aplikacji podpisanych wieloma certyfikatami.
Weryfikacja
W Androidzie 9 i nowszych pliki APK można weryfikować zgodnie ze schematem podpisu APK w wersji 3, 2 lub 1. Starsze platformy ignorują podpisy w wersji 3 i próbują zweryfikować podpisy w wersji 2, a potem w wersji 1.
Rysunek 1. Proces weryfikacji podpisu pliku APK
Weryfikacja schematu podpisu APK w wersji 3
- Odszukaj blok podpisywania pliku APK i sprawdź, czy:
- 2 pola rozmiaru w bloku podpisywania APK zawierają tę samą wartość.
- Po katalogu centralnym ZIP następuje rekord zakończenia katalogu centralnego ZIP.
- Po zakończeniu centralnego katalogu ZIP nie następuje więcej danych.
- Znajdź pierwszy blok schematu podpisu APK w wersji 3 w bloku podpisywania APK. Jeśli blokada v3 jest obecna, przejdź do kroku 3. W przeciwnym razie użyj schematu weryfikacji APK w wersji 2.
- W przypadku każdego
signer
w bloku schematu podpisu APK V3 z minimalną i maksymalną wersją pakietu SDK, która mieści się w zakresie bieżącej platformy:- Wybierz najsilniejszy obsługiwany
signature algorithm ID
zsignatures
. Kolejność siły zależy od wersji implementacji lub platformy. - Sprawdź odpowiadające
signature
zsignatures
wsigned data
za pomocą poleceniapublic key
. (Teraz można bezpiecznie przeanalizowaćsigned data
). - Sprawdź, czy minimalna i maksymalna wersja pakietu SDK w podpisanych danych są zgodne z tymi określonymi dla
signer
. - Sprawdź, czy uporządkowana lista identyfikatorów algorytmów podpisu w plikach
digests
isignatures
jest identyczna. (ma to zapobiec usuwaniu lub dodawaniu podpisu). - Oblicz digest zawartości pliku APK, używając tego samego algorytmu digest co algorytm digest użyty przez algorytm podpisu.
- Sprawdź, czy obliczony digest jest identyczny z odpowiadającym mu
digest
zdigests
. - Sprawdź, czy SubjectPublicKeyInfo pierwszego
certificate
wcertificates
jest identyczny zpublic key
. - Jeśli atrybut proof-of-rotation istnieje w przypadku
signer
, sprawdź, czy struktura jest ważna i czysigner
jest ostatnim certyfikatem na liście.
- Wybierz najsilniejszy obsługiwany
- Weryfikacja przebiega pomyślnie, jeśli w zakresie bieżącej platformy zostanie znaleziony dokładnie 1
signer
i jego weryfikacja na etapie 3 zakończy się powodzeniem.signer
Weryfikacja
Aby sprawdzić, czy Twoje urządzenie prawidłowo obsługuje wersję 3, uruchom PkgInstallSignatureVerificationTest.java
testy CTS w cts/hostsidetests/appsecurity/src/android/appsecurity/cts/
.