τTau SolutionsHerramientas

Firma y empaquetado

panorama · Revisado el 12 de agosto de 2026

1. Qué es y por qué existe

Android no instala un APK sin firma. No es una recomendación: es el mecanismo por el que el sistema decide si una actualización viene de quien publicó la versión anterior, y por el que dos aplicaciones pueden compartir permisos o identidad de usuario. Un APK sin firmar, o con la firma rota, se rechaza en el instalador con un error genérico que no dice cuál de las dos cosas ha pasado.

Cualquier herramienta de los documentos anteriores produce APK sin firma. apktool no firma; APKEditor no firma, por diseño; zipalign destruye la firma que hubiera. El ciclo no se cierra hasta este documento.

Aquí está solo el uso: qué herramienta, con qué opciones y en qué orden. El porqué estructural —qué cubre cada esquema, cómo está construido el APK Signing Block, por qué la alineación existe— está en el bloque 20-firma, y en particular en Alineación y zipalign.

2. El orden del pipeline, que no es negociable

┌─────────────────┐
│ 1. construir    │  apktool b · APKEditor build · APKEditor merge
└────────┬────────┘
         ▼
┌─────────────────┐
│ 2. alinear      │  zipalign -p -f 4  ó  -P 16
└────────┬────────┘
         ▼
┌─────────────────┐
│ 3. FIRMAR       │  apksigner sign
└────────┬────────┘
         ▼
┌─────────────────┐
│ 4. verificar    │  apksigner verify
└────────┬────────┘
         ▼
┌─────────────────┐
│ 5. instalar     │  adb install · adb install-multiple
└─────────────────┘

zipalign va antes de apksigner. Siempre. La documentación oficial de zipalign lo dice con todas las letras: con apksigner, alinear antes de firmar; cualquier cambio posterior a la firma la invalida. Solo con el jarsigner antiguo —que no se recomienda— el orden es el contrario.

Esto no es teoría. Se puede comprobar, y la sección 8 lo comprueba con salida real.

3. apksigner

La herramienta oficial de firma y verificación de las build-tools. Está instalada, así que todo lo de esta sección está ejecutado de verdad.

BT=~/Library/Android/sdk/build-tools/37.0.0
$BT/apksigner version
0.9

Cuatro comandos: sign, verify, rotate y lineage.

3.1 verify: leer una firma ajena

Es la orden más útil del documento, porque no requiere claves. Sobre el base.apk de Google Keep del corpus, extraído de su .xapk:

BT=~/Library/Android/sdk/build-tools/37.0.0
$BT/apksigner verify --verbose --print-certs keep/com.google.android.keep.apk
Verifies
Verified using v1 scheme (JAR signing): false
Verified using v2 scheme (APK Signature Scheme v2): false
Verified using v3 scheme (APK Signature Scheme v3): true
Verified using v3.1 scheme (APK Signature Scheme v3.1): true
Verified using v3.2 scheme (APK Signature Scheme v3.2): false
Verified using v4 scheme (APK Signature Scheme v4): false
Verified for SourceStamp: true
Number of signers: 1
V3.1 Signer: (minSdkVersion=33, maxSdkVersion=2147483647) certificate DN: CN=Android, OU=Android, O=Google Inc., L=Mountain View, ST=California, C=US
V3.1 Signer: (minSdkVersion=33, maxSdkVersion=2147483647) certificate SHA-256 digest: 7ce83c1b71f3d572fed04c8d40c5cb10ff75e6d87d9df6fbd53f0468c2905053
V3.1 Signer: (minSdkVersion=33, maxSdkVersion=2147483647) key algorithm: RSA
V3.1 Signer: (minSdkVersion=33, maxSdkVersion=2147483647) key size (bits): 4096
V3.0 Signer: (minSdkVersion=24, maxSdkVersion=32) certificate DN: CN=Android, OU=Android, O=Google Inc., L=Mountain View, ST=California, C=US
V3.0 Signer: (minSdkVersion=24, maxSdkVersion=32) certificate SHA-256 digest: f0fd6c5b410f25cb25c3b53346c8972fae30f8ee7411df910480ad6b2d60db83
V3.0 Signer: (minSdkVersion=24, maxSdkVersion=32) key algorithm: RSA
V3.0 Signer: (minSdkVersion=24, maxSdkVersion=32) key size (bits): 2048
Source Stamp Signer: certificate DN: CN=Android, OU=Android, O=Google Inc., L=Mountain View, ST=California, C=US
Source Stamp Signer: certificate SHA-256 digest: 3257d599a49d2c961a471ca9843f59d341a405884583fc087df4237b733bbd6d

