APK imza şeması v2

APK imza şeması v2, APK'nın korunan bölümlerindeki değişiklikleri tespit ederek doğrulama hızını artıran ve bütünlük garantilerini güçlendiren bir tüm dosya imza şemasıdır.

APK imza şeması v2 kullanılarak imzalama işlemi, ZIP Merkezi Dizin bölümünden hemen önce APK dosyasına bir APK imzalama bloğu ekler. APK imzalama bloğunda, v2 imzaları ve imzalayan kimlik bilgileri APK imza şeması v2 bloğunda saklanır.

İmzalanmadan önce ve sonra APK

Şekil 1. APK imzalamadan önce ve imzaladıktan sonra

APK imza şeması v2, Android 7.0'da (Nougat) kullanıma sunulmuştur. Bir APK'nın Android 6.0 (Marshmallow) ve daha eski cihazlarda yüklenebilmesi için v2 şemasıyla imzalanmadan önce JAR imzalama kullanılarak imzalanması gerekir.

APK imzalama bloğu

V1 APK biçimiyle geriye dönük uyumluluğu korumak için v2 ve sonraki APK imzaları, APK imza şeması v2'yi desteklemek amacıyla kullanıma sunulan yeni bir kapsayıcı olan APK imzalama bloğunda saklanır. APK dosyasında APK imzalama bloğu, dosyanın sonunda bulunan ZIP Merkezi Dizin'den hemen önce yer alır.

Blok, APK'da bloğun bulunmasını kolaylaştıracak şekilde sarmalanmış kimlik-değer çiftleri içerir. APK'nın v2 imzası, 0x7109871a kimliğine sahip bir kimlik-değer çifti olarak saklanır.

Biçim

APK imzalama bloğunun biçimi aşağıdaki gibidir (tüm sayısal alanlar "litle-endian"dır):

  • Bayt cinsinden size of block (bu alan hariç) (uint64)
  • uint64 uzunluğunda ön ek eklenmiş kimlik-değer çiftleri dizisi:
    • ID (uint32)
    • value (değişken uzunluk: çiftin uzunluğu - 4 bayt)
  • Bayt cinsinden size of block (ilk alanla (uint64) aynı)
  • magic "APK Sig Block 42" (16 bayt)

APK, önce ZIP Merkezi Dizin'in başlangıcı bulunarak (dosyanın sonunda ZIP Merkezi Dizin Sonu kaydını bulup Merkez Dizin'in başlangıç ofsetini kayıttan okuyarak) ayrıştırılır. magic değeri, Central Directory'den önceki bölümün APK imzalama bloğu olabileceğinin belirlenmesi için hızlı bir yol sağlar. Böylece size of block değeri, etkili bir şekilde dosyadaki bloğun başlangıcına işaret eder.

Bilinmeyen kimliklere sahip kimlik-değer çiftleri, blok yorumlanırken yoksayılmalıdır.

APK imza şeması v2 bloğu

APK, her biri bir imzalama anahtarıyla temsil edilen bir veya daha fazla imzalayan/kimlik tarafından imzalanır. Bu bilgiler, APK imza şeması v2 bloğu olarak depolanır. Her imzalayan için aşağıdaki bilgiler saklanır:

  • (imza algoritması, özet, imza) delegeleri hakkında daha fazla bilgi edinin. Özet, imza doğrulamasını APK'nın içeriğinin bütünlük kontrolünden ayırmak için depolanır.
  • İmzalayanın kimliğini temsil eden X.509 sertifika zinciri.
  • Anahtar/değer çiftleri olarak ek özellikler.

Her imzalayan için APK, sağlanan listedeki desteklenen bir imza kullanılarak doğrulanır. Bilinmeyen imza algoritmalarına sahip imzalar yoksayılır. Birden çok desteklenen imzayla karşılaşıldığında hangi imzanın kullanılacağını seçmek her uygulamaya bağlıdır. Bu sayede, gelecekte daha güçlü imzalama yöntemleri geriye dönük uyumlu bir şekilde kullanıma sunulabilir. Önerilen yaklaşım, en güçlü imzayı doğrulamaktır.

Biçim

APK imza şeması v2 bloğu, APK imzalama bloğunun içinde 0x7109871a kimliği altında depolanır.

