Android 9 obsługuje rotację kluczy APK , co daje aplikacjom możliwość zmiany klucza podpisywania w ramach aktualizacji APK. Aby rotacja była praktyczna, pliki APK muszą wskazywać poziomy zaufania między nowym i starym kluczem podpisywania. Aby obsługiwać rotację kluczy, zaktualizowaliśmy schemat podpisu APK z wersji 2 do wersji 3, aby umożliwić użycie nowych i starych kluczy. Wersja 3 dodaje informacje o obsługiwanych wersjach zestawu SDK i strukturze dowodu rotacji do bloku podpisywania pliku APK.
Blok podpisywania APK
Aby zachować kompatybilność wsteczną z formatem APK v1, podpisy APK v2 i v3 są przechowywane w bloku podpisu APK, znajdującym się bezpośrednio przed centralnym katalogiem ZIP.
Format bloku podpisywania pliku APK w wersji 3 jest taki sam jak w wersji 2 . Podpis v3 pakietu APK jest przechowywany jako para identyfikator-wartość o identyfikatorze 0xf05368c0.
Blok schematu podpisu APK v3
Schemat v3 został zaprojektowany tak, aby był 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.
Jednak schemat v3 dodaje informacje o obsługiwanych wersjach zestawu SDK i strukturze dowodu rotacji.
Format
Blok schematu podpisu APK v3 jest przechowywany w bloku podpisu APK pod identyfikatorem 0xf05368c0
.
Format bloku schematu podpisu APK v3 jest zgodny z formatem v2:
- sekwencja
signer
z przedrostkiem długości:-
signed data
z prefiksem długości:- sekwencja skrótów z
digests
długości:-
signature algorithm ID
(4 bajty) -
digest
(z przedrostkiem długości)
-
- sekwencja
certificates
X.509 z prefiksem długości:-
certificate
X.509 z prefiksem długości (formularz ASN.1 DER)
-
-
minSDK
(uint32) - ten podpisujący powinien zostać zignorowany, jeśli wersja platformy jest niższa od tego numeru. -
maxSDK
(uint32) - ten podpisujący powinien zostać zignorowany, jeśli wersja platformy jest powyżej tego numeru. - sekwencja
additional attributes
z przedrostkiem długości:-
ID
(uint32) -
value
(zmienna długość: długość dodatkowego atrybutu - 4 bajty) -
ID - 0x3ba06f8c
-
value -
struktura dowodu rotacji
-
- sekwencja skrótów z
-
minSDK
(uint32) - duplikat wartości minSDK w sekcji podpisanych danych - używany do pominięcia weryfikacji tego podpisu, jeśli bieżąca platforma nie jest w zasięgu. Musi odpowiadać podpisanej wartości danych. -
maxSDK
(uint32) - duplikat wartości maxSDK w sekcji podpisanych danych - używany do pominięcia weryfikacji tego podpisu, jeśli bieżąca platforma nie jest w zasięgu. Musi odpowiadać podpisanej wartości danych. - sekwencja
signatures
z przedrostkiem długości:-
signature algorithm ID
(uint32) -
signature
z przedrostkiem długości nadsigned data
-
-
public key
z prefiksem długości (SubjectPublicKeyInfo, formularz ASN.1 DER)
-
Struktury potwierdzające rotację i stare certyfikaty zaufania
Struktura dowodu rotacji umożliwia aplikacjom obracanie certyfikatów podpisu bez blokowania ich w innych aplikacjach, z którymi się komunikują. Aby to osiągnąć, podpisy aplikacji zawierają dwa nowe elementy danych:
- zapewnienie stronom trzecim, że certyfikatowi podpisywania aplikacji można ufać wszędzie tam, gdzie ufa się jego poprzednikom
- starsze certyfikaty podpisywania aplikacji, którym sama aplikacja nadal ufa
Atrybut dowodu rotacji w sekcji podpisanych danych składa się z listy z pojedynczym łączem, przy czym każdy węzeł zawiera certyfikat podpisywania używany do podpisywania poprzednich wersji aplikacji. Ten atrybut ma zawierać struktury danych koncepcyjnego dowodu rotacji i zaufanych starych certyfikatów. Lista jest uporządkowana według wersji z najstarszym certyfikatem podpisującym odpowiadającym węzłowi głównemu. Strukturę danych potwierdzającą rotację buduje się w ten sposób, że certyfikat w każdym węźle podpisuje następny na liście, a tym samym nasyca każdy nowy klucz dowodem, że powinien być tak samo godny zaufania jak starszy klucz(e).
Struktura danych typu self-trust-old-certs jest tworzona poprzez dodanie do każdego węzła flag wskazujących jego przynależność i właściwości do zbioru. Na przykład może być obecna flaga wskazująca, że certyfikat podpisywania w danym węźle jest zaufany w zakresie uzyskiwania uprawnień do podpisu Androida. Ta flaga pozwala innym aplikacjom podpisanym przy użyciu starszego certyfikatu nadal uzyskiwać uprawnienia do podpisywania zdefiniowane przez aplikację podpisaną przy użyciu nowego certyfikatu podpisywania. Ponieważ cały atrybut dowodu rotacji znajduje się w sekcji podpisanych danych pola signer
w wersji 3, jest on chroniony kluczem używanym do podpisania zawierającego go pliku APK.
Ten format wyklucza wiele kluczy podpisujących i zbieżność różnych certyfikatów podpisujących przodków w jeden (wiele węzłów początkowych do wspólnego ujścia).
Format
Dowód rotacji jest przechowywany w bloku APK Signature Scheme v3 pod identyfikatorem 0x3ba06f8c
. Jego format to:
- sekwencja
levels
z przedrostkiem długości:-
signed data
z prefiksem długości (według poprzedniego certyfikatu - jeśli istnieje)-
certificate
X.509 z prefiksem długości (formularz ASN.1 DER) -
signature algorithm ID
(uint32) - algorytm używany przez certyfikat na poprzednim poziomie
-
-
flags
(uint32) - flagi wskazujące, czy ten certyfikat powinien znajdować się w strukturze starych certyfikatów zaufania i dla jakich operacji. -
signature algorithm ID
(uint32) - musi być zgodny z tym z sekcji podpisanych danych na kolejnym poziomie. -
signature
z przedrostkiem długości nad powyższymisigned data
-
Wiele certyfikatów
Obecnie system Android traktuje plik APK podpisany wieloma certyfikatami jako posiadający unikalną tożsamość podpisu odrębną od składających się na niego certyfikatów. Zatem atrybut dowodu rotacji w sekcji podpisanych danych tworzy ukierunkowany graf acykliczny, który można lepiej postrzegać jako listę z pojedynczym łączem, w której każdy zestaw sygnatariuszy danej wersji reprezentuje jeden węzeł. Zwiększa to dodatkową złożoność struktury dowodu rotacji (wersja z wieloma podpisami poniżej). W szczególności problemem staje się zamawianie. Co więcej, nie jest już możliwe niezależne podpisywanie plików APK, ponieważ struktura dowodu rotacji musi uwzględniać stare certyfikaty podpisywania podpisujące nowy zestaw certyfikatów, a nie podpisywanie ich jeden po drugim. Na przykład plik APK podpisany kluczem A, który chce być podpisany dwoma nowymi kluczami B i C, nie może zawierać podpisu B po prostu podpisu A lub B, ponieważ jest to inna tożsamość podpisu niż B i C. To mogłoby oznacza, że sygnatariusze muszą skoordynować działania przed zbudowaniem takiej struktury.
Atrybut potwierdzający rotację wielu sygnatariuszy
- sekwencja
sets
z przedrostkiem długości :-
signed data
(według poprzedniego zestawu - jeśli istnieje)- sekwencja
certificates
z przedrostkiem długości-
certificate
X.509 z prefiksem długości (formularz ASN.1 DER)
-
- Kolejność
signature algorithm IDs
(uint32) - po jednym dla każdego certyfikatu z poprzedniego zestawu, w tej samej kolejności.
- sekwencja
-
flags
(uint32) - flagi wskazujące, czy ten zestaw certyfikatów powinien znajdować się w strukturze starych certyfikatów zaufania i dla jakich operacji. - sekwencja
signatures
z przedrostkiem długości:-
signature algorithm ID
(uint32) - musi być zgodny z tym z sekcji podpisanych danych -
signature
z przedrostkiem długości nad powyższymisigned data
-
-
Wielu przodków w strukturze dowodu rotacji
Schemat v3 również nie obsługuje dwóch różnych kluczy zmienianych na ten sam klucz podpisywania dla tej samej aplikacji. Różni się to od przypadku przejęcia, w którym firma przejmująca chciałaby przenieść nabytą aplikację, aby używać jej klucza podpisującego do udostępniania uprawnień. Przejęcie jest postrzegane jako obsługiwany przypadek użycia, ponieważ nowa aplikacja będzie wyróżniać się nazwą pakietu i może zawierać własną strukturę potwierdzającą rotację. Nieobsługiwany przypadek, w którym ta sama aplikacja ma dwie różne ścieżki dostępu do tego samego certyfikatu, łamie wiele założeń przyjętych w projekcie rotacji kluczy.
Weryfikacja
W systemie Android 9 i nowszych wersjach pliki APK można weryfikować zgodnie ze schematem podpisu APK v3, v2 lub v1. Starsze platformy ignorują podpisy v3 i próbują zweryfikować podpisy v2, a następnie v1.
Weryfikacja schematu podpisu APK v3
- Znajdź blok podpisywania pliku APK i sprawdź, czy:
- Dwa pola rozmiaru bloku podpisywania APK zawierają tę samą wartość.
- Bezpośrednio po ZIP Central Directory następuje rekord ZIP End of Central Directory.
- Po zakończeniu ZIP Central Directory nie następuje więcej danych.
- Znajdź pierwszy blok schematu podpisu APK v3 wewnątrz bloku podpisywania APK. Jeśli obecny jest blok v3, przejdź do kroku 3. W przeciwnym razie wróć do weryfikacji pliku APK przy użyciu schematu v2 .
- Dla każdego
signer
w bloku schematu podpisów APK v3 z minimalną i maksymalną wersją pakietu SDK mieszczącą się w zakresie bieżącej platformy:- Wybierz najsilniejszy obsługiwany
signature algorithm ID
zsignatures
. Kolejność mocy zależy od każdej wersji implementacji/platformy. - Zweryfikuj odpowiedni
signature
zsignatures
względemsigned data
przy użyciupublic key
. (Teraz można bezpiecznie analizowaćsigned data
.) - Sprawdź, czy minimalna i maksymalna wersja zestawu SDK w podpisanych danych jest zgodna z wersją określoną dla
signer
. - Sprawdź, czy uporządkowana lista identyfikatorów algorytmów podpisu w
digests
isignatures
jest identyczna. (Zapobiega to usuwaniu/dodawaniu podpisów.) - Oblicz skrót zawartości APK , używając tego samego algorytmu skrótu, co algorytm skrótu używany przez algorytm podpisu.
- Sprawdź, czy obliczone podsumowanie jest identyczne z odpowiadającym
digests
digest
- Sprawdź, czy SubjectPublicKeyInfo pierwszego
certificate
certificates
jest identyczny zpublic key
. - Jeśli dla
signer
istnieje atrybut dowodu rotacji, sprawdź, czy struktura jest prawidłowa i czy tensigner
jest ostatnim certyfikatem na liście.
- Wybierz najsilniejszy obsługiwany
- Weryfikacja przebiegła pomyślnie, jeśli w zasięgu bieżącej platformy został znaleziony dokładnie jeden
signer
i dla tegosigner
powiódł się krok 3.
Walidacja
Aby sprawdzić, czy Twoje urządzenie poprawnie obsługuje wersję 3, uruchom testy PkgInstallSignatureVerificationTest.java
CTS w cts/hostsidetests/appsecurity/src/android/appsecurity/cts/
.