APK imza şeması v4

Android 11, APK imza şeması v4 ile akış uyumlu bir imza şemasını destekler. v4 imzası, APK'nın tüm baytları üzerinde hesaplanan Merkle karma ağacına dayanır. Şema, fs-verity karma ağacının yapısını tam olarak takip eder (örneğin, tuzun sıfırla doldurulması ve son bloğun sıfırla doldurulması). Android 11, imzayı ayrı bir dosyada (<apk name>.apk.idsig) saklar. v4 imzası için tamamlayıcı bir v2 veya v3 imzası gerekir.

Dosya biçimi

Tüm sayısal alanlar little endian biçimindedir. Tüm alanlar, sizeof() ile aynı sayıda bayt kullanır. Dolaylı dolgu veya hizalama eklenmez.

Aşağıdaki yardımcı yapı, tanımları basitleştirir:

template <class SizeT>
struct sized_bytes {
        SizeT size;
        byte bytes[size];
};

Ana dosya içeriği:

struct V4Signature {
        int32 version; // only version 2 is supported as of now
        sized_bytes<int32> hashing_info;
        sized_bytes<int32> signing_info;
        sized_bytes<int32> merkle_tree;  // optional
};

hashing_info, karma ağacı oluşturma ve kök karma için kullanılan parametredir: oluşturma ve kök karma için kullanılan parametredir:

struct hashing_info.bytes {
    int32 hash_algorithm;    // only 1 == SHA256 supported
    int8 log2_blocksize;     // only 12 (block size 4096) supported now
    sized_bytes<int32> salt; // used exactly as in fs-verity, 32 bytes max
    sized_bytes<int32> raw_root_hash; // salted digest of the first Merkle tree page
};

signing_info aşağıdaki yapıdadır:

struct signing_info.bytes {
    sized_bytes<int32> apk_digest; // used to match with the corresponding APK
    sized_bytes<int32> x509_certificate; // ASN.1 DER form
    sized_bytes<int32> additional_data; // a free-form binary data blob
    sized_bytes<int32> public_key; // ASN.1 DER, must match the x509_certificate
    int32 signature_algorithm_id; // see the APK v2 doc for the list
    sized_bytes<int32> signature;
};

apk_digest, APK'nın v3 imza bloğundan alınır. Bu blok yoksa v2 bloğundan alınır (apk_digest'e bakın).

Oluşturma ve doğrulama için signature kodu, aşağıdaki verileri ikili blob'a seri hale getirmeli ve imzalı veri olarak imzalama ve doğrulama algoritmasına iletmelidir:

struct V4DataForSigning {
        int32 size;
        int64 file_size; // the size of the file that's been hashed.
        hashing_info.hash_algorithm;
        hashing_info.log2_blocksize;
        hashing_info.salt;
        hashing_info.raw_root_hash;
        signing_info.apk_digest;
        signing_info.x509_certificate;
        signing_info.additional_data;
};

merkle_tree, fs-verity dokümanında açıklandığı şekilde hesaplanan APK'nın tamamı olan Merkle ağacıdır.

Üreticiler ve tüketiciler

apksigner Android SDK aracı, varsayılan parametrelerle çalıştırırsanız v4 imza dosyasını oluşturur. v4 imzalama özelliğini diğer imzalama şemalarıyla aynı şekilde devre dışı bırakabilirsiniz. Bu araç, v4 imzasının geçerli olup olmadığını da doğrulayabilir.

adb, adb install --incremental komutu çalıştırılırken .apk.idsig dosyasının APK'nın yanında olmasını bekler. adb, varsayılan olarak artımlı yüklemeyi denemek için IDSIG dosyasını da kullanır ve dosya eksik veya geçersizse normal yüklemeye geri döner.

Bir yükleme oturumu oluşturulduğunda, oturuma dosya eklenirken yeni akışla yükleme API'si PackageInstaller, kırpılmış v4 imzasını ayrı bir bağımsız değişken olarak kabul eder. Bu noktada, signing_info, IncFS'ye bütün bir blob olarak aktarılır. IncFS, blob'dan kök karmayı çıkarır.

Yükleme oturumu kaydedilirken PackageManagerService, IncFS'den signing_info blob'unu almak için ioctl çağrısı yapar, ayrıştırır ve imzayı doğrular.

Artımlı Veri Yükleyici bileşeni, imzanın Merkle ağacı bölümünü veri yükleyici yerel API'si üzerinden yayınlar. package service shell komutu install-incremental, her eklenen dosya için parametre olarak Base64 kodlamalı, temizlenmiş v4 imza dosyasını kabul eder. İlgili Merkle ağacının komutun stdin bölümüne gönderilmesi gerekir.

apk_digest

apk_digest, sıraya göre mevcut olan ilk içerik özetidir:

  1. V3, 1 MB blok, SHA2-512 (CONTENT_DIGEST_CHUNKED_SHA512)
  2. V3, 4 KB blok, SHA2-256 (CONTENT_DIGEST_VERITY_CHUNKED_SHA256)
  3. V3, 1 MB blok, SHA2-256 (CONTENT_DIGEST_CHUNKED_SHA256)
  4. V2, SHA2-512
  5. V2, SHA2-256

APK imzası şeması v3'teki length-prefixed sequence of length-prefixed signer (uzunluk önekli imzalayanın uzunluk önekli dizisi) bölümüne bakın.

Doğrulama ve test

APK doğrulama işlemi v4 aşağıdaki şekilde gösterilmiştir:

APK doğrulama süreci v4

Şekil 1. APK doğrulama süreci v4.

Özellik birimi testlerini ve CTS'yi kullanarak uygulamayı doğrulayın:

  • CtsIncrementalInstallHostTestCases
  • /android/cts/hostsidetests/incrementalinstall

İmza biçimini test etme

İmza biçimini test etmek için bir derleme ortamı oluşturun ve aşağıdaki manuel testleri çalıştırın:

$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest

İmza biçimini Android SDK (ADB ve apksigner) ile test etme

İmza biçimini Android SDK ile test etmek için şu süreci kullanın:

  1. Derleme ortamı oluşturun ve IncFS'nin uygulanmasını tamamladığınızdan emin olun.
  2. Derlemeyi hedef fiziksel cihaza veya emülatöre yükleyin.
  3. APK oluşturun veya mevcut bir APK'yı edinin, ardından hata ayıklama imzalama anahtarı oluşturun.
  4. APK'yı build-tools klasöründen v4 imza biçimiyle imzalayıp yükleyin.

    İmza
    $ ./apksigner sign --ks debug.keystore game.apk

    Yükle
    $ ./adb install game.apk

    Bu testleri nerede bulabilirsiniz?
    /android/cts/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java