APK imza şeması v2 bloğunun biçimi aşağıdaki gibidir (tüm sayısal değerler "küçük-endian"dır, tüm uzunluk önekli alanlarda uzunluk için uint32 kullanılır):

  • Uzunluk ön ekiyle başlayan signer'nin uzunluk ön ekiyle başlayan dizisi:
    • uzunluk ön ekiyle signed data:
      • Uzunluk ön ekiyle başlayan digests'nin uzunluk ön ekiyle başlayan dizisi:
      • X.509 certificates uzunluğuna öncelikli sıra:
        • uzunluk ön ekiyle X.509 certificate (ASN.1 DER formu)
      • Uzunluk ön ekiyle başlayan additional attributes'nin uzunluk ön ekiyle başlayan dizisi:
        • ID (uint32)
        • value (değişken uzunluk: ek özelliğin uzunluğu - 4 bayt)
    • Uzunluk ön ekiyle başlayan signatures'nin uzunluk ön ekiyle başlayan dizisi:
      • signature algorithm ID (uint32)
      • length-prefixed signature over signed data
    • uzunluk öneki public key (SubjectPublicKeyInfo, ASN.1 DER formu)

İmza algoritması kimlikleri

  • 0x0101: SHA2-256 özetiyle RSASSA-PSS, SHA2-256 MGF1, 32 bayt tuz, son ek: 0xbc
  • 0x0102: SHA2-512 özetiyle RSASSA-PSS, SHA2-512 MGF1, 64 bayt tuz, ek: 0xbc
  • 0x0103: SHA2-256 özeti ile RSASSA-PKCS1-v1_5. Bu, kesin imzalar gerektiren derleme sistemleri içindir.
  • 0x0104: SHA2-512 özetiyle RSASSA-PKCS1-v1_5. Bu, kesin imzalar gerektiren derleme sistemleri içindir.
  • 0x0201: SHA2-256 özetine sahip ECDSA
  • 0x0202: SHA2-512 özetiyle ECDSA
  • 0x0301: SHA2-256 özetiyle DSA

Yukarıdaki imza algoritmalarının tümü Android platformu tarafından desteklenir. İmzalama araçları, algoritmaların bir alt kümesini destekleyebilir.

Desteklenen anahtar boyutları ve EC eğrileri:

  • RSA: 1024, 2048, 4096, 8192, 16384
  • EC: NIST P-256, P-384, P-521
  • DSA: 1024, 2048, 3072

Bütünlük korumalı içerikler

APK'lar, içeriklerini korumak için dört bölümden oluşur:

  1. ZIP girişlerinin içeriği (0 ofsetinden APK imzalama bloğunun başına kadar)
  2. APK imzalama bloğu
  3. ZIP Merkezi Dizini
  4. ZIP Merkezi Dizin Sonu

İmzalanmış APK bölümleri

Şekil 2. İmzalanmış APK bölümleri

APK imza şeması v2, bölüm 1, 3, 4 ve bölüm 2'de yer alan APK imza şeması v2 bloğunun signed data bloklarının bütünlüğünü korur.

1, 3 ve 4. bölümlerin bütünlüğü, signed data bloklarında depolanan içeriklerinin bir veya daha fazla özeti ile korunur. Bu özetler sırayla bir veya daha fazla imzayla korunur.

1, 3 ve 4 numaralı bölümlerin özeti, iki düzeyli bir Merkle ağacına benzer şekilde aşağıdaki gibi hesaplanır. Her bölüm, art arda gelen 1 MB'lık (220 bayt) parçalara ayrılır. Her bölümdeki son parça daha kısa olabilir. Her bir parçanın özeti, 0xa5 baytının birleştirilmesi, parçanın bayt cinsinden uzunluğu (litle-endian uint32) ve parça içeriği üzerinden hesaplanır. Üst düzey özet, 0x5a baytının, parça sayısının (az bayttan büyük uint32) ve parçaların APK'da göründüğü sırayla parçaların özetlerinin birleştirilmesi üzerinden hesaplanır. Özet, paralelleştirerek hesaplamayı hızlandırmak için parçalara ayrılmış şekilde hesaplanır.

APK özeti

Şekil 3. APK özeti

4. bölümün (ZIP Merkezi Dizininin Sonu) korunması, ZIP Merkezi Dizininin ofsetini içeren bölüm nedeniyle karmaşıktır. Zaman farkı, APK imzalama bloğunun boyutu değiştiğinde (örneğin, yeni bir imza eklendiğinde) değişir. Bu nedenle, Merkezi Dizin'in ZIP Sonu üzerinden yapılan hesaplamada ZIP Merkezi Dizini'nin ofsetini içeren alan, APK imzalama bloğunun ofsetini içeriyor olarak değerlendirilmelidir.

Geri alma korumaları

Bir saldırgan, v2 imzalı APK'nın doğrulanmasını destekleyen Android platformlarında v2 imzalı APK'yı v1 imzalı APK olarak doğrulamaya çalışabilir. Bu saldırıyı azaltmak için, v1 ile de imzalanmış olan v2 ile imzalanmış APK'lar, META-INF/*.SF dosyalarının ana bölümünde bir X-Android-APK-Signed özelliği içermelidir. Özelliğin değeri, virgülle ayrılmış bir APK imza şeması kimliği grubudur (bu şemanın kimliği 2'dir). APK doğrulayıcının, v1 imzasını doğrularken bu gruptaki doğrulayıcının tercih ettiği APK imza şeması (ör. v2 şeması) için imzası olmayan APK'ları reddetmesi gerekir. Bu koruma, META-INF/*.SF dosyalarının içeriklerinin v1 imzalarıyla korunmasına dayanır. JAR imzalı APK doğrulaması bölümüne bakın.

