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.
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:signature algorithm ID
(uint32)- (uzunluk ön eklidir)
digest
: Bütünlüğü Korunan İçerik bölümüne bakın
- X.509
certificates
uzunluğuna öncelikli sıra:- uzunluk ön ekiyle X.509
certificate
(ASN.1 DER formu)
- uzunluk ön ekiyle X.509
- 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
- Uzunluk ön ekiyle başlayan
signatures
'nin uzunluk ön ekiyle başlayan dizisi:signature algorithm ID
(uint32)- length-prefixed
signature
oversigned data
- uzunluk öneki
public key
(SubjectPublicKeyInfo, ASN.1 DER formu)
- uzunluk ön ekiyle
İ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:
- ZIP girişlerinin içeriği (0 ofsetinden APK imzalama bloğunun başına kadar)
- APK imzalama bloğu
- ZIP Merkezi Dizini
- ZIP Merkezi Dizin Sonu
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.
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 şeması v2 doğrulaması
- APK imzalama bloğunu bulun ve şunları doğrulayın:
- APK imzalama bloğunun iki boyut alanı aynı değeri içeriyor.
- ZIP Merkezi Dizin'in hemen ardından ZIP Merkezi Dizin Sonu kaydı gelir.
- ZIP End of Central Directory'den sonra daha fazla veri gelmez.
- 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.
- APK imza şeması v2 bloğundaki her
signer
için:signatures
arasından en güçlü desteklenensignature algorithm ID
'yi seçin. Güç sıralaması her uygulamaya/platform sürümüne bağlıdır.public key
kullanaraksignatures
'daki ilgilisignature
'yisigned data
ile karşılaştırın. (signed data
artık ayrıştırılabilir.)digests
vesignatures
'daki imza algoritması kimliklerinin sıralı listesinin aynı olduğundan emin olun. (Bu, imzanın kaldırılmasını/eklenmesini önlemek içindir.)- İmza algoritması tarafından kullanılan özet algoritmasıyla aynı özet algoritmasını kullanarak APK içeriğinin özetini hesaplayın.
- Hesaplanan özetin,
digests
alanındaki karşılık gelendigest
ile aynı olduğunu doğrulayın. certificates
'un ilkcertificate
öğesinin SubjectPublicKeyInfo değerininpublic key
ile aynı olduğunu doğrulayın.
- En az bir
signer
bulunursa ve bulunan hersigner
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:
- Her imzalayan, META-INF/<signer>.SF ve META-INF/<signer>.(RSA|DSA|EC) JAR girişiyle temsil edilir.
- <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.
- <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.
- 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.
- 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 ->).