Android 11 支援與串流相容的簽署配置,也就是 APK 簽署配置 v4。v4 簽章是根據針對 APK 所有位元組計算的 Merkle 雜湊樹狀結構產生。這個配置完全遵循 fs-verity 雜湊樹狀結構 (例如,以零填補鹽值,並以零填補最後一個區塊)。Android 11 會將簽章儲存在另一個檔案 <apk name>.apk.idsig 中。V4 簽章需要搭配 v2 或 v3 簽章。
檔案格式
所有數值欄位都採用小端序。所有欄位佔用的位元組數量都與 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;
};merkle_tree 是 APK 的完整 Merkle 樹狀結構,計算方式請參閱 fs-verity 說明文件。
生產者和消費者
如果您使用預設參數執行 apksigner Android SDK 工具,系統會產生 v4 簽章檔案。停用 v4 簽署的方式與其他簽署機制相同。這項工具也能驗證 v4 簽章是否有效。
執行 adb install --incremental 指令時,adb 會預期 .apk.idsig 檔案位於 APK 旁邊。adb 預設也會使用 IDSIG 檔案嘗試增量安裝,如果檔案遺失或無效,則會改為一般安裝。
建立安裝工作階段時,PackageInstaller 中的新串流安裝 API 會在將檔案新增至工作階段時,接受已移除的 v4 簽章做為個別引數。此時,signing_info 會以整個 Blob 的形式傳遞至 IncFS。IncFS 會從 Blob 擷取根雜湊。
提交安裝工作階段時,PackageManagerService 會發出 ioctl 呼叫,從 IncFS 擷取 signing_info blob、剖析該 blob,並驗證簽章。
Incremental Data Loader 元件會透過資料載入器原生 API,串流簽章的 Merkle 樹狀結構部分。package 服務殼層指令 install-incremental 接受以 Base64 編碼的已移除 v4 簽章檔案,做為每個新增檔案的參數。對應的 Merkle 樹狀結構必須傳送至指令的 stdin。
apk_digest
apk_digest 是第一個可用的內容摘要,順序如下:
- V3、1 MB 區塊、SHA2-512 (
CONTENT_DIGEST_CHUNKED_SHA512) - V3、4 KB 區塊、SHA2-256 (
CONTENT_DIGEST_VERITY_CHUNKED_SHA256) - V3、1 MB 區塊、SHA2-256 (
CONTENT_DIGEST_CHUNKED_SHA256) - V2、SHA2-512
- 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