Saldırganlar, APK İmza Şeması v2 bloğundan daha güçlü imzaları kaldırmayı deneyebilir. Bu saldırıyı hafifletmek için APK'nın imzalandığı imza algoritması kimliklerinin listesi, her imza tarafından korunan signed data bloğunda saklanır.

Doğrulama

Android 7.0 ve sonraki sürümlerde APK'lar, APK imza şeması v2+ veya JAR imzalamasına (v1 şeması) göre doğrulanabilir. Eski platformlar v2 imzalarını yoksayar ve yalnızca v1 imzalarını doğrular.

APK imza doğrulama süreci

Şekil 4. APK imza doğrulama süreci (yeni adımlar kırmızıyla gösterilmiştir)

APK imza şeması v2 doğrulaması

  1. APK imzalama bloğunu bulun ve şunları doğrulayın:
    1. APK imzalama bloğunun iki boyut alanı aynı değeri içeriyor.
    2. ZIP Merkezi Dizin'in hemen ardından ZIP Merkezi Dizin Sonu kaydı gelir.
    3. ZIP End of Central Directory'den sonra daha fazla veri gelmez.
  2. APK imzalama bloğunun içindeki ilk APK imza şeması v2 bloğunu bulun. v2 bloğu varsa 3. adıma geçin. Aksi takdirde, APK'yı v1 şemasını kullanarak doğrulamaya geçin.
  3. APK imza şeması v2 bloğundaki her signer için:
    1. signatures arasından en güçlü desteklenen signature algorithm ID'yi seçin. Güç sıralaması her uygulamaya/platform sürümüne bağlıdır.
    2. public key kullanarak signatures'daki ilgili signature'yi signed data ile karşılaştırın. (signed data artık ayrıştırılabilir.)
    3. digests ve signatures'daki imza algoritması kimliklerinin sıralı listesinin aynı olduğundan emin olun. (Bu, imzanın kaldırılmasını/eklenmesini önlemek içindir.)
    4. İmza algoritması tarafından kullanılan özet algoritmasıyla aynı özet algoritmasını kullanarak APK içeriğinin özetini hesaplayın.
    5. Hesaplanan özetin, digests alanındaki karşılık gelen digest ile aynı olduğunu doğrulayın.
    6. certificates'un ilk certificate öğesinin SubjectPublicKeyInfo değerinin public key ile aynı olduğunu doğrulayın.
  4. En az bir signer bulunursa ve bulunan her signer için 3. adım başarılı olursa doğrulama başarılı olur.

Not: 3. veya 4. adımda hata oluşursa APK, v1 şeması kullanılarak doğrulanmamalıdır.

JAR imzalı APK doğrulaması (v1 şeması)

JAR imzalı APK, META-INF/MANIFEST.MF'de listelenen girişleri tam olarak içermesi ve tüm girişlerin aynı imzalar tarafından imzalanması gereken bir standart imzalı JAR dosyasıdır. Bütünlüğü aşağıdaki şekilde doğrulanır:

  1. Her imzalayan, META-INF/<signer>.SF ve META-INF/<signer>.(RSA|DSA|EC) JAR girişiyle temsil edilir.
  2. <signer>.(RSA|DSA|EC), imzasının <signer>.SF dosyası üzerinden doğrulandığı SignedData yapısına sahip bir PKCS #7 İçerik Yönetim Sistemi ContentInfo dosyasıdır.
  3. <signer>.SF dosyası, META-INF/MANIFEST.MF dosyasının tamamını ve META-INF/MANIFEST.MF dosyasının her bölümünün özetini içerir. MANIFEST.MF dosyasının tam dosya özeti doğrulandı. Bu işlem başarısız olursa bunun yerine her MANIFEST.MF bölümünün özeti doğrulanır.
  4. META-INF/MANIFEST.MF, bütünlük korumalı her JAR girişi için girişin sıkıştırılmamış içeriğinin özetini içeren, uygun şekilde adlandırılmış bir bölüm içerir. Bu özetlerin tümü doğrulanır.
  5. APK, MANIFEST.MF'de listelenmeyen ve JAR imzasının parçası olmayan JAR girişleri içeriyorsa APK doğrulaması başarısız olur.

Dolayısıyla, koruma zinciri, bütünlük korumalı her JAR girişinin içeriğidir. (<signer>.(RSA|DSA|EC) -> <signer>.SF -> MANIFEST.MF ->).