Salida recortada; se han quitado los digests SHA-1 y MD5 y las huellas de clave pública.

Este volcado enseña la firma moderna entera de un vistazo:

  • v3.1 con segmentación por SDK. Hay dos firmantes v3 distintos con rangos disjuntos: API 24-32 con una clave RSA de 2048 bits, y API 33 en adelante con una de 4096. Es rotación de clave desplegada en producción: los dispositivos antiguos siguen validando con la clave vieja y los nuevos con la nueva.
  • Sin v1 y sin v2. Google ya no las incluye. Con minSdkVersion 24, v3 basta.
  • Source stamp presente, con su propio certificado: acredita el origen con independencia de la firma de distribución.

3.2 sign: firmar de verdad

Pipeline completo ejecutado sobre org.fossify.calculator_1.4.0.apk del corpus, con el keystore creado en la sección 4:

BT=~/Library/Android/sdk/build-tools/37.0.0
$BT/zipalign -p -f 4 demo-in.apk demo-aligned.apk

$BT/apksigner sign --ks demo.p12 --ks-type PKCS12 --ks-key-alias pruebas-demo \
  --ks-pass pass:demopass --key-pass pass:demopass \
  --min-sdk-version 24 --max-sdk-version 35 \
  --v1-signing-enabled true --v2-signing-enabled true \
  --v3-signing-enabled true --v4-signing-enabled true \
  --out demo-signed.apk demo-aligned.apk

Sin salida y con código 0. Produce dos ficheros:

-rw-r--r--  1 jj  wheel  7176568  demo-signed.apk
-rw-r--r--  1 jj  wheel    62953  demo-signed.apk.idsig

El .idsig es la firma v4, y viaja al lado del APK, no dentro. Si se pierde, se pierde la firma v4 y con ella la instalación incremental.

Las opciones que importan:

Opción Para qué
--ks <fichero> El keystore
--ks-key-alias <alias> Qué clave del keystore usar. Obligatorio si hay más de una
--ks-pass <formato> Contraseña del keystore: pass:, env:, file:, stdin
--key-pass <formato> Contraseña de la clave privada, si difiere
--ks-type <tipo> PKCS12, JKS
--key / --cert Alternativa al keystore: clave PKCS#8 DER y certificado X.509 sueltos
--min-sdk-version <n> Determina qué esquemas hacen falta. Ver sección 3.3
--max-sdk-version <n> Límite superior del rango a cubrir
--v1-signing-enabled <bool> Firma JAR
--v2-signing-enabled <bool> Esquema v2
--v3-signing-enabled <bool> Esquema v3
--v4-signing-enabled <true|false|only> Esquema v4; genera el .idsig. only produce solo el .idsig
--rotation-min-sdk-version <n> Desde qué API se usa la clave rotada
--next-signer Separa las opciones de un segundo firmante
--v1-signer-name <base> Nombre base de los ficheros de firma v1
--out <fichero> Salida. Sin él, firma en el sitio
-v, --verbose Detalle

Nunca --ks-pass pass:... fuera de una demostración. La contraseña queda en el historial del shell y en la tabla de procesos. En cualquier uso real, env: o file:.

3.3 La sutileza de verify que engaña a todo el mundo

El APK recién firmado, verificado:

