APK簽名方案v4

Android 11通過APK簽名方案v4支持流兼容的簽名方案。 v4簽名基於在APK的所有字節上計算的Merkle哈希樹。它完全遵循fs-verity哈希樹的結構(例如,對salt進行零填充,並對最後一個塊進行零填充)。 Android 11將簽名存儲在單獨的文件<apk name>.apk.idsig簽名需要補充的v2v3簽名。

文件格式

所有數字字段均採用小尾數形式。所有字段正好佔據其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來自APK的v3簽名塊,或者(如果不存在)來自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是APK的整個Merkle樹,按照fs-verity文檔中的描述進行計算。

生產者和消費者

如果使用默認參數運行,則apksigner Android SDK工具會生成v4簽名文件。可以與其他簽名方案相同的方式禁用v4簽名。它還可以驗證v4簽名是否有效。

當運行adb install --incremental命令時, adb期望.apk.idsig文件位於.apk旁邊。
默認情況下,它還會使用.idsig文件嘗試增量安裝,如果丟失或無效,它將退回到常規安裝。

創建安裝會話時,在將文件添加到會話時, PackageInstaller的新流安裝API將剝離的v4簽名作為單獨的參數接受。此時, signing_info作為整個blob傳遞到incfs中。 Incfs從Blob中提取根哈希。

提交安裝會話時,PackageManagerService會執行一個ioctl來從incfs中檢索signing_info blob,然後對其進行解析並驗證簽名。

預計增量數據加載程序組件將通過數據加載程序本機API流式傳輸簽名的Merkle樹部分。
package服務外殼程序命令install-incremental接受將編碼為base64的剝離後的v4簽名文件作為每個添加文件的參數。相應的Merkle樹必鬚髮送到命令的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簽名方案v3中的長度前綴簽名序列

apk驗證程序v4
圖1 :APK驗證流程v4

驗證與測試

使用功能單元測試和CTS驗證實施。

  • CtsIncrementalInstallHostTestCases
    • / android / cts / hostsidetests / incrementalinstall

測試簽名格式

要測試簽名格式,請設置開發環境並運行以下手動測試:

$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest

使用Android SDK測試簽名格式(ADB和apksigner)

要使用Android SDK測試簽名格式,請設置開發環境並確保已完成IncFS的實現。然後在目標物理設備或仿真器上刷新構建。您需要生成或獲取現有的APK,然後創建調試簽名密鑰。最後,從build-tools文件夾簽名並安裝v4簽名格式的apk。

符號

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

安裝

$ ./adb install game.apk

在哪裡可以找到這些測試?

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