Esquema de firma de APK v4

Android 11 admite un esquema de firma compatible con la transmisión con el APK Esquema de firma v4. La firma v4 se basa en el árbol hash de Merkle. para calcular sobre todos los bytes del APK. Sigue la estructura del árbol de hash fs-verity de manera exacta (por ejemplo, sin relleno cero). la sal y el relleno cero). Android 11 almacena la firma en un archivo separado, <apk name>.apk.idsigUna firma v4 requiere una firma complementaria v2 o v3.

Formato de archivo

Todos los campos numéricos están en formato de tipo endian. Todos los campos ocupan exactamente el número de bytes como su sizeof(), sin relleno implícito ni alineación agregada.

A continuación, se incluye una struct auxiliar para simplificar las definiciones.

template <class SizeT>
struct sized_bytes {
        SizeT size;
        byte bytes[size];
};

Contenido del archivo principal:

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 es los parámetros que se usan para el árbol de hash generación + el hash raíz:

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 es la siguiente struct:

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 se toma del bloque de firma v3 del APK o, si no es así, presente, del bloque v2 (consulta apk_digest)

Para crear y verificar un código signature, se debe serializar los siguientes datos al BLOB binario y pasarlos al el algoritmo de firma o verificación como los datos firmados:

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 es el árbol completo de Merkle del APK, calculado como se describe en la documentación de fs-verity.

Productores y consumidores

La herramienta del SDK de Android apksigner ahora genera el archivo de firma v4 si lo ejecutas con parámetros predeterminados. La firma v4 se puede inhabilitar de la misma manera que los otros esquemas de firma. También puede verificar si la firma v4 está válido.

adb espera que el archivo .apk.idsig esté presente junto al .apk cuando ejecutando el comando adb install --incremental
También usará el archivo .idsig para probar la instalación incremental. predeterminada y recurrirá a una instalación normal si falta o no válido.

Cuando se crea una sesión de instalación, la nueva API de instalación de transmisión En PackageInstaller, se aceptan los atributos extraídos firma v4 como argumento independiente cuando se agrega un archivo a la sesión. En este punto, signing_info se pasa a incfs como un un BLOB completo. Incfs extrae el hash raíz del BLOB.

Cuando se confirma la sesión de instalación, PackageManagerService un ioctl para recuperar el blob de signing_info de incfs, lo analiza y lo verifica la firma.

Se espera que el componente Incremental Data Loader transmita la parte del árbol de Merkle. de la firma mediante la API nativa del cargador de datos.
Comando install-incremental del shell del servicio package acepta el archivo de firma v4 codificado como base64 como parámetro para cada archivo agregado. El árbol de Merkle correspondiente se debe enviar al archivo de stdin

resumen_apk

apk_digest es el primer resumen de contenido disponible en el siguiente orden:

  1. V3, bloque de 1 MB, SHA2-512 (CONTENT_DIGEST_CHUNKED_SHA512),
  2. V3, bloque de 4 Kb, SHA2-256 (CONTENT_DIGEST_VERITY_CHUNKED_SHA256),
  3. V3, bloque de 1 MB, SHA2-256 (CONTENT_DIGEST_CHUNKED_SHA256),
  4. V2, SHA2-512 y
  5. V2 y SHA2-256.

Consulta las tablas con prefijos de firmas con prefijo de longitud en el esquema de firmas de APK v3.

Proceso de validación de APK v4
Figura 1: Proceso de validación de APK v4

Validación y prueba

Valida la implementación con pruebas de unidades de funciones y CTS.

  • CtsIncrementalInstallHostTestCases
    • /android/cts/hostsidetests/incrementalinstall

Prueba el formato de la firma

Para probar el formato de la firma, configura un entorno de desarrollo y ejecuta las siguientes pruebas manuales:

$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest

Cómo probar el formato de firma con el SDK de Android (ADB y apksigner)

Para probar el formato de firma con el SDK de Android, configura un entorno de desarrollo. y asegúrate de haber completado la implementación IncFS: Luego, escribe la compilación en la memoria flash en un emulador o dispositivo físico de destino. Necesitas para generar u obtener un APK existente y, luego, crear una clave de firma de depuración. Por último, firma e instala el APK con el formato de firma v4 desde la carpeta build-tools.

Firma

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

Instalar

$ ./adb install game.apk

¿Dónde se pueden encontrar estas pruebas?

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