$BT/apksigner verify --verbose --min-sdk-version 24 demo-signed.apk
Verifies
Verified using v1 scheme (JAR signing): false
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): true
Verified using v3.1 scheme (APK Signature Scheme v3.1): false
Verified using v3.2 scheme (APK Signature Scheme v3.2): false
Verified using v4 scheme (APK Signature Scheme v4): false
Verified for SourceStamp: false
Number of signers: 1

Se pidió v1 y dice false. Se pidió v4 y dice false. ¿Se ignoraron los flags? No. Los dos false tienen causas distintas y ninguna es un fallo.

v1: está, pero no se usa en ese rango de API. Los ficheros están físicamente dentro:

unzip -l demo-signed.apk | grep -E "META-INF/(MANIFEST\.MF|[A-Z0-9_-]+\.(SF|RSA))"
   156212  01-01-1981 01:01   META-INF/PRUEBAS-.SF
     1304  01-01-1981 01:01   META-INF/PRUEBAS-.RSA
   156085  01-01-1981 01:01   META-INF/MANIFEST.MF

Y verificando en un rango de API donde v1 sí es necesaria:

$BT/apksigner verify --verbose --min-sdk-version 21 --max-sdk-version 23 demo-signed.apk
Verifies
Verified using v1 scheme (JAR signing): true
Verified using v2 scheme (APK Signature Scheme v2): false
Verified using v3 scheme (APK Signature Scheme v3): false
...

La regla: apksigner verify no responde «¿está presente este esquema?» sino «¿se usó este esquema para verificar en el rango de API que me has dado?». Con --min-sdk-version 24, Android prefiere v2/v3 y v1 ni se mira. Con 21-23, solo existe v1 y es la que se usa.

Quien lea esa salida como un inventario de esquemas presentes va a informar mal. Para saber qué hay dentro, se mira el ZIP y el APK Signing Block.

v4: hay que pasarle el .idsig explícitamente.

$BT/apksigner verify --verbose --min-sdk-version 24 \
  --v4-signature-file demo-signed.apk.idsig demo-signed.apk
Verifies
Verified using v1 scheme (JAR signing): false
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): true
Verified using v3.1 scheme (APK Signature Scheme v3.1): false
Verified using v3.2 scheme (APK Signature Scheme v3.2): false
Verified using v4 scheme (APK Signature Scheme v4): true
Verified for SourceStamp: false
Number of signers: 1

Ahora sí. La firma v4 estaba correcta desde el principio; el verificador no la buscaba.

Opciones de verify:

Opción Efecto
--print-certs Certificados: DN, digests SHA-256/SHA-1/MD5, algoritmo y tamaño de clave
--print-certs-pem Además, el PEM por stdout
--min-sdk-version / --max-sdk-version El rango a comprobar. Cambia el veredicto
--v4-signature-file <fichero> El .idsig
-v, --verbose Desglose por esquema
-Werr Los avisos cuentan como error

3.4 Por qué firmar solo en v1 hoy es no firmar

Firmando el mismo APK únicamente con v1:

$BT/apksigner sign --ks demo.p12 --ks-key-alias pruebas-demo \
  --ks-pass pass:demopass --key-pass pass:demopass --min-sdk-version 21 \
  --v1-signing-enabled true --v2-signing-enabled false \
  --v3-signing-enabled false --v4-signing-enabled false \
  --out demo-v1.apk demo-aligned.apk

$BT/apksigner verify --verbose demo-v1.apk
DOES NOT VERIFY
ERROR: Target SDK version 36 requires a minimum of signature scheme v2; the APK is not signed with this or a later signature scheme
WARNING: META-INF/com/android/build/gradle/app-metadata.properties not protected by signature. Unauthorized modifications to this JAR entry will not be detected. Delete or move the entry outside of META-INF/.
WARNING: META-INF/version-control-info.textproto not protected by signature. Unauthorized modifications to this JAR entry will not be detected. Delete or move the entry outside of META-INF/.

La aplicación declara targetSdkVersion 36, y con ese target Android exige v2 como mínimo. La firma v1 es válida criptográficamente y aun así el APK no se instala.

