Skema Tanda Tangan APK v2

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 sebelum dan sesudah penandatanganan

Gambar 1. APK sebelum dan sesudah penandatanganan

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 :
      • 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 signatures dengan awalan panjang :
      • signature algorithm ID (uint32)
      • signature dengan awalan panjang di atas signed 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:

  1. Isi entri ZIP (dari offset 0 hingga awal Blok Penandatanganan APK)
  2. Blok Penandatanganan APK
  3. Direktori Pusat ZIP
  4. ZIP Akhir Direktori Pusat

Bagian APK setelah penandatanganan

Gambar 2. Bagian APK setelah penandatanganan

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.

intisari APK

Gambar 3. Intisari APK

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.

Proses verifikasi tanda tangan APK

Gambar 4. Proses verifikasi tanda tangan APK (langkah baru berwarna merah)

Verifikasi APK Signature Scheme v2

  1. Temukan Blok Penandatanganan APK dan verifikasi bahwa:
    1. Dua bidang ukuran Blok Penandatanganan APK berisi nilai yang sama.
    2. ZIP Central Directory segera diikuti oleh ZIP End of Central Directory record.
    3. ZIP End of Central Directory tidak diikuti oleh lebih banyak data.
  2. 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 .
  3. Untuk setiap signer di Blok APK Signature Scheme v2:
    1. Pilih signature algorithm ID didukung terkuat dari signatures . Urutan kekuatan tergantung pada setiap versi implementasi/platform.
    2. Verifikasi tanda tangan yang sesuai dari signature signatures terhadap signed data menggunakan public key . (Sekarang aman untuk mengurai signed data .)
    3. Verifikasi bahwa daftar berurutan ID algoritme tanda tangan dalam digests dan signatures adalah identik. (Ini untuk mencegah pengupasan/penambahan tanda tangan.)
    4. Hitung intisari konten APK menggunakan algoritme intisari yang sama dengan algoritme intisari yang digunakan oleh algoritme tanda tangan.
    5. Verifikasi bahwa intisari yang dihitung identik dengan digests digest
    6. Pastikan bahwa SubjectPublicKeyInfo dari certificate certificates identik dengan public key .
  4. Verifikasi berhasil jika setidaknya satu signer ditemukan dan langkah 3 berhasil untuk setiap signer 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:

  1. Setiap penanda tangan diwakili oleh entri JAR META-INF/<signer>.SF dan META-INF/<signer>.(RSA|DSA|EC).
  2. <signer>.(RSA|DSA|EC) adalah PKCS #7 CMS ContentInfo dengan struktur SignedData yang tanda tangannya diverifikasi melalui file <signer>.SF.
  3. 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.
  4. 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.
  5. 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.