Firma y empaquetado
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 verifyno 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 sí 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 sí 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-multiplees la vía para splits sin fusionarlos. Todos losAPKdel conjunto deben compartirpackageNameyversionCodey estar firmados con la misma clave; si no, la instalación falla entera.install -rreinstala conservando los datos, y solo funciona si la firma coincide con la de la versión instalada. UnAPKrefirmado con otra clave exige desinstalar primero.bundletool install-apkshaceget-device-spec,extract-apkseinstall-multipleen 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
- 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
signyverifyde las secciones 3.2 y 3.3, y la sintaxis derotateylineagede la sección 3.5. - 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; conjarsigner, después. - 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-apksde la sección 7. - 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.keystorey 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. - 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
androiddel debug keystore, el aliasandroiddebugkey, las rutas en macOS/Linux y Windows, y la orden dekeytoolpara listarlo. - 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. - Ejecuciones locales sobre el corpus — realizadas el 12 de agosto de 2026 con
build-tools37.0.0 (apksigner0.9,zipalign,aapt2), OpenJDK 21.0.10 (keytool) ybundletool1.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 contraGoogleKeep_com.google.android.keep.xapk,org.fossify.calculator_1.4.0.apk,com.termux_1002.apkyorg.videolan.vlc_13070108.apkdel corpus. - 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. - Documentos de este corpus — Alineació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.