Android 9 admite la rotación de claves de APK, que les permite a las apps cambiar su clave de firma como parte de una actualización de APK. Para que la rotación sea práctica, los APKs deben indicar los niveles de confianza entre la clave de firma nueva y la anterior. Para admitir la rotación de claves, actualizamos el esquema de firma de APK de la versión 2 a la 3 para permitir que se usen las claves nuevas y las anteriores. La versión 3 agrega información sobre las versiones del SDK compatibles y una estructura de prueba de rotación al bloque de firma de APK.
Bloqueo de firma de APK
Para mantener la retrocompatibilidad con el formato de APK v1, las firmas de APK v2 y v3 se almacenan en un bloque de firma de APK, que se encuentra inmediatamente antes del directorio central de ZIP.
El formato de bloque de firma de APK v3 es el mismo que el de v2. La firma v3 del APK se almacena como un par ID-valor con el ID 0xf05368c0.
Bloque del esquema de firma de APK v3
El esquema v3 está diseñado para ser muy similar al esquema v2. Tiene el mismo formato general y admite los mismos IDs de algoritmo de firma, tamaños de clave y curvas EC.
Sin embargo, el esquema de la versión 3 agrega información sobre las versiones del SDK compatibles y la estructura de prueba de rotación.
Formato
El bloque del esquema de firma de APK v3 se almacena dentro del bloque de firma de APK con el ID 0xf05368c0
.
El formato del bloque del esquema de firma de APK v3 sigue el de v2:
- Secuencia con prefijo de longitud de
signer
con prefijo de longitud:signed data
con prefijo de longitud:- Secuencia con prefijo de longitud de
digests
con prefijo de longitud:signature algorithm ID
(4 bytes)digest
(con prefijo de longitud)
- Secuencia con prefijo de longitud de
certificates
X.509:certificate
X.509 con prefijo de longitud (formato ASN.1 DER)
minSDK
(uint32): Se debe ignorar este firmante si la versión de la plataforma es inferior a este número.maxSDK
(uint32): Se debe ignorar este firmante si la versión de la plataforma es superior a este número.- Secuencia con prefijo de longitud de
additional attributes
con prefijo de longitud:ID
(uint32)value
(longitud variable: longitud del atributo adicional: 4 bytes)ID - 0x3ba06f8c
value -
Estructura de prueba de rotación
- Secuencia con prefijo de longitud de
minSDK
(uint32): Es un duplicado del valor de minSDK en la sección de datos firmados que se usa para omitir la verificación de esta firma si la plataforma actual no está dentro del rango. Debe coincidir con el valor de datos firmados.maxSDK
(uint32): Es un duplicado del valor de maxSDK en la sección de datos firmados que se usa para omitir la verificación de esta firma si la plataforma actual no está dentro del rango. Debe coincidir con el valor de datos firmados.- Secuencia con prefijo de longitud de
signatures
con prefijo de longitud:signature algorithm ID
(uint32)signature
con prefijo de longitud sobresigned data
public key
con prefijo de longitud (SubjectPublicKeyInfo, formato ASN.1 DER)
Estructuras de prueba de rotación y de certificados antiguos de confianza propia
La estructura de prueba de rotación permite que las apps giren su certificado de firma sin bloquearse en otras apps con las que se comunican. Para lograrlo, las firmas de apps contienen dos datos nuevos:
- Una aserción para terceros de que se puede confiar en el certificado de firma de la app siempre que se confíe en sus predecesores
- los certificados de firma anteriores de la app en los que la app aún confía
El atributo de prueba de rotación en la sección de datos firmados consta de una lista con un solo vínculo, en la que cada nodo contiene un certificado de firma que se usa para firmar versiones anteriores de la app. Este atributo debe contener las estructuras de datos conceptuales de prueba de rotación y de certificados antiguos de confianza propia. La lista se ordena por versión con el certificado de firma más antiguo que corresponde al nodo raíz. La estructura de datos de la prueba de rotación se compila haciendo que el certificado de cada nodo firme el siguiente de la lista y, de esta manera, se le infunda a cada clave nueva evidencia de que debe ser tan confiable como las claves anteriores.
La estructura de datos de certificados confiables propios anteriores se construye agregando marcas a cada nodo que indican su membresía y propiedades en el conjunto. Por ejemplo, puede haber una marca que indique que el certificado de firma de un nodo determinado es de confianza para obtener permisos de firma de Android. Esta marca permite que otras apps que firmó el certificado anterior sigan recibiendo un permiso de firma definido por una app firmada con el nuevo certificado de firma. Debido a que todo el atributo de prueba de rotación reside en la sección de datos firmados del campo signer
de v3, está protegido por la clave que se usa para firmar el APK que lo contiene.
Este formato excluye claves de firma múltiples y la convergencia de diferentes certificados de firma de ancestros en uno (varios nodos de inicio a un sumidero común).
Formato
La prueba de rotación se almacena dentro del bloque del esquema de firma de APK v3 con el ID 0x3ba06f8c
. Su formato es el siguiente:
- Secuencia con prefijo de longitud de
levels
con prefijo de longitud:signed data
con prefijo de longitud (por certificado anterior, si existe)certificate
X.509 con prefijo de longitud (formato ASN.1 DER)signature algorithm ID
(uint32): Es el algoritmo que usa la certificación en el nivel anterior.
flags
(uint32): Indica si este certificado debe estar o no en la estructura de certificados de confianza propia y para qué operaciones.signature algorithm ID
(uint32): Debe coincidir con el de la sección de datos firmados en el siguiente nivel.signature
con prefijo de longitud sobre elsigned data
anterior
Múltiples certificados
No se admiten varios firmantes, y Google Play no publica apps firmadas con varios certificados.
Verificación
En Android 9 y versiones posteriores, los APKs se pueden verificar según el esquema de firma de APK v3, v2 o v1. Las plataformas más antiguas ignoran las firmas v3 y, en su lugar, intentan verificar las firmas v2 y, luego, las v1.
Figura 1: Proceso de verificación de la firma de APK
Verificación del esquema de firma de APK v3
- Busca el bloque de firma del APK y verifica lo siguiente:
- Dos campos de tamaño del bloque de firma de APK contienen el mismo valor.
- El directorio central de ZIP está seguido inmediatamente del registro de fin del directorio central de ZIP.
- No hay más datos después del final del directorio central del ZIP.
- Busca el primer bloque del esquema de firma de APK v3 dentro del bloque de firma de APK. Si el bloque v3 está presente, continúa con el paso 3. De lo contrario, vuelve a verificar el APK con el esquema v2.
- Para cada
signer
en el bloque del esquema de firma de APK v3 con una versión mínima y máxima del SDK que esté dentro del rango de la plataforma actual:- Elige la
signature algorithm ID
compatible más potente designatures
. El orden de la fuerza depende de cada versión de implementación o plataforma. - Verifica el
signature
correspondiente designatures
ensigned data
conpublic key
. (Ahora es seguro analizarsigned data
). - Verifica que las versiones mínimas y máximas del SDK en los datos firmados coincidan con las especificadas para
signer
. - Verifica que la lista ordenada de IDs de algoritmo de firma en
digests
ysignatures
sea idéntica. (Esto es para evitar la eliminación o adición de firmas). - Calcula el resumen del contenido del APK con el mismo algoritmo de resumen que el algoritmo de resumen que usa el algoritmo de firma.
- Verifica que el resumen calculado sea idéntico al
digest
correspondiente dedigests
. - Verifica que SubjectPublicKeyInfo del primer
certificate
decertificates
sea idéntico apublic key
. - Si existe el atributo de prueba de rotación para el
signer
, verifica que la estructura sea válida y que estesigner
sea el último certificado de la lista.
- Elige la
- La verificación se realiza correctamente si se encontró exactamente un
signer
dentro del rango de la plataforma actual y el paso 3 se realizó correctamente para esesigner
.
Validación
Para probar que tu dispositivo admita la versión 3 correctamente, ejecuta las pruebas de CTS de PkgInstallSignatureVerificationTest.java
en cts/hostsidetests/appsecurity/src/android/appsecurity/cts/
.