APK Signature Scheme v4

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

รูปแบบไฟล์

ฟิลด์ตัวเลขทั้งหมดอยู่ในรูปแบบ Little 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 คือพารามิเตอร์ที่ใช้สำหรับการสร้าง แฮชทรีและแฮชรูท

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;
};

merkle_tree คือต้นไม้ Merkle ทั้งหมดของ APK ซึ่งคำนวณตามที่อธิบายไว้ในเอกสารประกอบ fs-verity

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

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

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

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

เมื่อมีการคอมมิตเซสชันการติดตั้ง PackageManagerService จะioctlเรียกใช้เพื่อดึงข้อมูลออบเจ็กต์ขนาดใหญ่แบบไบนารี (Blob) signing_info จาก IncFS, แยกวิเคราะห์ และตรวจสอบลายเซ็น

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

apk_digest

apk_digest คือสรุปเนื้อหาแรกที่พร้อมใช้งานตามลำดับต่อไปนี้

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

ดูลำดับของลายเซ็นที่นำหน้าด้วยความยาว ซึ่งนำหน้าด้วยความยาวใน APK Signature Scheme v3

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

กระบวนการตรวจสอบ APK v4 แสดงอยู่ในรูปต่อไปนี้

กระบวนการตรวจสอบ APK v4

รูปที่ 1 กระบวนการตรวจสอบ APK เวอร์ชัน 4

ตรวจสอบการติดตั้งใช้งานโดยใช้การทดสอบหน่วยฟีเจอร์และ CTS

  • CtsIncrementalInstallHostTestCases
  • /android/cts/hostsidetests/incrementalinstall

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

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

$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest

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

ใช้กระบวนการนี้เพื่อทดสอบรูปแบบลายเซ็นด้วย Android SDK

  1. ตั้งค่าสภาพแวดล้อมการสร้าง และตรวจสอบว่าคุณได้ติดตั้งใช้งาน IncFS เสร็จสมบูรณ์แล้ว
  2. แฟลชบิลด์ในอุปกรณ์จริงหรือโปรแกรมจำลองเป้าหมาย
  3. สร้างหรือรับ APK ที่มีอยู่ แล้วสร้างคีย์การลงนามสำหรับแก้ไขข้อบกพร่อง
  4. ลงนามและติดตั้ง APK ด้วยรูปแบบลายเซ็น v4 จากโฟลเดอร์ build-tools

    ลงชื่อ
    $ ./apksigner sign --ks debug.keystore game.apk

    ติดตั้ง
    $ ./adb install game.apk

    ตำแหน่งที่พบการทดสอบเหล่านี้
    /android/cts/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java