Android 11 поддерживает схему подписи, совместимую с потоковой передачей, — схему подписи APK v4. Подпись v4 основана на хеш-дереве Меркла, вычисленном по всем байтам APK. Схема точно следует структуре хеш-дерева fs-verity (например, заполняет соль нулями и последний блок нулями). 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 берется из блока подписи версии 3 APK. Если этот блок отсутствует, он берется из блока версии 2 (см. apk_digest ).
Для создания и проверки кода signature необходимо сериализовать следующие данные в двоичный блок и передать его в алгоритм подписи и проверки в качестве подписанных данных :
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-файла, вычисленное в соответствии с описанием в документации fs-verity .
Производители и потребители
Инструмент apksigner для Android SDK генерирует файл подписи v4, если запустить его с параметрами по умолчанию. Вы можете отключить подпись v4 так же, как и другие схемы подписи. Инструмент также может проверить, действительна ли подпись v4.
При выполнении команды adb install --incremental adb ожидает наличия файла .apk.idsig рядом с APK-файлом. По умолчанию adb использует файл IDSIG для попытки инкрементной установки, а если он отсутствует или недействителен, переходит к обычной установке.
При создании сеанса установки новый API потоковой установки в PackageInstaller принимает урезанную подпись версии 4 в качестве отдельного аргумента при добавлении файла в сеанс. На этом этапе signing_info передается в IncFS как целый блок данных. IncFS извлекает корневой хеш из этого блока.
При фиксации сеанса установки PackageManagerService выполняет вызов ioctl для получения двоичных данных signing_info из IncFS, анализирует их и проверяет подпись.
Компонент Incremental Data Loader передает часть подписи, содержащую дерево Меркла, через собственный API загрузчика данных. Команда оболочки package service install-incremental принимает в качестве параметра для каждого добавляемого файла усеченный файл подписи v4, закодированный в Base64. Соответствующее дерево Меркла должно быть передано в stdin команды.
apk_digest
apk_digest — это первый доступный дайджест контента в порядке следования:
- V3, блок 1 МБ, SHA2-512 (
CONTENT_DIGEST_CHUNKED_SHA512) - V3, блок 4 КБ, SHA2-256 (
CONTENT_DIGEST_VERITY_CHUNKED_SHA256) - V3, блок 1 МБ, SHA2-256 (
CONTENT_DIGEST_CHUNKED_SHA256) - V2, SHA2-512
- V2, SHA2-256
См. последовательность подписантов с префиксом длины в схеме подписи APK версии 3.
Проверка и тестирование
Процесс проверки APK-файлов версии 4 показан на следующем рисунке:

Рисунок 1. Процесс проверки APK версии 4.
Проверьте реализацию с помощью модульных тестов и CTS:
-
CtsIncrementalInstallHostTestCases -
/android/cts/hostsidetests/incrementalinstall
Проверьте формат подписи.
Для проверки формата подписи настройте среду сборки и выполните следующие ручные тесты:
$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest
Проверьте формат подписи с помощью Android SDK (ADB и apksigner).
Используйте этот процесс для проверки формата подписи с помощью Android SDK:
- Настройте среду сборки и убедитесь, что внедрение IncFS завершено.
- Прошейте сборку на целевое физическое устройство или эмулятор.
- Сгенерируйте или получите существующий APK-файл, а затем создайте отладочный ключ подписи .
- Подпишите и установите 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