APK Signature Scheme v4

Android 11 รองรับรูปแบบการเซ็นชื่อที่เข้ากันได้กับการสตรีมด้วย APK Signature Scheme v4 ลายเซ็น v4 อิงตามแผนผังแฮชของ Merkle ที่คำนวณจากไบต์ทั้งหมดของ APK มันเป็นไปตามโครงสร้างของต้นไม้แฮช fs-verity ทุกประการ (เช่น เติมเกลือให้ศูนย์และบล็อกสุดท้ายเป็นศูนย์) Android 11 เก็บลายเซ็นในไฟล์แยกต่างหาก <apk name>.apk.idsig ลายเซ็น v4 ต้องมีลายเซ็น v2 หรือ v3 เสริม

รูปแบบไฟล์

ฟิลด์ตัวเลขทั้งหมดอยู่ใน endian น้อย ฟิลด์ทั้งหมดใช้จำนวนไบต์ตรงตาม sizeof() โดยไม่มีการเพิ่มหรือการจัดตำแหน่งโดยนัย

ด้านล่างนี้เป็นโครงสร้างตัวช่วยเพื่อลดความซับซ้อนของคำจำกัดความ

template <class SizeT>
struct sized_bytes {
        SizeT size;
        byte bytes[size];
};

เนื้อหาไฟล์หลัก:

struct V4Signature {
        int32 version; // only version 2 is supported as of now
        sized_bytes<int32> hashing_info;
        sized_bytes<int32> signing_info;
        sized_bytes<int32> merkle_tree;  // optional
};

hashing_info เป็นพารามิเตอร์ที่ใช้สำหรับการสร้าง hash tree + the root hash:

struct hashing_info.bytes {
    int32 hash_algorithm;    // only 1 == SHA256 supported
    int8 log2_blocksize;     // only 12 (block size 4096) supported now
    sized_bytes<int32> salt; // used exactly as in fs-verity, 32 bytes max
    sized_bytes<int32> raw_root_hash; // salted digest of the first Merkle tree page
};

signing_info เป็นโครงสร้างต่อไปนี้:

struct signing_info.bytes {
    sized_bytes<int32> apk_digest;  // used to match with the corresponding APK
    sized_bytes<int32> x509_certificate; // ASN.1 DER form
    sized_bytes<int32> additional_data; // a free-form binary data blob
    sized_bytes<int32> public_key; // ASN.1 DER, must match the x509_certificate
    int32 signature_algorithm_id; // see the APK v2 doc for the list
    sized_bytes<int32> signature;
};
  • apk_digest นำมาจากบล็อกการลงนาม v3 ของ APK หรือหากไม่มีอยู่ในบล็อก v2 (ดู apk_digest )

ในการสร้างและยืนยันรหัส signature ต้องทำให้ข้อมูลต่อไปนี้เป็นอนุกรมลงในไบนารี blob และส่งผ่านไปยังอัลกอริทึมการลงนาม / การตรวจสอบเป็น ข้อมูลที่ลงนาม :

struct V4DataForSigning {
        int32 size;
        int64 file_size; // the size of the file that's been hashed.
        hashing_info.hash_algorithm;
        hashing_info.log2_blocksize;
        hashing_info.salt;
        hashing_info.raw_root_hash;
        signing_info.apk_digest;
        signing_info.x509_certificate;
        signing_info.additional_data;
};
  1. merkle_tree คือ Merkle tree ทั้งหมด ของ APK ซึ่งคำนวณตามที่อธิบายไว้ในเอกสารประกอบ fs-verity

ผู้ผลิตและผู้บริโภค

เครื่องมือ apksigner Android SDK ตอนนี้สร้างไฟล์ลายเซ็น v4 หากคุณเรียกใช้ด้วยพารามิเตอร์เริ่มต้น การลงนาม v4 สามารถปิดใช้งานได้เช่นเดียวกับรูปแบบการลงนามอื่นๆ นอกจากนี้ยังสามารถตรวจสอบได้ว่าลายเซ็น v4 นั้นถูกต้องหรือไม่

