Schemat podpisu APK w wersji 3

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)
      • 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
    • 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 nad signed 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.
    • 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 nad signed data

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.

Proces weryfikacji podpisu pliku APK

Rysunek 1. Proces weryfikacji podpisu pliku APK

Weryfikacja schematu podpisu APK w wersji 3

  1. Odszukaj blok podpisywania pliku APK i sprawdź, czy:
    1. 2 pola rozmiaru w bloku podpisywania APK zawierają tę samą wartość.
    2. Po katalogu centralnym ZIP następuje rekord zakończenia katalogu centralnego ZIP.
    3. Po zakończeniu centralnego katalogu ZIP nie następuje więcej danych.
  2. 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.
  3. 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:
    1. Wybierz najsilniejszy obsługiwany signature algorithm ID z signatures. Kolejność siły zależy od wersji implementacji lub platformy.
    2. Sprawdź odpowiadające signature z signatures w signed data za pomocą polecenia public key. (Teraz można bezpiecznie przeanalizować signed data).
    3. Sprawdź, czy minimalna i maksymalna wersja pakietu SDK w podpisanych danych są zgodne z tymi określonymi dla signer.
    4. Sprawdź, czy uporządkowana lista identyfikatorów algorytmów podpisu w plikach digestssignatures jest identyczna. (ma to zapobiec usuwaniu lub dodawaniu podpisu).
    5. Oblicz digest zawartości pliku APK, używając tego samego algorytmu digest co algorytm digest użyty przez algorytm podpisu.
    6. Sprawdź, czy obliczony digest jest identyczny z odpowiadającym mu digestdigests.
    7. Sprawdź, czy SubjectPublicKeyInfo pierwszego certificate w certificates jest identyczny z public key.
    8. Jeśli atrybut proof-of-rotation istnieje w przypadku signer, sprawdź, czy struktura jest ważna i czy signer jest ostatnim certyfikatem na liście.
  4. 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.javatesty CTS w cts/hostsidetests/appsecurity/src/android/appsecurity/cts/.