Code Signing (firma de código) es un mecanismo de firma digital para archivos ejecutables que garantiza la autenticidad del desarrollador y la integridad de la aplicación. En Android, cada archivo APK debe firmarse con un certificado antes de instalarse en un dispositivo o publicarse en Google Play. Según Google, 2024, Android admite cuatro generaciones de esquemas de firma: desde v1 basado en JAR hasta v4 para instalación por streaming.
Puntos clave
Code Signing es un proceso criptográfico en el que el desarrollador firma un código ejecutable con su certificado digital. La firma se crea mediante cifrado asimétrico: la clave privada del desarrollador genera una firma digital y la clave pública se incorpora al certificado. Cualquier persona puede verificar la firma utilizando la clave pública, pero modificar el código sin romper la firma es imposible.
En el desarrollo móvil, la firma de código cumple tres funciones. Primera — autenticación: el usuario y la plataforma pueden identificar al desarrollador de la aplicación. Segunda — integridad: cualquier cambio en el APK después de la firma invalida la firma. Tercera — actualizaciones de confianza: la plataforma solo permite actualizar una aplicación con APKs firmados con el mismo certificado que la versión instalada.
La firma digital de aplicaciones Android tiene importancia legal. Según la legislación rusa (63-FZ) y la europea eIDAS, una firma electrónica cualificada equivale a una firma manuscrita. Sin embargo, firmar un APK con un certificado autofirmado (práctica común en Android) no está cualificado — confirma la integridad, pero no la identidad del desarrollador desde un punto de vista legal.
Android admite cuatro esquemas de firma APK, cada uno resuelve los problemas de la versión anterior y añade nuevas capacidades. Todos los esquemas pueden coexistir en un mismo APK — esto es necesario para la compatibilidad con versiones antiguas de Android.
El esquema v1 (JAR signing) apareció en Android 1.0. Firma archivos individuales dentro del archivo APK usando entradas en META-INF/MANIFEST.MF. El inconveniente: un atacante puede modificar el APK (añadir o eliminar archivos) y volver a firmar solo los modificados sin tocar el resto. Esto hace que v1 sea vulnerable a ciertos ataques. El esquema v2 (APK Signature Scheme), introducido en Android 7.0, firma todo el archivo APK en su conjunto, incluidos todos los bytes excepto la propia firma, eliminando la posibilidad de modificación selectiva.
| Esquema | Android | Característica | Rotación de clave |
|---|---|---|---|
| v1 (JAR) | 1.0+ | Firma por archivo | No |
| v2 | 7.0+ | Firma completa del APK | No |
| v3 | 9.0+ | Firma + rotación | Sí |
| v4 | 11.0+ | Streaming + ADB | Sí |
El esquema v3, introducido en Android 9.0, resuelve un problema antiguo: ¿qué hacer si la clave de firma está comprometida o ha caducado? Anteriormente, cambiar la clave de firma significaba que la aplicación se trataba como nueva — no se podía instalar sobre una existente. v3 añade un mecanismo de rotación: el APK puede incluir una prueba de rotación (proof-of-rotation), firmada por la clave antigua. El sistema verifica la cadena y permite actualizar la aplicación firmada con la nueva clave.
Keystore es un contenedor seguro que contiene claves privadas y certificados para firmar aplicaciones. En el desarrollo de Android se utiliza el formato JKS (Java KeyStore) o PKCS12. El keystore se crea con la utilidad keytool, que forma parte del JDK. Cada clave en el almacén se identifica por un alias y está protegida por una contraseña.
El certificado en un keystore contiene la clave pública e información del propietario: nombre de la organización, país, período de validez. Para aplicaciones Android, el certificado puede ser autofirmado — Google no exige una autoridad de certificación (CA), lo que diferencia a Android de iOS. Sin embargo, la validez del certificado debe ser de al menos 25 años, ya que la aplicación se actualizará con la misma clave.
# Creando un nuevo keystore para firmar
keytool -genkey -v -keystore my-release.keystore \
-alias my-app-alias \
-keyalg RSA \
-keysize 2048 \
-validity 10000
# Visualizando el contenido del keystore
keytool -list -v -keystore my-release.keystore
Android admite dos algoritmos para las claves de firma: RSA y ECDSA. RSA con un tamaño de clave de 2048 bits es el estándar de facto, compatible con todas las versiones de Android. ECDSA (Elliptic Curve Digital Signature Algorithm) con la curva P-256 proporciona la misma fortaleza criptográfica con un tamaño de clave menor. Desde Android 9.0 se recomienda ECDSA, ya que es más rápido en la verificación en dispositivos móviles.
En Android Gradle Plugin, la firma se configura mediante el bloque signingConfigs en build.gradle del nivel de módulo. Para compilaciones de depuración, Android Studio crea automáticamente un keystore de depuración con contraseñas conocidas. Para compilaciones de publicación, el desarrollador especifica la ruta a su keystore, el alias de la clave y las contraseñas. Se recomienda almacenar las contraseñas en archivos de configuración separados, excluidos del control de versiones.
Una práctica moderna es la gestión centralizada de firmas a través de CI/CD. Jenkins, GitLab CI o GitHub Actions pueden almacenar el keystore como un artefacto protegido y las contraseñas como secretos de entorno. Esto evita la fuga de claves a través del repositorio y simplifica la rotación de claves cuando sea necesario.
// build.gradle (nivel de app) — configuración de firma
android {
signingConfigs {
release {
storeFile file("my-release.keystore")
storePassword System.getenv("KEYSTORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEY_PASSWORD")
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
Para máxima compatibilidad, un APK debe estar firmado con los tres esquemas (v1 + v2 + v3). Android Gradle Plugin incluye todos los esquemas por defecto. Los APK firmados solo con v2 no se instalarán en Android 6.0 y versiones anteriores. Los APK solo con v1 no obtendrán los beneficios de integridad de v2 en Android 7.0+. Incluir todos los esquemas no aumenta el tamaño del APK más de un 1–2% y garantiza la compatibilidad con cualquier dispositivo.
Play App Signing es un servicio de Google Play que gestiona centralizadamente las claves de firma de las aplicaciones. El desarrollador sube un APK firmado con una clave de carga (upload key) a Google Play Console, y Google Play lo vuelve a firmar con una clave de distribución (distribution key) antes de entregarlo a los usuarios. Esto protege la clave de distribución contra pérdida o compromiso.
Ventajas de Play App Signing: seguridad — la clave de distribución se almacena en el almacenamiento protegido de Google; rotación — se puede solicitar un cambio de clave a través de la consola; recuperación — si se pierde la clave de carga, se puede generar una nueva. Inconveniente: para aplicaciones que existían antes de la introducción de Play App Signing, la migración requiere crear una nueva aplicación, ya que la clave de distribución anterior ya está en uso.
# Obteniendo la huella digital del certificado (SHA-256)
keytool -list -v -keystore my-release.keystore \
-alias my-app-alias | grep "SHA256"
# Verificando la firma del APK con apksigner
apksigner verify --verbose app-release.apk
Si la clave de firma se pierde y no se utiliza Play App Signing, es imposible restaurar la capacidad de actualizar la aplicación — habrá que crear una nueva aplicación con un nuevo nombre de paquete. Esta es una de las principales razones para usar Play App Signing. Google recomienda mantener una copia de seguridad del keystore en un almacenamiento offline seguro (unidad USB encriptada, caja de seguridad bancaria).
Al instalar un APK, Android realiza una verificación de firma en varias etapas. Primera — comprobación del certificado: si ha caducado y el formato es correcto. Segunda — verificación de la firma: si la firma criptográfica coincide con el contenido del APK. Tercera — comparación del certificado con la versión instalada: si la aplicación ya existe en el dispositivo, el certificado debe coincidir, de lo contrario se bloquea la instalación.
El sistema de verificación está integrado en PackageManagerService. Al procesar una solicitud de instalación, PMS extrae la firma del APK, la verifica mediante la clase android.util.PackageParser y la compara con la firma almacenada de la aplicación instalada (si existe). Si no coinciden, el usuario recibe el error “INSTALL_FAILED_UPDATE_INCOMPATIBLE”. Este mecanismo previene los ataques de sustitución (el malware no puede reemplazar una aplicación legítima con su propia versión).
Un desarrollador puede verificar independientemente la firma del APK utilizando la utilidad apksigner de Android SDK Build Tools. El comando apksigner verify --verbose app.apk muestra con qué esquemas está firmado el APK, si los certificados son válidos y si las firmas coinciden con el contenido. Para la verificación programática de la firma de una aplicación instalada, se usa PackageManager.getPackageInfo() con la bandera GET_SIGNATURES.
// Verificación programática de la firma de una aplicación instalada
fun getAppSignature(context: Context, packageName: String): String? {
val pm = context.packageManager
val info = pm.getPackageInfo(
packageName,
PackageManager.GET_SIGNATURES
)
return info.signatures?.firstOrNull()?.toCharsString()
}
La seguridad de la clave de firma es un aspecto crítico del desarrollo de Android. El compromiso de la clave permite a un atacante firmar actualizaciones de su aplicación con su propio código. Las reglas principales: nunca almacene la clave en un repositorio, no use una misma clave para diferentes aplicaciones, no transfiera la clave a través de canales no seguros (correo electrónico, mensajería).
La práctica recomendada es la separación de claves. Use una clave separada para cada aplicación y una clave separada para la carga en Google Play (upload key). Para compilaciones de depuración, Android Studio crea un debug.keystore compartido — no debe usarse para compilaciones de publicación. La validez del certificado debe ser de 25 a 30 años (estándar actual, confirmado por Google).
| Práctica | Recomendación |
|---|---|
| Almacenamiento de clave | Soporte encriptado, secretos CI/CD |
| Validez del certificado | Al menos 25 años |
| Algoritmo | RSA 2048+ o ECDSA P-256 |
| Separación | Clave separada por aplicación |
| Respaldo | Copia offline del keystore |
Verifique regularmente la integridad de la cadena de firma. Cuando los empleados con acceso a las claves se marchan, actualice la clave de carga a través de Google Play Console. Utilice herramientas como Google Play Integrity API para verificar que su aplicación no ha sido manipulada en los dispositivos de los usuarios. La API devuelve datos sobre la firma e integridad, enviándolos al servidor para su verificación.
Preguntas frecuentes
Code Signing es una firma digital de un archivo APK que confirma que la aplicación fue creada por un desarrollador específico y no ha sido modificada después de la firma. Sin firma, el APK no se instalará en un dispositivo.
Use la utilidad keytool del JDK: keytool -genkey -v -keystore my-release.keystore -alias my-alias -keyalg RSA -keysize 2048 -validity 10000. Especifique el keystore resultante en build.gradle en el bloque signingConfigs.
Si la clave se pierde y no utiliza Play App Signing, la actualización de la aplicación se vuelve imposible. Tendrá que crear una nueva aplicación en Google Play con un nuevo nombre de paquete. Use Play App Signing para protegerse contra la pérdida de clave.
v1 firma cada archivo dentro del APK individualmente — un atacante puede modificar un archivo y volver a firmar solo ese. v2 firma todo el APK en su conjunto — cualquier cambio invalida la firma, proporcionando un mayor nivel de seguridad.
Play App Signing es un servicio de Google Play que almacena centralizadamente la clave de distribución de aplicaciones. El desarrollador sube un APK firmado con una clave de carga, y Google lo vuelve a firmar antes de entregarlo a los usuarios, protegiendo la clave contra pérdida o robo.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también