APK Signature Scheme v2, APK'nın korunan bölümlerindeki değişiklikleri algılayarak doğrulama hızını artıran ve bütünlük garantilerini güçlendiren tam dosya imza şemasıdır.
APK Signature Scheme v2 kullanarak imzalamak, APK dosyasına ZIP Central Directory bölümünden hemen önce bir APK İmzalama Bloğu ekler. APK İmzalama Bloğu içinde, v2 imzaları ve imzalayan kimlik bilgileri bir APK İmza Şeması v2 Bloğunda depolanır.
Şekil 1. APK imzalamadan önce ve sonra
APK Signature Scheme v2, Android 7.0'da (Nougat) kullanıma sunuldu. Bir APK'yı Android 6.0 (Marshmallow) ve daha eski cihazlara yüklenebilir hale getirmek için APK, v2 şemasıyla imzalanmadan önce JAR imzası kullanılarak imzalanmalıdır.
APK İmzalama Bloğu
v1 APK biçimiyle geriye dönük uyumluluğu korumak için v2 ve daha yeni APK imzaları, APK Signature Scheme v2'yi desteklemek üzere tanıtılan yeni bir kapsayıcı olan APK İmzalama Bloğu içinde depolanır. Bir APK dosyasında, APK İmza Bloğu, dosyanın sonunda bulunan ZIP Merkez Dizininin hemen önünde bulunur.
Blok, APK'da bloğu bulmayı kolaylaştıracak şekilde sarılmış kimlik değeri çiftleri içerir. APK'nın v2 imzası, ID 0x7109871a ile bir ID-değer çifti olarak saklanır.
Biçim
APK İmza Bloğunun formatı aşağıdaki gibidir (tüm sayısal alanlar küçük endian'dır):
- bayt cinsinden
size of block
(bu alan hariç) (uint64) - uint64-uzunluk-ön ekli ID-değer çiftlerinin sırası:
-
ID
(uint32) -
value
(değişken uzunluk: çiftin uzunluğu - 4 bayt)
-
- bayt cinsinden
size of block
—ilk alanla aynı (uint64) -
magic
“APK Sig Block 42” (16 bayt)
APK, önce ZIP Merkez Dizininin başlangıcını bularak (dosyanın sonundaki Merkez Dizinin ZIP Sonu kaydını bularak, ardından Kayıttan Merkezi Dizinin başlangıç uzaklığını okuyarak) ayrıştırılır. magic
değer, Central Directory'den önce gelenin büyük olasılıkla APK İmzalama Bloğu olduğunu belirlemenin hızlı bir yolunu sağlar. size of block
daha sonra etkin bir şekilde dosyadaki bloğun başlangıcına işaret eder.
Blok yorumlanırken bilinmeyen ID'lere sahip ID-değer çiftleri göz ardı edilmelidir.
APK İmza Ş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 bir APK Signature Scheme v2 Block olarak saklanır. Her imzalayan için aşağıdaki bilgiler saklanır:
- (imza algoritması, özet, imza) demetleri. Özet, APK içeriğinin bütünlük kontrolünden imza doğrulamasını ayırmak için saklanı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 listeden desteklenen bir imza kullanılarak doğrulanır. Bilinmeyen imza algoritmalarına sahip imzalar yoksayılır. Desteklenen birden çok imzayla karşılaşıldığında hangi imzanın kullanılacağını seçmek her uygulamaya bağlıdır. Bu, gelecekte geriye dönük uyumlu bir şekilde daha güçlü imzalama yöntemlerinin sunulmasını sağlar. Önerilen yaklaşım, en güçlü imzayı doğrulamaktır.
Biçim
APK Signature Scheme v2 Block, APK İmzalama Bloğu içinde 0x7109871a
kimliği altında depolanır.
APK Signature Scheme v2 Block'un formatı aşağıdaki gibidir (tüm sayısal değerler küçük endiandır, tüm uzunluk önekli alanlar uzunluk için uint32 kullanır):
- uzunluk önekli
signer
uzunluk öneki dizisi:- uzunluk ön ekli
signed data
:- uzunluk ön ekli
digests
uzunluk ön ekli dizisi :-
signature algorithm ID
(uint32) - (uzunluk ön ekli)
digest
— bkz. Bütünlük Korumalı İçindekiler
-
- X.509
certificates
uzunluk ön ekli dizisi :- uzunluk ön ekli X.509
certificate
(ASN.1 DER formu)
- uzunluk ön ekli X.509
- uzunluk önekli
additional attributes
dizisi:-
ID
(uint32) -
value
(değişken uzunluk: ek özelliğin uzunluğu - 4 bayt)
-
- uzunluk ön ekli
- uzunluk önekli
signatures
uzunluk öneki dizisi:-
signature algorithm ID
(uint32) -
signed data
üzerinde uzunluk ön eklisignature
-
- uzunluk önekli
public key
(SubjectPublicKeyInfo, ASN.1 DER formu)
- uzunluk ön ekli
İmza Algoritması Kimlikleri
- 0x0101—SHA2-256 özetli RSASSA-PSS, SHA2-256 MGF1, 32 bayt tuz, fragman: 0xbc
- 0x0102—RSASSA-PSS, SHA2-512 özet, SHA2-512 MGF1, 64 bayt tuz, fragman: 0xbc
- 0x0103—RSASSA-PKCS1-v1_5, SHA2-256 özeti ile. Bu, deterministik imzalar gerektiren yapı sistemleri içindir.
- 0x0104—RSASSA-PKCS1-v1_5, SHA2-512 özeti ile. Bu, deterministik imzalar gerektiren yapı sistemleri içindir.
- 0x0201—SHA2-256 özetli ECDSA
- 0x0202—SHA2-512 özetli ECDSA
- 0x0301—SHA2-256 özetli DSA
Yukarıdaki imza algoritmalarının tümü Android platformu tarafından desteklenmektedir. İmzalama araçları, algoritmaların bir alt kümesini destekleyebilir.
Desteklenen tuş 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 içeriğini korumak amacıyla bir APK dört bölümden oluşur:
- ZIP girişlerinin içeriği (0 ofsetinden APK İmza Bloğunun başlangıcına kadar)
- APK İmzalama Bloğu
- ZIP Merkez Dizini
- Merkez Dizinin ZIP Sonu
Şekil 2. İmzalandıktan sonra APK bölümleri
APK Signature Scheme v2, bölüm 1, 3, 4'ün bütünlüğünü ve bölüm 2'de bulunan APK Signature Scheme v2 Block'un signed data
bloklarını korur.
Bölüm 1, 3 ve 4'ün bütünlüğü, bir veya daha fazla imza ile korunan signed data
bloklarında saklanan içeriklerinin bir veya daha fazla özeti ile korunur.
1, 3 ve 4 bölümleri üzerindeki özet, iki seviyeli Merkle ağacına benzer şekilde aşağıdaki gibi hesaplanır. Her bölüm ardışık 1 MB (2 20 bayt) parçalara bölünür. Her bölümdeki son parça daha kısa olabilir. Her yığının özeti, bayt 0xa5
, yığının bayt cinsinden uzunluğu (little-endian uint32) ve yığının içeriği üzerinden hesaplanır. Üst düzey özet, bayt 0x5a
birleştirilmesi, parçaların sayısı (little-endian uint32) ve parçaların APK'da göründüğü sırayla parçaların özetlerinin birleştirilmesi üzerinden hesaplanır. Özet, paralel hale getirerek hesaplamayı hızlandırmak için yığın şeklinde hesaplanır.
Şekil 3. APK özeti
4. bölümün (Merkezi Dizinin ZIP Sonu) korunması, ZIP Merkez Dizininin ofsetini içeren bölüm nedeniyle karmaşıktır. APK İmza Bloğunun boyutu değiştiğinde, örneğin yeni bir imza eklendiğinde, ofset değişir. Bu nedenle, Merkez Dizinin ZIP Sonu üzerinden özet hesaplanırken, ZIP Merkez Dizininin ofsetini içeren alan, APK İmzalama Bloğunun ofsetini içeriyor olarak ele alınmalıdır.
Geri Alma Korumaları
Saldırgan, v2 imzalı APK'nın doğrulanmasını destekleyen Android platformlarında v2 imzalı bir APK'nın v1 imzalı APK olarak doğrulanmasını deneyebilir. Bu saldırıyı azaltmak için v1 imzalı olan v2 imzalı APK'lar, META-INF/*.SF dosyalarının ana bölümünde bir X-Android-APK-Signed özniteliği içermelidir. Özniteliğin değeri, virgülle ayrılmış bir dizi APK imza şeması kimliğidir (bu şemanın kimliği 2'dir). v1 imzasını doğrularken, doğrulayıcının bu kümeden tercih ettiği APK imza şeması için imzası olmayan APK'ları reddetmek için APK doğrulayıcı gerekir (ör. v2 şeması). Bu koruma, META-INF/*.SF dosyalarının içeriğinin v1 imzalarıyla korunması gerçeğine dayanır. JAR imzalı APK doğrulaması ile ilgili bölüme bakın.
Saldırgan, APK Signature Scheme v2 Block'tan daha güçlü imzaları kaldırmaya çalışabilir. Bu saldırıyı azaltmak için APK'nın imzalandığı imza algoritması kimliklerinin listesi, her bir imza tarafından korunan signed data
bloğunda saklanır.
Doğrulama
Android 7.0 ve sonraki sürümlerde APK'lar, APK Signature Scheme v2+ veya JAR imzalamaya (v1 şeması) göre doğrulanabilir. Daha eski platformlar v2 imzalarını yok sayar ve yalnızca v1 imzalarını doğrular.
Şekil 4. APK imza doğrulama süreci (kırmızı ile yeni adımlar)
APK İmza Şeması v2 doğrulaması
- APK İmzalama Bloğu'nu bulun ve şunları doğrulayın:
- APK Signing Block'un iki boyut alanı aynı değeri içerir.
- ZIP Central Directory'nin hemen ardından ZIP End of Central Directory kaydı gelir.
- ZIP End of Central Directory daha fazla veri tarafından takip edilmez.
- APK İmzalama Bloğu içindeki ilk APK İmza Şeması v2 Bloğu'nu bulun. v2 Bloğu varsa, 3. adıma geçin. Aksi takdirde, v1 şemasını kullanarak APK'yı doğrulamaya geri dönün.
- APK İmza Planı v2 Bloğundaki her
signer
için:- İmzalardan desteklenen en güçlü
signatures
signature algorithm ID
seçin. Güç sıralaması her uygulama/platform versiyonuna bağlıdır. -
public key
kullanaraksigned data
karşısignatures
karşılık gelensignature
doğrulayın. (signed data
ayrıştırmak artık güvenlidir.) -
digests
vesignatures
sıralı imza algoritması kimlikleri listesinin aynı olduğunu doğrulayın. (Bu, imzanın çıkarı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
karşılık gelendigest
aynı olduğunu doğrulayın. - İlk
certificate
certificates
public key
aynı olduğunu doğrulayın.
- İmzalardan desteklenen en güçlü
- En az bir
signer
bulunursa ve bulunan hersigner
için 3. adım başarılıysa doğrulama başarılı olur.
Not : 3. veya 4. adımda bir hata oluşursa APK v1 şeması kullanılarak doğrulanmamalıdır.
JAR imzalı APK doğrulaması (v1 şeması)
JAR imzalı APK, tam olarak META-INF/MANIFEST.MF içinde listelenen girişleri içermesi ve tüm girişlerin aynı imzalayanlar tarafından imzalanması gereken standart imzalı bir JAR'dır. Bütünlüğü şu şekilde doğrulanır:
- Her imzalayan bir META-INF/<signer>.SF ve META-INF/<signer>.(RSA|DSA|EC) JAR girişi ile temsil edilir.
- <signer>.(RSA|DSA|EC), imzası <signer>.SF dosyası üzerinden doğrulanan SignedData yapısına sahip bir PKCS #7 CMS ContentInfo'dur.
- <signer>.SF dosyası, META-INF/MANIFEST.MF'nin tam dosya özetini ve META-INF/MANIFEST.MF'nin her bölümünün özetini içerir. MANIFEST.MF'nin tam dosya özeti doğrulanır. Bu 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. Tüm bu özetler 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.
Bu nedenle koruma zinciri, bütünlük korumalı her JAR girişinin <signer>.(RSA|DSA|EC) -> <signer>.SF -> MANIFEST.MF -> içeriğidir.