APK Signature Scheme v2 adalah skema tanda tangan seluruh file yang meningkatkan kecepatan verifikasi dan memperkuat jaminan integritas dengan mendeteksi perubahan apa pun pada bagian APK yang dilindungi.
Penandatanganan menggunakan APK Signature Scheme v2 menyisipkan Blok Penandatanganan APK ke dalam file APK tepat sebelum bagian Direktori Pusat ZIP. Di dalam Blok Penandatanganan APK, tanda tangan v2 dan informasi identitas penandatangan disimpan dalam Blok Skema Tanda Tangan APK v2 .
APK Signature Scheme v2 diperkenalkan di Android 7.0 (Nougat). Untuk membuat APK dapat diinstal di Android 6.0 (Marshmallow) dan perangkat yang lebih lama, APK harus ditandatangani menggunakan penandatanganan JAR sebelum ditandatangani dengan skema v2.
Blok Penandatanganan APK
Untuk menjaga kompatibilitas mundur dengan format APK v1, tanda tangan v2 dan APK yang lebih baru disimpan di dalam Blok Penandatanganan APK, wadah baru yang diperkenalkan untuk mendukung Skema Tanda Tangan APK v2. Dalam file APK, Blok Penandatanganan APK terletak tepat sebelum Direktori Pusat ZIP, yang terletak di akhir file.
Blok tersebut berisi pasangan nilai ID yang dibungkus sedemikian rupa sehingga memudahkan untuk menemukan blok di APK. Tanda tangan v2 APK disimpan sebagai pasangan nilai ID dengan ID 0x7109871a.
Format
Format Blok Penandatanganan APK adalah sebagai berikut (semua bidang numerik adalah little-endian):
-
size of block
dalam byte (tidak termasuk bidang ini) (uint64) - Urutan pasangan nilai ID dengan awalan panjang uint64:
-
ID
(uint32) -
value
(panjang variabel: panjang pasangan - 4 byte)
-
-
size of block
dalam byte—sama dengan bidang pertama (uint64) -
magic
"APK Sig Block 42" (16 byte)
APK diurai dengan terlebih dahulu menemukan awal Direktori Pusat ZIP (dengan menemukan catatan ZIP Akhir Direktori Pusat di akhir file, lalu membaca offset awal Direktori Pusat dari catatan). Nilai magic
menyediakan cara cepat untuk menetapkan bahwa apa yang mendahului Direktori Pusat kemungkinan adalah Blok Penandatanganan APK. size of block
kemudian secara efisien menunjuk ke awal blok dalam file.
Pasangan nilai ID dengan ID yang tidak diketahui harus diabaikan saat menafsirkan blok.
APK Signature Scheme v2 Block
APK ditandatangani oleh satu atau beberapa penandatangan/identitas, masing-masing diwakili oleh kunci penandatanganan. Informasi ini disimpan sebagai APK Signature Scheme v2 Block. Untuk setiap penandatangan, informasi berikut disimpan:
- (algoritma tanda tangan, intisari, tanda tangan) tupel. Intisari disimpan untuk memisahkan verifikasi tanda tangan dari pemeriksaan integritas konten APK.
- Rantai sertifikat X.509 yang mewakili identitas penanda tangan.
- Atribut tambahan sebagai pasangan nilai kunci.
Untuk setiap penandatangan, APK diverifikasi menggunakan tanda tangan yang didukung dari daftar yang disediakan. Tanda tangan dengan algoritma tanda tangan yang tidak diketahui diabaikan. Terserah setiap implementasi untuk memilih tanda tangan mana yang akan digunakan ketika beberapa tanda tangan yang didukung ditemukan. Ini memungkinkan pengenalan metode penandatanganan yang lebih kuat di masa mendatang dengan cara yang kompatibel ke belakang. Pendekatan yang disarankan adalah memverifikasi tanda tangan terkuat.
Format
APK Signature Scheme v2 Block disimpan di dalam APK Signing Block di bawah ID 0x7109871a
.
Format APK Signature Scheme v2 Block adalah sebagai berikut (semua nilai numerik adalah little-endian, semua bidang dengan awalan panjang menggunakan uint32 untuk panjang):
- urutan penanda dengan awalan panjang dari
signer
yang diawali dengan panjang :-
signed data
dengan awalan panjang :- urutan awalan panjang dari
digests
awalan panjang :-
signature algorithm ID
(uint32) - (panjang-diawali)
digest
—lihat Konten yang Dilindungi Integritas
-
- urutan awalan panjang dari
certificates
X.509 :-
certificate
X.509 dengan awalan panjang (formulir ASN.1 DER)
-
- urutan awalan panjang dari
additional attributes
awalan panjang :-
ID
(uint32) -
value
(panjang variabel: panjang atribut tambahan - 4 byte)
-
- urutan awalan panjang dari
- urutan awalan panjang dari
signatures
dengan awalan panjang :-
signature algorithm ID
(uint32) -
signature
dengan awalan panjang di atassigned data
-
-
public key
dengan awalan panjang (SubjectPublicKeyInfo, formulir ASN.1 DER)
-
ID Algoritma Tanda Tangan
- 0x0101—RSASSA-PSS dengan intisari SHA2-256, SHA2-256 MGF1, garam 32 byte, cuplikan: 0xbc
- 0x0102—RSASSA-PSS dengan intisari SHA2-512, SHA2-512 MGF1, garam 64 byte, cuplikan: 0xbc
- 0x0103—RSASSA-PKCS1-v1_5 dengan intisari SHA2-256. Ini untuk membangun sistem yang memerlukan tanda tangan deterministik.
- 0x0104—RSASSA-PKCS1-v1_5 dengan intisari SHA2-512. Ini untuk membangun sistem yang memerlukan tanda tangan deterministik.
- 0x0201—ECDSA dengan intisari SHA2-256
- 0x0202—ECDSA dengan intisari SHA2-512
- 0x0301—DSA dengan intisari SHA2-256
Semua algoritma tanda tangan di atas didukung oleh platform Android. Alat penandatanganan dapat mendukung subset algoritme.
Ukuran kunci yang didukung dan kurva EC:
- RSA: 1024, 2048, 4096, 8192, 16384
- EC: NIST P-256, P-384, P-521
- DSA: 1024, 2048, 3072
Konten yang dilindungi integritas
Untuk tujuan melindungi konten APK, APK terdiri dari empat bagian:
- Isi entri ZIP (dari offset 0 hingga awal Blok Penandatanganan APK)
- Blok Penandatanganan APK
- Direktori Pusat ZIP
- ZIP Akhir Direktori Pusat
APK Signature Scheme v2 melindungi integritas bagian 1, 3, 4, dan blok signed data
dari APK Signature Scheme v2 Block yang terdapat di dalam bagian 2.
Integritas bagian 1, 3, dan 4 dilindungi oleh satu atau lebih intisari dari isinya yang disimpan dalam blok signed data
yang, pada gilirannya, dilindungi oleh satu atau lebih tanda tangan.
Intisari atas bagian 1, 3, dan 4 dihitung sebagai berikut, mirip dengan pohon Merkle dua tingkat . Setiap bagian dibagi menjadi potongan 1 MB (2 20 byte) berturut-turut. Potongan terakhir di setiap bagian mungkin lebih pendek. Intisari setiap potongan dihitung melalui penggabungan byte 0xa5
, panjang potongan dalam byte (little-endian uint32), dan konten potongan. Intisari tingkat atas dihitung melalui penggabungan byte 0x5a
, jumlah potongan (little-endian uint32), dan penggabungan intisari potongan dalam urutan potongan muncul di APK. Intisari dihitung dalam mode chunked untuk memungkinkan mempercepat komputasi dengan memparalelkannya.
Perlindungan bagian 4 (ZIP End of Central Directory) diperumit oleh bagian yang berisi offset dari ZIP Central Directory. Offset berubah saat ukuran Blok Penandatanganan APK berubah, misalnya, saat tanda tangan baru ditambahkan. Jadi, ketika menghitung intisari melalui ZIP End of Central Directory, bidang yang berisi offset dari ZIP Central Directory harus diperlakukan sebagai berisi offset dari APK Signing Block.
Perlindungan Rollback
Penyerang dapat mencoba memverifikasi APK bertanda v2 sebagai APK bertanda v1 di platform Android yang mendukung verifikasi APK bertanda v2. Untuk mengurangi serangan ini, APK bertanda v2 yang juga bertanda tangan v1 harus berisi atribut X-Android-APK-Signed di bagian utama file META-INF/*.SF. Nilai atribut adalah kumpulan ID skema tanda tangan APK yang dipisahkan koma (ID skema ini adalah 2). Saat memverifikasi tanda tangan v1, pemverifikasi APK diperlukan untuk menolak APK yang tidak memiliki tanda tangan untuk skema tanda tangan APK yang disukai pemverifikasi dari set ini (misalnya, skema v2). Perlindungan ini bergantung pada fakta bahwa konten file META-INF/*.SF dilindungi oleh tanda tangan v1. Lihat bagian tentang verifikasi APK yang ditandatangani JAR .
Penyerang dapat mencoba menghapus tanda tangan yang lebih kuat dari Blok Skema Tanda Tangan APK v2. Untuk mengurangi serangan ini, daftar ID algoritme tanda tangan yang digunakan untuk menandatangani APK disimpan di blok signed data
tangan yang dilindungi oleh setiap tanda tangan.
Verifikasi
Di Android 7.0 dan yang lebih baru, APK dapat diverifikasi menurut Skema Tanda Tangan APK v2+ atau penandatanganan JAR (skema v1). Platform lama mengabaikan tanda tangan v2 dan hanya memverifikasi tanda tangan v1.
Verifikasi APK Signature Scheme v2
- Temukan Blok Penandatanganan APK dan verifikasi bahwa:
- Dua bidang ukuran Blok Penandatanganan APK berisi nilai yang sama.
- ZIP Central Directory segera diikuti oleh ZIP End of Central Directory record.
- ZIP End of Central Directory tidak diikuti oleh lebih banyak data.
- Temukan Blok Skema Tanda Tangan APK v2 pertama di dalam Blok Penandatanganan APK. Jika blok v2 jika ada, lanjutkan ke langkah 3. Jika tidak, kembali ke verifikasi APK menggunakan skema v1 .
- Untuk setiap
signer
di Blok APK Signature Scheme v2:- Pilih
signature algorithm ID
didukung terkuat darisignatures
. Urutan kekuatan tergantung pada setiap versi implementasi/platform. - Verifikasi tanda tangan yang sesuai dari
signature
signatures
terhadapsigned data
menggunakanpublic key
. (Sekarang aman untuk menguraisigned data
.) - Verifikasi bahwa daftar berurutan ID algoritme tanda tangan dalam
digests
dansignatures
adalah identik. (Ini untuk mencegah pengupasan/penambahan tanda tangan.) - Hitung intisari konten APK menggunakan algoritme intisari yang sama dengan algoritme intisari yang digunakan oleh algoritme tanda tangan.
- Verifikasi bahwa intisari yang dihitung identik dengan
digests
digest
- Pastikan bahwa SubjectPublicKeyInfo dari
certificate
certificates
identik denganpublic key
.
- Pilih
- Verifikasi berhasil jika setidaknya satu
signer
ditemukan dan langkah 3 berhasil untuk setiapsigner
yang ditemukan.
Catatan : APK tidak boleh diverifikasi menggunakan skema v1 jika terjadi kegagalan pada langkah 3 atau 4.
Verifikasi APK bertanda JAR (skema v1)
APK bertanda JAR adalah JAR bertanda tangan standar , yang harus berisi persis entri yang tercantum dalam META-INF/MANIFEST.MF dan di mana semua entri harus ditandatangani oleh kumpulan penandatangan yang sama. Integritasnya diverifikasi sebagai berikut:
- Setiap penanda tangan diwakili oleh entri JAR META-INF/<signer>.SF dan META-INF/<signer>.(RSA|DSA|EC).
- <signer>.(RSA|DSA|EC) adalah PKCS #7 CMS ContentInfo dengan struktur SignedData yang tanda tangannya diverifikasi melalui file <signer>.SF.
- File <signer>.SF berisi ringkasan seluruh file META-INF/MANIFEST.MF dan ringkasan setiap bagian META-INF/MANIFEST.MF. Intisari seluruh file dari MANIFEST.MF diverifikasi. Jika gagal, intisari dari setiap bagian MANIFEST.MF diverifikasi sebagai gantinya.
- META-INF/MANIFEST.MF berisi, untuk setiap entri JAR yang dilindungi integritas, bagian yang dinamai yang berisi intisari dari konten entri yang tidak terkompresi. Semua intisari ini diverifikasi.
- Verifikasi APK gagal jika APK berisi entri JAR yang tidak tercantum dalam MANIFEST.MF dan bukan bagian dari tanda tangan JAR.
Rantai perlindungan dengan demikian adalah <signer>.(RSA|DSA|EC) -> <signer>.SF -> MANIFEST.MF -> konten dari setiap entri JAR yang dilindungi integritas.