Skema Tanda Tangan APK 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 penanda tangan disimpan dalam Blok Skema Tanda Tangan APK v2 .
APK Signature Scheme v2 diperkenalkan di Android 7.0 (Nougat). Agar 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 dengan format APK v1, tanda tangan APK v2 dan yang lebih baru disimpan di dalam Blok Penandatanganan APK, sebuah wadah baru yang diperkenalkan untuk mendukung APK Signature Scheme 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 kolom 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 seperti kolom pertama (uint64) -
magic
“APK Sig Block 42” (16 byte)
APK diurai dengan terlebih dahulu menemukan awal Direktori Pusat ZIP (dengan menemukan catatan Akhir Direktori Pusat ZIP di akhir file, kemudian membaca offset awal Direktori Pusat dari catatan). Nilai magic
memberikan cara cepat untuk menetapkan bahwa apa yang mendahului Direktori Pusat kemungkinan besar 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.
Blok Skema Tanda Tangan APK v2
APK ditandatangani oleh satu atau lebih penandatangan/identitas, masing-masing diwakili oleh kunci penandatanganan. Informasi ini disimpan sebagai Blok APK Signature Scheme v2. Untuk setiap penandatangan, informasi berikut disimpan:
- (algoritma tanda tangan, intisari, tanda tangan) tupel. Intisarinya disimpan untuk memisahkan verifikasi tanda tangan dari pemeriksaan integritas konten APK.
- Rantai sertifikat X.509 mewakili identitas penandatangan.
- 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 akan diabaikan. Setiap implementasi bebas memilih tanda tangan mana yang akan digunakan ketika beberapa tanda tangan yang didukung ditemukan. Hal ini memungkinkan pengenalan metode penandatanganan yang lebih kuat di masa depan dengan cara yang kompatibel dengan masa lalu. Pendekatan yang disarankan adalah memverifikasi tanda tangan terkuat.
Format
Blok Skema Tanda Tangan APK v2 disimpan di dalam Blok Penandatanganan APK di bawah ID 0x7109871a
.
Format Blok APK Signature Scheme v2 adalah sebagai berikut (semua nilai numerik adalah little-endian, semua kolom dengan awalan panjang menggunakan uint32 untuk panjangnya):
- urutan
signer
dengan awalan panjang:-
signed data
dengan awalan panjang :- urutan intisari dengan awalan panjang dari
digests
dengan awalan panjang :-
signature algorithm ID
(uint32) -
digest
(awalan panjang) —lihat Konten yang dilindungi integritas
-
- urutan
certificates
X.509 dengan awalan panjang :-
certificate
X.509 dengan awalan panjang (formulir ASN.1 DER)
-
- urutan
additional attributes
dengan awalan panjang:-
ID
(uint32) -
value
(panjang variabel: panjang atribut tambahan - 4 byte)
-
- urutan intisari dengan awalan panjang dari
- urutan tanda tangan dengan 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 DER ASN.1)
-
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 mungkin mendukung subset algoritma.
Ukuran kunci dan kurva EC yang didukung:
- 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 Blok APK Signature Scheme v2 yang terdapat di dalam bagian 2.
Integritas bagian 1, 3, dan 4 dilindungi oleh satu atau lebih intisari kontennya yang disimpan dalam blok signed data
yang, pada gilirannya, dilindungi oleh satu atau lebih tanda tangan.
Intisari bagian 1, 3, dan 4 dihitung sebagai berikut, mirip dengan pohon Merkle dua tingkat. Setiap bagian dibagi menjadi beberapa bagian berturut-turut berukuran 1 MB (2 20 byte). Bagian terakhir di setiap bagian mungkin lebih pendek. Intisari setiap bongkahan dihitung berdasarkan rangkaian byte 0xa5
, panjang bongkahan dalam byte (little-endian uint32), dan konten bongkahan. Intisari tingkat atas dihitung berdasarkan rangkaian byte 0x5a
, jumlah bongkahan (little-endian uint32), dan rangkaian intisari bongkahan sesuai urutan munculnya bongkahan di APK. Intisari dihitung secara terpotong untuk memungkinkan mempercepat komputasi dengan memparalelkannya.
Perlindungan bagian 4 (ZIP End of Central Directory) diperumit dengan bagian yang berisi offset Direktori Pusat ZIP. Offset berubah ketika ukuran Blok Penandatanganan APK berubah, misalnya, ketika tanda tangan baru ditambahkan. Jadi, ketika menghitung intisari pada ZIP End of Central Directory, bidang yang berisi offset dari ZIP Central Directory harus diperlakukan sebagai berisi offset dari Blok Penandatanganan APK.
Perlindungan Kembalikan
Penyerang dapat mencoba memverifikasi APK bertanda tangan v2 sebagai APK bertanda tangan v1 di platform Android yang mendukung verifikasi APK bertanda tangan v2. Untuk memitigasi serangan ini, APK bertanda tangan v2 yang juga bertanda tangan v1 harus berisi atribut X-Android-APK-Signed di bagian utama file META-INF/*.SF-nya. Nilai atribut adalah kumpulan ID skema tanda tangan APK yang dipisahkan koma (ID skema ini adalah 2). Saat memverifikasi tanda tangan v1, pemverifikasi APK diharuskan untuk menolak APK yang tidak memiliki tanda tangan untuk skema tanda tangan APK yang lebih disukai pemverifikasi dari rangkaian ini (misalnya, skema v2). Perlindungan ini bergantung pada fakta bahwa konten file META-INF/*.SF dilindungi oleh tanda tangan v1. Lihat bagian verifikasi APK bertanda tangan JAR .
Penyerang dapat mencoba menghapus tanda tangan yang lebih kuat dari Blok APK Signature Scheme v2. Untuk memitigasi serangan ini, daftar ID algoritme tanda tangan yang digunakan untuk menandatangani APK disimpan dalam blok signed data
yang dilindungi oleh setiap tanda tangan.
Verifikasi
Di Android 7.0 dan yang lebih baru, APK dapat diverifikasi berdasarkan APK Signature Scheme v2+ atau penandatanganan JAR (skema v1). Platform lama mengabaikan tanda tangan v2 dan hanya memverifikasi tanda tangan v1.
Verifikasi APK Skema Tanda Tangan v2
- Temukan Blok Penandatanganan APK dan verifikasi bahwa:
- Dua bidang ukuran Blok Penandatanganan APK berisi nilai yang sama.
- Direktori Pusat ZIP segera diikuti oleh catatan ZIP Akhir Direktori Pusat.
- ZIP Akhir Direktori Pusat tidak diikuti oleh data lainnya.
- Temukan Blok APK Signature Scheme v2 pertama di dalam Blok Penandatanganan APK. Jika Blok v2 ada, lanjutkan ke langkah 3. Jika tidak, kembali memverifikasi APK menggunakan skema v1 .
- Untuk setiap
signer
di Blok APK Signature Scheme v2:- Pilih
signature algorithm ID
terkuat yang didukung darisignatures
. Urutan kekuatan tergantung pada setiap versi implementasi/platform. - Verifikasi
signature
yang sesuai darisignatures
terhadapsigned data
menggunakanpublic key
. (Sekarang aman untuk menguraisigned data
.) - Verifikasi bahwa daftar urutan ID algoritma tanda tangan dalam
digests
dansignatures
adalah identik. (Ini untuk mencegah pengupasan/penambahan tanda tangan.) - Hitung intisari konten APK menggunakan algoritma intisari yang sama dengan algoritma intisari yang digunakan oleh algoritma tanda tangan.
- Verifikasi bahwa intisari yang dihitung identik dengan
digest
yang sesuai daridigests
. - Verifikasi bahwa
certificates
certificate
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 tangan JAR (skema v1)
APK bertanda tangan JAR adalah JAR bertanda tangan standar , yang harus berisi entri persis seperti yang tercantum dalam META-INF/MANIFEST.MF dan semua entri harus ditandatangani oleh kelompok penandatangan yang sama. Integritasnya diverifikasi sebagai berikut:
- Setiap penandatangan diwakili oleh entri JAR META-INF/<signer>.SF dan META-INF/<signer>.(RSA|DSA|EC) .
- <signer>.(RSA|DSA|EC) adalah ContentInfo CMS PKCS #7 dengan struktur SignedData yang tanda tangannya diverifikasi melalui file <signer>.SF.
- File <signer>.SF berisi intisari seluruh file META-INF/MANIFEST.MF dan intisari setiap bagian META-INF/MANIFEST.MF. Intisari seluruh file MANIFEST.MF diverifikasi. Jika gagal, intisari setiap bagian MANIFEST.MF akan diverifikasi.
- META-INF/MANIFEST.MF berisi, untuk setiap entri JAR yang dilindungi integritas, bagian bernama sesuai yang berisi ringkasan konten entri yang tidak terkompresi. Semua intisari ini telah diverifikasi.
- Verifikasi APK gagal jika APK berisi entri JAR yang tidak terdaftar di 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.