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;
};
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-07-27。"],[],[],null,["# APK signature scheme v4\n\nAndroid 11 supports a streaming-compatible signing scheme with the APK\nsignature scheme v4. The v4 signature is based on the Merkle hash tree\ncalculated over all bytes of the APK. It follows the structure of the [fs-verity](https://www.kernel.org/doc/html/latest/filesystems/fsverity.html#merkle-tree) hash tree exactly (for example, zero-padding\nthe salt and zero-padding the last block). Android 11 stores the signature\nin a separate file, `\u003capk name\u003e.apk.idsig`A v4 signature\nrequires a complementary [v2](/docs/security/features/apksigning/v2) or [v3](/docs/security/features/apksigning/v3) signature.\n\nFile format\n-----------\n\nAll numeric fields are in little endian. All fields occupy exactly the number\nof bytes as their `sizeof()`, no implicit padding or\nalignment added.\n\nBelow is a helper struct to simplify the definitions. \n\n```transact-sql\ntemplate \u003cclass SizeT\u003e\nstruct sized_bytes {\n SizeT size;\n byte bytes[size];\n};\n```\n\nMain file content: \n\n```scdoc\nstruct V4Signature {\n int32 version; // only version 2 is supported as of now\n sized_bytes\u003cint32\u003e hashing_info;\n sized_bytes\u003cint32\u003e signing_info;\n sized_bytes\u003cint32\u003e merkle_tree; // optional\n};\n```\n| **Key Term:** If the v4 signature contains the Merkle tree it's called *complete*, without the merkle tree it is *stripped*.\n\n`hashing_info` is the parameters used for hash tree\ngeneration + the root hash: \n\n```scdoc\nstruct hashing_info.bytes {\n int32 hash_algorithm; // only 1 == SHA256 supported\n int8 log2_blocksize; // only 12 (block size 4096) supported now\n sized_bytes\u003cint32\u003e salt; // used exactly as in fs-verity, 32 bytes max\n sized_bytes\u003cint32\u003e raw_root_hash; // salted digest of the first Merkle tree page\n};\n```\n\n`signing_info` is the following struct: \n\n```scdoc\nstruct signing_info.bytes {\n sized_bytes\u003cint32\u003e apk_digest; // used to match with the corresponding APK\n sized_bytes\u003cint32\u003e x509_certificate; // ASN.1 DER form\n sized_bytes\u003cint32\u003e additional_data; // a free-form binary data blob\n sized_bytes\u003cint32\u003e public_key; // ASN.1 DER, must match the x509_certificate\n int32 signature_algorithm_id; // see the APK v2 doc for the list\n sized_bytes\u003cint32\u003e signature;\n};\n```\n| **Note:** `signing_info` as a whole gets passed into the IncFS driver as a binary data blob. Kernel provides an ioctl to retrieve it together with the `hashing_info`.\n\n- `apk_digest` is taken from the APK's v3 signing block, or, if not present, from the v2 block (see [apk_digest](#apk-digest))\n\nTo create and verify a `signature` code has to serialize\nthe following data into binary blob and pass it into the\nsigning / verifying algorithm as the**signed data**: \n\n```scdoc\nstruct V4DataForSigning {\n int32 size;\n int64 file_size; // the size of the file that's been hashed.\n hashing_info.hash_algorithm;\n hashing_info.log2_blocksize;\n hashing_info.salt;\n hashing_info.raw_root_hash;\n signing_info.apk_digest;\n signing_info.x509_certificate;\n signing_info.additional_data;\n};\n```\n\n1. `merkle_tree` is the [whole Merkle tree](https://www.kernel.org/doc/html/latest/filesystems/fsverity.html#merkle-tree) of the APK, calculated as described in the [fs-verity](https://www.kernel.org/doc/html/latest/filesystems/fsverity.html#merkle-tree) documentation.\n\n| **Note:** This field is optional, and is allowed to be missing from the signature in case when the whole APK is available for the processing tool instead. The tool would need to recalculate the tree then.\n\nProducers and consumers\n-----------------------\n\n`apksigner` Android SDK tool now generates the v4 signature file\nif you run it with default parameters. v4 signing can be disabled the same way\nas the other signing schemes. It can also verify if the v4 signature is\nvalid.\n\n`adb` expects the .apk.idsig file to be present next to the .apk when\nrunning the `adb install --incremental` command \n\nIt will also use the .idsig file to try Incremental installation by\ndefault, and will fall back to a regular installation if it's missing or\ninvalid.\n\nWhen an installation session is created, the new streaming installation API\nin the `PackageInstaller` accepts the [stripped](#stripped-def)\nv4 signature as a separate argument when adding a file to the session.\nAt this point, `signing_info` is passed into incfs as a\nwhole blob. Incfs extracts root hash from the blob.\n\nWhen the installation session is being committed, PackageManagerService does\nan ioctl to retrieve the `signing_info` blob from incfs, parses it and verifies\nthe signature.\n\nIncremental Data Loader component is expected to stream the Merkle tree part\nof the signature through the data loader native API. \n\n`package` service shell command `install-incremental`\naccepts the stripped v4 signature file encoded as base64 as a parameter for each\nadded file. The corresponding Merkle tree has to be sent into the command's\n`stdin`.\n\napk_digest\n----------\n\n`apk_digest` is the first available content digest in order:\n\n1. V3, 1MB block, SHA2-512 (CONTENT_DIGEST_CHUNKED_SHA512),\n2. V3, 4KB block, SHA2-256 (CONTENT_DIGEST_VERITY_CHUNKED_SHA256),\n3. V3, 1MB block, SHA2-256 (CONTENT_DIGEST_CHUNKED_SHA256),\n4. V2, SHA2-512,\n5. V2, SHA2-256.\n\nSee [length-prefixed\nsequence of length-prefixed signatures](/docs/security/features/apksigning/v3) in APK signature scheme v3.\n**Figure 1**: APK validation process v4\n\nValidation and testing\n----------------------\n\nValidate the implementation using Feature Unit Tests and CTS.\n\n- `CtsIncrementalInstallHostTestCases`\n - /android/cts/hostsidetests/incrementalinstall\n\n### Test the signature format\n\nTo test the signature format, [setup\na development environment](/docs/setup/build/building#initialize) and run the following manual tests: \n\n```bash\n$ atest PackageManagerShellCommandTest\n\nPackageManagerShellCommandIncrementalTest\n```\n\n### Test the signature format with Android SDK (ADB and apksigner)\n\nTo test the signature format with Android SDK, [setup a development environment](/docs/setup/build/building#initialize)\nand ensure you have completed the implementation of\n[IncFS](/docs/core/architecture/kernel/incfs).\nThen flash the build on a target physical device or emulator. You need\nto generate or obtain an existing APK and then create a [debug signing key](https://developer.android.com/studio/publish/app-signing#debug-mode).\nFinally, sign and install the apk with v4 signature format\nfrom the build-tools folder.\n\n**Sign** \n\n```bash\n$ ./apksigner sign --ks debug.keystore game.apk\n```\n\n**Install** \n\n```bash\n$ ./adb install game.apk\n```\n\n**Where can these tests be found?** \n\n```text\n/android/cts/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java\n```"]]