En esta página, se describen varios métodos para garantizar que el APK instalado en tu dispositivo Android corresponda al reclamo que se realizó en el modelo de solicitante. Esto implica extraer el APK en cuestión de tu dispositivo, verificar la integridad de su código y realizar una prueba de inclusión de registros en el artefacto extraído.
Proceso de verificación
Se implementa un registro de transparencia con un árbol Merkle que consta de hashes. Un nodo hoja contiene datos, y un nodo principal contiene el hash de sus nodos secundarios.
Básicamente, se realizan dos cálculos en el árbol de Merkle para verificar la propiedad de evidencia de manipulación de los registros de transparencia: la prueba de inclusión y la prueba de coherencia. El primero demuestra que el registro incluye una entrada correspondiente a una versión de APK en particular. La entrada de registro incluye un hash, que es el resumen SHA256 del token de firma de código en forma de un token web JSON (JWT), que se puede obtener de los APKs correspondientes. Este último demuestra que, cuando se agregan entradas nuevas al árbol, el nuevo punto de control es (criptográficamente) coherente con la versión anterior del árbol.
Para verificar un APK cubierto, realiza una prueba de prueba de inclusión basada en un punto de control presenciado. Ten en cuenta que planeamos integrar este registro con una red de testigos pública a través de un protocolo de testigos estandarizado. Esto proporcionará un punto de control certificado, lo que garantiza la coherencia del registro.
Si quieres convencerte de que el APK que tienes en tu dispositivo cumple con la afirmación que se hace en el modelo del reclamante, consulta el texto a continuación.
Prueba de inclusión
Un usuario de Android puede verificar que un APK cubierto en su dispositivo esté en el registro. Para ello, primero debe extraer el APK y sus metadatos relevantes, y, luego, comparar el hash raíz recalculado con el hash raíz que se incluye en el punto de control publicado. Si coinciden, el usuario de Android puede tener la certeza de que cuenta con algunas de las protecciones que se describen en el Modelo de amenazas.
Cómo verificar la inclusión de un APK en el registro
Como se describió anteriormente, la lista de APKs que se incluyen actualmente se encuentra en la página de descripción general.
Requisitos previos para la verificación
Antes de verificar que el APK que acabas de extraer de tu dispositivo cumpla con nuestro reclamo, deberás instalar las siguientes herramientas desde una computadora conectada a la red.
Android Debug Bridge (ADB)
ADB es una herramienta que se comunica con un dispositivo Android y está disponible en el sitio web de las Herramientas de la plataforma del SDK de Android.
AAPT2
AAPT2 (Android Asset Packaging Tool) es una herramienta de compilación que se usa para compilar y empaquetar los recursos de una app para Android. Se puede encontrar como una herramienta independiente en Android SDK Build Tools 26.0.2 y versiones posteriores.
bundletool
bundletool es una herramienta que se usa para compilar un Android App Bundle (AAB). También se puede usar para convertir un AAB en APKs que se pueden instalar en dispositivos.
Se puede descargar desde GitHub.
Verificador de prueba de inclusión
Este es un módulo de Go que publicamos en un repositorio de Git dentro del Proyecto de código abierto de Android (AOSP) llamado avb.
Puede consultar el registro de transparencia del APK de los servicios del sistema de Google y mostrar si un paquete se incluye en el registro.
En una sección posterior, se puede encontrar un ejemplo de cómo se usa.
Para descargar esta herramienta, primero debes clonar el repositorio de avb.
computer:~$ git clone https://android.googlesource.com/platform/external/avb
El código fuente del verificador se puede encontrar en tools/transparency/verify dentro del repositorio avb.
Cómo construir una carga útil para la verificación
Para verificar que el APK que extrajiste de tu dispositivo según nuestras afirmaciones, debes crear una carga útil de registro a partir de la información derivada del APK.
Antes de comenzar, asegúrate de que se pueda usar adb en tu dispositivo habilitando la depuración de adb en él.
Luego, busca dónde se instaló el APK en tu dispositivo. Para los fines de esta guía, usaremos el APK de Android System Key Verifier (com.google.android.contactkeys) como ejemplo de trabajo.
computer:~$ adb shell pm list packages -f | grep contactkeys
package:/data/app/~~i5WYSO4PuAAv798-eHdM7A==/com.google.android.contactkeys-PQCKjnn7xDqjeVhcUDibBA==/base.apk=com.google.android.contactkeys
Si el APK de Android System Key Verifier está instalado en tu dispositivo, el comando anterior devolverá una ruta de acceso que indica dónde está instalado en tu dispositivo. De lo contrario, no verás ningún resultado.
Luego, descarga el APK de tu dispositivo Android en la computadora en la que estás trabajando con este comando (ten en cuenta que la ubicación real y el nombre de archivo del APK en tu dispositivo pueden variar):
computer:~$ mkdir -p /tmp/testdir && cd /tmp/testdir
computer:/tmp/testdir$ adb pull /data/app/~~i5WYSO4PuAAv798-eHdM7A==/com.google.android.contactkeys-PQCKjnn7xDqjeVhcUDibBA==/base.apk ./contactkeys_candidate.apk
Para obtener y, de este modo, verificar el nombre del paquete del APK que acabas de descargar, primero deberás descomprimir el APK, ya que, en última instancia, un APK es un tipo especial de archivo ZIP.
computer:/tmp/testdir$ mkdir extracted && unzip contactkeys_candidate.apk -d extracted/
En este paso, se descomprimen todos los archivos que componían el APK. El nombre y la versión del paquete se pueden encontrar en el manifiesto del APK, que suele estar en un archivo llamado AndroidManifest.xml.
Sin embargo, el archivo de manifiesto obtenido está en formato binario, que no es legible para los humanos.
Para convertir el XML binario en un formato legible, usamos la herramienta aapt2 que instalamos antes (como se requiere en la sección de requisitos previos).
computer:/tmp/testdir$ aapt2 dump badging ./contactkeys_candidate.apk
package: name='com.google.android.contactkeys' versionCode='7805' versionName='1.219.791156583' platformBuildVersionName='Baklava' platformBuildVersionCode='36' compileSdkVersion='36' compileSdkVersionCodename='Baklava'
En el resultado anterior, ahora podemos confirmar que el nombre del paquete de este APK es com.google.android.contactkeys y el número de versión (versionCode) es 1413.
Ahora, buscaremos la firma de transparencia de código dentro del APK. Debe ser un archivo llamado code_transparency_signed.jwt que se encuentre dentro de la carpeta META-INF entre los demás archivos extraídos del APK.
computer:/tmp/testdir$ sha256sum extracted/META-INF/code_transparency_signed.jwt
1779a2aee029112c2c9bfc9390b9678f3e5f4595b39705e8528dd522e8042f11 code_transparency_signed.jwt
Con esta cadena hash, ahora tenemos toda la información necesaria para armar una carga útil de registro según el formato que se describe en la sección Contenido del registro. En este ejemplo, una carga útil de registro correspondiente debería verse de la siguiente manera:
1779a2aee029112c2c9bfc9390b9678f3e5f4595b39705e8528dd522e8042f11
SHA256(Signed Code Transparency JWT)
com.google.android.contactkeys
1143
También observa el carácter de nueva línea después de la versión del paquete.
Puedes guardar el contenido en un archivo, como payload.txt. Esto será útil cuando realices la prueba de inclusión más adelante.
Cómo verificar la autenticidad de la firma de código del APK
Ahora, debemos verificar la autenticidad del token de firma de código incorporado en el APK. Para ello, usamos bundletool y la clave pública del par de claves que se usó para firmarlo en primer lugar. Se publican en cada sección de los APKs respectivos. Suponiendo que guardaste el certificado de clave pública (p.ej., para Android System Key Verifier) en un archivo llamado signing_cert_pubkey.pem, sigue la siguiente guía para realizar la verificación de la firma de código.
Primero, debes crear un archivo ZIP y agregar el APK candidato a él.
computer:/tmp/testdir$ zip -u test.zip contactkeys_candidate.apk
zip warning: test.zip not found or empty
adding: contactkeys_candidate.apk (deflated 58%)
computer:/tmp/testdir$ file test.zip
test.zip: Zip archive data, at least v2.0 to extract, compression method=deflate
Ahora, podemos usar el comando check-transparency de bundletool para verificar si la firma de código integrada en el APK candidato coincide con la que se publicó.
computer:/tmp/testdir$ java -jar BUNDLETOOL_INSTALL_PATH/bundletool-all-version.jar check-transparency \
--mode=apk \
--apk-zip=test.zip \
--transparency-key-certificate=signing_cert_pubkey.pem
APK signature is valid. SHA-256 fingerprint of the apk signing key certificate (must be compared with the developer's public key manually): D9 E1 73 5B 2A 39 51 27 3A 87 35 B7 66 9E F1 9E F5 3A F1 C1 27 5C BA 31 39 3C 18 40 8B 03 79 D0
Code transparency signature verified for the provided code transparency key certificate.
Code transparency verified: code related file contents match the code transparency file.
Debes asegurarte de que el resultado del comando anterior indique que se verificaron tanto la firma de transparencia del código como la transparencia del código.
Si no es así, por ejemplo, si ves un resultado como Code transparency verification failed because the provided public key
certificate does not match the transparency file, significa que la integridad del código del APK en cuestión podría estar comprometida y no debes confiar en él.
Recuerda verificar que los estés comparando con el certificado de clave pública correcto.
De lo contrario, si todo lo demás está bien, esto significa que se verificó la autenticidad de la firma de código del APK que estás validando.
Verificación de la inclusión del paquete (prueba de inclusión)
Con la carga útil que creaste anteriormente, ya puedes probar si el paquete en cuestión se incluyó en el registro de transparencia.
Se publicó una herramienta de prueba de inclusión en el repositorio de avb dentro del Proyecto de código abierto de Android. Para ejecutarlo, haz lo siguiente:
computer:external/avb/tools/transparency/verify$ PAYLOAD_PATH=PATH_TO_PAYLOAD_DIR/payload.txt
computer:external/avb/tools/transparency/verify$ go build cmd/verifier/verifier.go
computer:external/avb/tools/transparency/verify$ ./verifier --payload_path=${PAYLOAD_PATH} --log_type=google_system_apk
El verificador usa el punto de control correspondiente y el contenido del registro (que se encuentra en el directorio de mosaicos) para comprobar que la carga útil del APK esté en el registro de transparencia, lo que verifica que Google lo publicó.
El resultado del comando se escribe en stdout:
OK. inclusion check success!si el código del paquete se incluye en el registroFAILUREsi no lo es.