Esta salida es la evidencia directa de un hallazgo del censo de las trece herramientas: cuatro de las trece firman solo en v1, y sus APK no se instalan en Android 11 o superior con targetSdk moderno. La herramienta parece funcionar hasta el último paso.

Los WARNING son la otra lección de v1: la firma JAR no cubre las entradas de META-INF/, así que cualquiera puede modificarlas sin invalidarla. Es la debilidad estructural que motivó v2.

3.5 rotate y lineage

Rotar la clave de firma sin perder la identidad de la aplicación. rotate construye el fichero de lineage que acredita la sucesión:

apksigner rotate --in lineage-anterior --out lineage-nuevo \
  --old-signer --ks clave-vieja.jks \
  --new-signer --ks clave-nueva.jks

Y al firmar se aporta el linaje:

apksigner sign --ks clave-vieja.jks \
  --next-signer --ks clave-nueva.jks \
  --lineage lineage-nuevo --rotation-min-sdk-version 28 app.apk

lineage inspecciona y edita un linaje existente.

⚠️ No ejecutado localmente: rotate y lineage requieren dos keystores con una relación de sucesión real, que no se ha construido en esta revisión. La sintaxis procede de la documentación oficial de apksigner, consultada el 12 de agosto de 2026. La salida de la sección 3.1 muestra un linaje desplegado de verdad, el de Google Keep.

El mecanismo y el formato del linaje están en Firma v4 y verificación.

4. keytool

Viene con el JDK. Está disponible (OpenJDK 21.0.10), así que esta sección también está ejecutada.

4.1 Crear un keystore PKCS#12

PKCS#12 es el formato actual; JKS es el heredado y Java avisa al usarlo.

keytool -genkeypair -v -keystore demo.p12 -storetype PKCS12 -alias pruebas-demo \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -dname "CN=Ejemplo Demo, OU=Docs, O=Ejemplo, L=Madrid, C=ES" \
  -storepass demopass -keypass demopass
Generando par de claves RSA de 2.048 bits para certificado autofirmado (SHA384withRSA) con una validez de 10.000 días
	para: CN=Ejemplo Demo, OU=Docs, O=Ejemplo, L=Madrid, C=ES
[Almacenando demo.p12]

La salida sale en español porque el JDK respeta el locale del sistema. Conviene saberlo antes de escribir un script que analice esta salida: no lo hagas.

-validity 10000 son unos 27 años. Google Play exige que el certificado siga siendo válido bastante más allá del final de vida previsto de la aplicación; el valor de 10.000 días es la convención heredada de la documentación de Android.

4.2 Listar el keystore

keytool -list -v -keystore demo.p12 -storepass demopass
Tipo de Almacén de Claves: PKCS12
Proveedor de Almacén de Claves: SUN

Su almacén de claves contiene 1 entrada

Nombre de Alias: pruebas-demo
Fecha de Creación: 12 ago 2026
Tipo de Entrada: PrivateKeyEntry
Longitud de la Cadena de Certificado: 1
Certificado[1]:
Propietario: CN=Ejemplo Demo, OU=Docs, O=Ejemplo, L=Madrid, C=ES
Emisor: CN=Ejemplo Demo, OU=Docs, O=Ejemplo, L=Madrid, C=ES
Número de serie: e8251338a7c3fb45
Válido desde: Wed Aug 12 12:31:43 CEST 2026 hasta: Sun Dec 28 11:31:43 CET 2053
Huellas digitales del certificado:
	 SHA1: 8F:B6:F0:35:AA:FE:12:EE:E3:32:49:EC:6C:B2:BA:A4:2F:71:E1:5C
	 SHA256: FE:9D:A8:50:02:E2:8D:F0:C5:40:16:4B:22:64:88:70:E0:92:99:58:63:F3:1C:50:BB:FE:4C:8B:AA:D0:EF:CC
