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 akan menyisipkan blok penandatanganan APK ke dalam file APK tepat sebelum bagian ZIP Central Directory. Di dalam blok penandatanganan APK, tanda tangan v2 dan informasi identitas penanda tangan disimpan dalam blok APK signature scheme 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 mempertahankan kompatibilitas mundur dengan format APK v1, tanda tangan APK v2 dan yang lebih baru disimpan di dalam blok penandatanganan APK, penampung 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 ini berisi pasangan nilai ID yang digabungkan dengan cara yang memudahkan penentuan lokasi 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 kolom ini) (uint64)- Urutan pasangan nilai ID berawalan uint64-length:
ID
(uint32)value
(panjang variabel: panjang pasangan - 4 byte)
size of block
dalam byte—sama dengan kolom pertama (uint64)magic
“APK Sig Block 42” (16 byte)
APK diuraikan dengan terlebih dahulu menemukan awal Direktori Pusat ZIP (dengan
menemukan Akhir ZIP dari kumpulan data Central Directory di akhir file, lalu
membaca offset awal Central Directory dari kumpulan data). Nilai
magic
menyediakan cara cepat untuk menetapkan bahwa apa yang mendahului
Direktori Pusat kemungkinan adalah blok penandatanganan APK. Nilai size of
block
kemudian mengarah ke awal blok secara efisien 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 beberapa penanda tangan/identitas, yang masing-masing diwakili oleh kunci penandatanganan. Informasi ini disimpan sebagai blok APK signature scheme v2. Untuk setiap penanda tangan, informasi berikut disimpan:
- (algoritma tanda tangan, digest, tanda tangan). Ringkasan 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 penanda tangan, APK diverifikasi menggunakan tanda tangan yang didukung dari daftar yang diberikan. Tanda tangan dengan algoritma tanda tangan yang tidak diketahui akan diabaikan. Setiap implementasi dapat memilih tanda tangan yang akan digunakan saat beberapa tanda tangan yang didukung ditemukan. Hal ini memungkinkan pengenalan metode penandatanganan yang lebih kuat di masa mendatang dengan cara yang kompatibel dengan versi lama. Pendekatan yang disarankan adalah memverifikasi tanda tangan terkuat.
Format
Blok APK signature scheme v2 disimpan di dalam blok penandatanganan APK dengan ID
0x7109871a
.
Format blok APK signature scheme v2 adalah sebagai berikut (semua nilai numerik adalah little-endian, semua kolom awalan panjang menggunakan uint32 untuk panjang):
- urutan berawalan panjang dari
signer
berawalan panjang:signed data
dengan awalan panjang:- urutan
digests
yang diawali dengan panjang:signature algorithm ID
(uint32)- (dengan awalan panjang)
digest
—lihat Konten yang Dilindungi Integritas
- urutan
certificates
X.509 dengan awalan panjang:certificate
X.509 dengan awalan panjang (bentuk DER ASN.1)
- urutan
additional attributes
yang diawali dengan panjang:ID
(uint32)value
(panjang variabel: panjang atribut tambahan - 4 byte)
- urutan
- urutan
signatures
yang diawali dengan panjang:signature algorithm ID
(uint32)signature
dengan awalan panjang di atassigned data
public key
dengan awalan panjang (SubjectPublicKeyInfo, format ASN.1 DER)
ID algoritma tanda tangan
- 0x0101—RSASSA-PSS dengan ringkasan SHA2-256, SHA2-256 MGF1, 32 byte salt, trailer: 0xbc
- 0x0102—RSASSA-PSS dengan ringkasan SHA2-512, SHA2-512 MGF1, salt 64 byte, trailer: 0xbc
- 0x0103—RSASSA-PKCS1-v1_5 dengan ringkasan SHA2-256. Ini untuk sistem build yang memerlukan tanda tangan deterministik.
- 0x0104—RSASSA-PKCS1-v1_5 dengan ringkasan SHA2-512. Ini untuk sistem build yang memerlukan tanda tangan deterministik.
- 0x0201—ECDSA dengan ringkasan SHA2-256
- 0x0202—ECDSA dengan ringkasan SHA2-512
- 0x0301—DSA dengan ringkasan SHA2-256
Semua algoritma tanda tangan di atas didukung oleh platform Android. Alat penandatanganan dapat mendukung sebagian 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:
- Konten entri ZIP (dari offset 0 hingga awal blok penandatanganan APK)
- Blok penandatanganan APK
- Direktori Pusat ZIP
- ZIP 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 beberapa ringkasan
kontennya yang disimpan dalam blok signed data
yang, pada
gilirannya, dilindungi oleh satu atau beberapa tanda tangan.
Ringkasan di bagian 1, 3, dan 4 dihitung sebagai berikut, mirip dengan
Merkle tree dua tingkat.
Setiap bagian dibagi menjadi beberapa bagian berukuran 1 MB (220 byte) secara berurutan. Bagian terakhir
di setiap bagian mungkin lebih pendek. Ringkasan setiap potongan dihitung melalui
penyambungan byte 0xa5
, panjang potongan dalam byte
(little-endian uint32), dan konten potongan tersebut. Ringkasan tingkat atas
dihitung berdasarkan penyambungan byte 0x5a
, jumlah potongan
(uint32 little-endian), dan penyambungan ringkasan potongan dalam
urutan kemunculan potongan di APK. Ringkasan dihitung dalam bentuk potongan untuk
mempercepat komputasi dengan melakukan paralelisasi.
Perlindungan bagian 4 (ZIP End of Central Directory) dipersulit oleh bagian yang berisi offset ZIP Central Directory. Offset berubah saat ukuran blok penandatanganan APK berubah, misalnya, saat tanda tangan baru ditambahkan. Dengan demikian, saat menghitung ringkasan di Akhir Direktori Pusat ZIP, kolom yang berisi offset Direktori Pusat ZIP harus diperlakukan sebagai berisi offset blok penandatanganan APK.
Perlindungan rollback
Penyerang dapat mencoba memverifikasi APK yang ditandatangani v2 sebagai APK yang ditandatangani v1 di platform Android yang mendukung verifikasi APK yang ditandatangani v2. Untuk mengurangi serangan ini, APK yang ditandatangani v2 yang juga ditandatangani 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, verifikasi APK diwajibkan untuk menolak APK yang tidak memiliki tanda tangan untuk skema tanda tangan APK yang lebih disukai verifikasi dari kumpulan 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 APK Signature
Scheme v2. Untuk mengurangi serangan ini, daftar ID algoritma 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 sesuai dengan 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 pastikan bahwa:
- Dua kolom ukuran blok penandatanganan APK berisi nilai yang sama.
- Direktori Pusat ZIP segera diikuti dengan data Akhir Direktori Pusat ZIP.
- Akhir Direktori Pusat ZIP tidak diikuti dengan 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 ke memverifikasi APK menggunakan skema v1.
- Untuk setiap
signer
dalam blok APK signature scheme v2:- Pilih
signature algorithm ID
terkuat yang didukung darisignatures
. Urutan kekuatan bergantung pada setiap versi implementasi/platform. - Verifikasi
signature
yang sesuai darisignatures
terhadapsigned data
menggunakanpublic key
. (Sekarang menguraikansigned data
dengan aman.) - Pastikan daftar ID algoritma tanda tangan yang diurutkan di
digests
dansignatures
identik. (Tindakan ini untuk mencegah penghapusan/penambahan tanda tangan.) - Menghitung ringkasan konten APK menggunakan algoritma ringkasan yang sama dengan algoritma ringkasan yang digunakan oleh algoritma tanda tangan.
- Verifikasi bahwa ringkasan yang dihitung identik dengan
digest
yang sesuai daridigests
. - Verifikasi bahwa SubjectPublicKeyInfo dari
certificate
pertamacertificates
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 yang ditandatangani JAR (skema v1)
APK yang ditandatangani JAR adalah JAR yang ditandatangani standar, yang harus berisi entri yang tercantum di META-INF/MANIFEST.MF dan semua entri harus ditandatangani oleh kumpulan penanda tangan 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 file lengkap META-INF/MANIFEST.MF dan ringkasan setiap bagian META-INF/MANIFEST.MF. Ringkasan seluruh file MANIFEST.MF diverifikasi. Jika gagal, ringkasan setiap bagian MANIFEST.MF akan diverifikasi.
- META-INF/MANIFEST.MF berisi, untuk setiap entri JAR yang dilindungi integritas, bagian yang diberi nama sesuai yang berisi ringkasan konten entri yang tidak dikompresi. Semua ringkasan ini telah diverifikasi.
- Verifikasi APK gagal jika APK berisi entri JAR yang tidak tercantum dalam MANIFEST.MF dan bukan bagian dari tanda tangan JAR.
Dengan demikian, rantai perlindungannya adalah <signer>.(RSA|DSA|EC) -> <signer>.SF -> MANIFEST.MF -> konten dari setiap entri JAR yang dilindungi integritas.