adb คาดว่าไฟล์ .apk.idsig จะอยู่ถัดจาก .apk เมื่อรันคำสั่ง adb install --incremental
นอกจากนี้ยังจะใช้ไฟล์ .idsig เพื่อลองติดตั้งแบบเพิ่มหน่วยตามค่าเริ่มต้น และจะถอยกลับไปเป็นการติดตั้งปกติหากไฟล์นั้นหายไปหรือไม่ถูกต้อง

เมื่อมีการสร้างเซสชันการติดตั้ง API การติดตั้งการสตรีมใหม่ใน PackageInstaller จะยอมรับลายเซ็น v4 ที่ ถูกถอดออก เป็นอาร์กิวเมนต์แยกต่างหากเมื่อเพิ่มไฟล์ไปยังเซสชัน ณ จุดนี้ signing_info ถูกส่งผ่านไปยัง incfs ทั้งหมดเป็น Blob Incfs แยกแฮชรูตจากหยด

เมื่อมีการคอมมิตเซสชั่นการติดตั้ง PackageManagerService จะทำ ioctl เพื่อดึงข้อมูลการ sign_info blob จาก incfs แยกวิเคราะห์และตรวจสอบลายเซ็น

คอมโพเนนต์ตัวโหลดข้อมูลส่วนเพิ่มคาดว่าจะสตรีมส่วนทรี Merkle ของลายเซ็นผ่าน API ดั้งเดิมของตัวโหลดข้อมูล
คำสั่ง package service shell install-incremental ยอมรับไฟล์ลายเซ็น v4 ที่ถูกถอดออกมาซึ่งเข้ารหัสเป็น base64 เป็นพารามิเตอร์สำหรับแต่ละไฟล์ที่เพิ่ม ต้องส่ง Merkle tree ที่เกี่ยวข้องไปยัง stdin ของคำสั่ง

apk_digest

apk_digest เป็นไดเจสต์เนื้อหาแรกที่มีให้ตามลำดับ:

  1. V3, บล็อก 1MB, SHA2-512 (CONTENT_DIGEST_CHUNKED_SHA512),
  2. V3, บล็อก 4KB, SHA2-256 (CONTENT_DIGEST_VERITY_CHUNKED_SHA256),
  3. V3, บล็อก 1MB, SHA2-256 (CONTENT_DIGEST_CHUNKED_SHA256),
  4. V2, SHA2-512,
  5. V2, SHA2-256.

ดู ลำดับลายเซ็นนำหน้าความยาว ใน APK Signature Scheme v3

กระบวนการตรวจสอบ apk v4
รูปที่ 1 : ขั้นตอนการตรวจสอบ APK v4

การตรวจสอบและการทดสอบ

ตรวจสอบการใช้งานโดยใช้การทดสอบหน่วยคุณลักษณะและ CTS

  • CtsIncrementalInstallHostTestCases
    • /android/cts/hostsidetests/incrementalinstall

การทดสอบรูปแบบลายเซ็น

ในการทดสอบรูปแบบลายเซ็น ให้ ตั้งค่าสภาพแวดล้อมการพัฒนา และรันการทดสอบด้วยตนเองต่อไปนี้:

$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest

การทดสอบรูปแบบลายเซ็นด้วย Android SDK (ADB และ apksigner)

หากต้องการทดสอบรูปแบบลายเซ็นด้วย Android SDK ให้ ตั้งค่าสภาพแวดล้อมการพัฒนา และตรวจสอบให้แน่ใจว่าคุณได้ใช้งาน IncFS เรียบร้อย แล้ว จากนั้นแฟลชบิลด์บนอุปกรณ์เป้าหมายหรืออีมูเลเตอร์ คุณต้องสร้างหรือรับ APK ที่มีอยู่ จากนั้นจึงสร้าง คีย์การลงนามแก้ไขข้อบกพร่อง สุดท้าย ลงชื่อและติดตั้ง apk ด้วยรูปแบบลายเซ็น v4 จากโฟลเดอร์เครื่องมือสร้าง

เข้าสู่ระบบ

$ ./apksigner sign --ks debug.keystore game.apk

ติดตั้ง

$ ./adb install game.apk

การทดสอบเหล่านี้สามารถพบได้ที่ไหน?

/android/cts/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java