Nombre del algoritmo de firma: SHA384withRSA
Algoritmo de clave pública de asunto: Clave RSA de 2048 bits
Versión: 3

Propietario y Emisor coinciden: es autofirmado, que es lo normal para firmar aplicaciones Android. El SHA-256 del certificado es la identidad de la aplicación a efectos de actualizaciones, y es el valor que hay que registrar en las consolas de servicios de terceros.

4.3 Exportar el certificado

keytool -exportcert -keystore demo.p12 -alias pruebas-demo \
  -storepass demopass -rfc -file pruebas-demo.pem

Sin -rfc sale en DER binario. El PEM es lo que piden las consolas de Firebase, Google Maps y similares.

4.4 El debug keystore

Android Studio crea un keystore de depuración con valores conocidos y públicos:

Elemento Valor
Ruta (macOS y Linux) ~/.android/debug.keystore
Ruta (Windows) %USERPROFILE%\.android\debug.keystore
Contraseña del keystore android
Alias androiddebugkey
Contraseña de la clave android
keytool -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore

La documentación de Google Play services confirma la ruta, la contraseña android y el alias androiddebugkey. ⚠️ sin verificar: esa página documenta la contraseña del keystore pero no menciona una contraseña distinta para la clave. El valor android para la clave es la convención universalmente asumida y la que usan las herramientas, pero no se ha localizado una fuente oficial que lo declare explícitamente.

Por qué no vale para distribuir. La documentación oficial de firma de aplicaciones lo dice directamente: el certificado de depuración lo generan las herramientas de compilación y es inseguro por diseño, y por eso la mayoría de las tiendas, incluida Google Play, no aceptan aplicaciones firmadas con él. La razón de fondo es que la clave privada es pública: cualquiera puede firmar una actualización de una aplicación firmada con el debug keystore, que es exactamente lo que la firma debía impedir.

Sirve para desarrollo, para pruebas locales y para reinstalar sobre uno mismo. Nada más.

5. zipalign

Instalado, así que ejecutado.

Alinear al escribir:

BT=~/Library/Android/sdk/build-tools/37.0.0
$BT/zipalign -p -f 4 entrada.apk salida.apk

Comprobar sin modificar:

CORPUS=~/corpus-apk
$BT/zipalign -c -v 4 $CORPUS/com.termux_1002.apk | head -8
Verifying alignment of ~/corpus-apk/com.termux_1002.apk (4)...
      87 META-INF/com/android/build/gradle/app-metadata.properties (OK - compressed)
     179 classes.dex (OK - compressed)
 1378689 lib/arm64-v8a/libtermux-bootstrap.so (OK - compressed)
30080690 lib/arm64-v8a/libtermux.so (OK - compressed)
30084061 lib/armeabi-v7a/libtermux-bootstrap.so (OK - compressed)
55930307 lib/armeabi-v7a/libtermux.so (OK - compressed)
55933390 lib/x86/libtermux-bootstrap.so (OK - compressed)

(OK - compressed) significa que la entrada va comprimida y por tanto la alineación no le aplica: solo importa para las entradas stored, que son las que el sistema mapea en memoria. Este APK comprime sus .so, lo que implica que declara extractNativeLibs="true".

Comprobación de páginas de 16 KB, que es el requisito nuevo:

$BT/zipalign -c -P 16 4 $CORPUS/org.videolan.vlc_13070108.apk; echo "exit=$?"
exit=0

Opciones:

Opción Efecto
-c Solo comprueba, no modifica
-f Sobrescribe la salida si existe
-p Alinea los .so sin comprimir a páginas de 4 KiB. Obsoleto: usar -P 16
-P <kb> Alinea los .so a páginas de ese tamaño. Valores válidos: 4, 16, 64
-v Detalle entrada a entrada
-z Recomprime con Zopfli
(alineación) Argumento obligatorio. Siempre 4

Desde el 1 de febrero de 2027 Google Play no admite actualizaciones sin soporte de páginas de 16 KB, así que -P 16 deja de ser opcional. El porqué está en Alineación y zipalign y en Código nativo y ELF.

6. uber-apk-signer

Dato Valor
Repositorio https://github.com/patrickfav/uber-apk-signer
Licencia Apache-2.0
Última versión v1.3.0, publicada el 16 de febrero de 2023
Último push 30 de octubre de 2023
Tracción 2.703 ★ · 264 forks · 11 issues abiertas
Archivado No

Consultado el 12 de agosto de 2026 vía la API de GitHub. Estado real: sin mantenimiento activo. Tres años y medio sin release, casi tres sin commits. No está archivado, pero no se mueve.

Qué automatiza: encadena zipalign + apksigner + verificación en una sola invocación, sobre uno o muchos APK, con el debug keystore por defecto si no se le da otro.

java -jar uber-apk-signer.jar --apks /ruta/con/apks/
java -jar uber-apk-signer.jar -a app.apk --ks release.jks \
  --ksAlias mialias --ksPass ... --ksKeyPass ...

⚠️ No ejecutado localmente: uber-apk-signer no está instalado y estas reglas prohíben descargar JAR de herramientas. La sintaxis procede de la descripción oficial del proyecto, consultada el 12 de agosto de 2026.

Cuándo compensa: cuando hay que firmar muchos APK de golpe, o cuando se quiere una sola orden en un script en lugar de tres. Es lo que usan APKLab y Apk Studio internamente, y por eso la salida de APKLab reporta «sign success / zipalign verified / signature verified [v1, v2, v3]» en un solo paso.

Cuándo no: en cualquier flujo nuevo. Es una capa de conveniencia sin mantenimiento sobre dos herramientas oficiales que sí lo tienen y que resuelven el problema en dos líneas. Y como congela su propia noción de qué esquemas hay que aplicar, envejece igual que envejecieron las interfaces gráficas del apartado anterior.

7. Instalar

ADB=~/Library/Android/sdk/platform-tools/adb

# Un APK único
$ADB install -r demo-signed.apk

# Un conjunto de splits, sin fusionarlos
$ADB install-multiple base.apk config.arm64_v8a.apk config.es.apk config.xxhdpi.apk

# Desde un APK Set, dejando que bundletool elija
java -jar bundletool.jar install-apks --apks=fixture.apks

⚠️ No ejecutado localmente: no hay ningún dispositivo Android conectado al entorno de referencia, y adb existe en ~/Library/Android/sdk/platform-tools/adb pero no está en el PATH. Ninguna de estas tres órdenes se ha ejecutado.

Lo que se ejecutó, y confirma la dependencia:

java -jar bundletool.jar get-device-spec --output=devspec.json
[BT:1.18.3] Error: Unable to determine the location of ADB. Please set the --adb flag or define ANDROID_HOME or PATH environment variable.

Tres notas que ahorran tiempo:

  • install-multiple es la vía para splits sin fusionarlos. Todos los APK del conjunto deben compartir packageName y versionCode y estar firmados con la misma clave; si no, la instalación falla entera.
  • install -r reinstala conservando los datos, y solo funciona si la firma coincide con la de la versión instalada. Un APK refirmado con otra clave exige desinstalar primero.
  • bundletool install-apks hace get-device-spec, extract-apks e install-multiple en un paso.

El catálogo de errores de instalación —INSTALL_PARSE_FAILED_NO_CERTIFICATES, INSTALL_FAILED_UPDATE_INCOMPATIBLE, INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES— está en Diagnóstico de fallos.

8. Qué se rompe si se altera el orden

La comprobación, ejecutada. El APK de partida es org.fossify.calculator_1.4.0.apk del corpus, que viene firmado en v2:

$BT/apksigner verify --verbose demo-in.apk | head -4
Verifies
Verified using v1 scheme (JAR signing): false
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): false

Se le pasa zipalign después de estar firmado, que es el error:

$BT/zipalign -p -f 4 demo-in.apk demo-aligned.apk
$BT/apksigner verify --verbose demo-aligned.apk
DOES NOT VERIFY
ERROR: Missing META-INF/MANIFEST.MF

La firma ha desaparecido. zipalign reescribe el ZIP entrada por entrada para colocarlas en sus offsets, y en ese proceso no conserva el APK Signing Block, que es donde vivía la firma v2. Como este APK tampoco tenía v1, no queda nada — y de ahí que el error mencione META-INF/MANIFEST.MF, que es lo primero que el verificador busca cuando no encuentra bloque de firma.

Orden Resultado
construir → alinear → firmar Correcto
construir → firmar → alinear Firma destruida. Hay que volver a firmar
construir → firmar → editar un fichero Firma inválida
alinear → firmar → zipalign -c Correcto: -c solo lee

El corolario práctico: zipalign -c es seguro siempre; zipalign sin -c sobre un APK firmado obliga a refirmar.

Y el corolario de diseño, que es más profundo: cualquier herramienta que reescriba el ZIP —apktool, APKEditor o la que sea— invalida la firma por construcción. No es un fallo que corregir, es la propiedad que hace útil a la firma.

Fuentes

  1. apksigner — documentación oficial de Android — https://developer.android.com/tools/apksigner Consultado el 12 de agosto de 2026. De aquí salen las tablas de opciones de sign y verify de las secciones 3.2 y 3.3, y la sintaxis de rotate y lineage de la sección 3.5.
  2. zipalign — documentación oficial de Android — https://developer.android.com/tools/zipalign Consultado el 12 de agosto de 2026. De aquí salen la tabla de opciones de la sección 5 y la regla de orden de la sección 2: con apksigner, alinear antes de firmar; con jarsigner, después.
  3. bundletool — documentación oficial de Android — https://developer.android.com/tools/bundletool Consultado el 12 de agosto de 2026. De aquí sale la sintaxis de install-apks de la sección 7.
  4. Sign your app — documentación oficial de Android Studio — https://developer.android.com/studio/publish/app-signing Consultado el 12 de agosto de 2026. De aquí salen la ruta $HOME/.android/debug.keystore y la afirmación literal de que el certificado de depuración es inseguro por diseño y que las tiendas, incluida Google Play, no aceptan aplicaciones firmadas con él.
  5. Client authentication — Google Play services — https://developers.google.com/android/guides/client-auth Consultado el 12 de agosto de 2026. De aquí salen la contraseña android del debug keystore, el alias androiddebugkey, las rutas en macOS/Linux y Windows, y la orden de keytool para listarlo.
  6. uber-apk-signer — repositorio oficial — https://github.com/patrickfav/uber-apk-signer Consultado el 12 de agosto de 2026 vía la API de GitHub y /releases/latest. De aquí salen la licencia Apache-2.0, la versión v1.3.0 del 16 de febrero de 2023, el último push del 30 de octubre de 2023 y los recuentos de la sección 6.
  7. Ejecuciones locales sobre el corpus — realizadas el 12 de agosto de 2026 con build-tools 37.0.0 (apksigner 0.9, zipalign, aapt2), OpenJDK 21.0.10 (keytool) y bundletool 1.18.3, sobre macOS Darwin 25.5.0. De aquí salen todas las salidas pegadas de las secciones 3.1 a 3.4, 4.1, 4.2, 5, 7 y 8, ejecutadas contra GoogleKeep_com.google.android.keep.xapk, org.fossify.calculator_1.4.0.apk, com.termux_1002.apk y org.videolan.vlc_13070108.apk del corpus.
  8. Censo de las trece herramientas de manipulación de APK — el inventario de Comparativa y selección, sección 4.3. De aquí sale el reparto de esquemas de firma del lote —cuántas firman con esquema moderno, cuántas solo con v1 y cuántas no firman— que la sección 3.4 comprueba experimentalmente.
  9. Documentos de este corpusAlineación y zipalign. De aquí sale la fecha del 1 de febrero de 2027 para el requisito de páginas de 16 KB de la sección 5, verificada allí contra la documentación oficial de Android.