Android 9 admite la rotación de claves de APK , lo que brinda a las aplicaciones la capacidad de cambiar su clave de firma como parte de una actualización de APK. Para que la rotación sea práctica, los APK 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 APK de v2 a v3 para permitir el uso de claves nuevas y antiguas. V3 agrega información sobre las versiones de SDK compatibles y una estructura de prueba de rotación al bloque de firma de APK.
Bloque de firma de APK
Para mantener la compatibilidad con versiones anteriores del formato APK v1, las firmas APK v2 y v3 se almacenan dentro de un bloque de firma APK, ubicado inmediatamente antes del directorio central ZIP.
El formato del bloque de firma de APK v3 es el mismo que v2 . La firma v3 del APK se almacena como un par ID-valor con ID 0xf05368c0.
APK Signature Scheme v3 Block
El esquema v3 está diseñado para ser muy similar al esquema v2 . Tiene el mismo formato general y admite los mismos ID de algoritmos de firma , tamaños de clave y curvas EC.
Sin embargo, el esquema v3 agrega información sobre las versiones de SDK admitidas y la estructura de prueba de rotación.
Formato
APK Signature Scheme v3 Block se almacena dentro del APK Signing Block con el ID 0xf05368c0
.
El formato del bloque APK Signature Scheme 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 (formulario ASN.1 DER)
-
-
minSDK
(uint32): este firmante debe ignorarse si la versión de la plataforma es inferior a este número. -
maxSDK
(uint32): este firmante debe ignorarse 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): duplicado del valor de minSDK en la sección de datos firmados: 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 los datos firmados. -
maxSDK
(uint32) - duplicado del valor maxSDK en la sección de datos firmados - usado para omitir la verificación de esta firma si la plataforma actual no está dentro del rango. Debe coincidir con el valor de los 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, formulario ASN.1 DER)
-
Estructuras de prueba de rotación y certificados antiguos de confianza propia
La estructura de prueba de rotación permite que las aplicaciones roten su certificado de firma sin que se bloqueen en otras aplicaciones con las que se comunican. Para lograr esto, las firmas de aplicaciones contienen dos nuevos datos:
- afirmación para terceros de que se puede confiar en el certificado de firma de la aplicación dondequiera que se confíe en sus predecesores
- los certificados de firma más antiguos de la aplicación en los que la propia aplicación 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 enlace, en la que cada nodo contiene un certificado de firma que se usa para firmar versiones anteriores de la aplicación. Este atributo está destinado a contener las estructuras de datos conceptuales de prueba de rotación y certificados antiguos de confianza. La lista está ordenada por versión con el certificado de firma más antiguo correspondiente al nodo raíz. La estructura de datos de prueba de rotación se construye haciendo que el certificado en cada nodo firme el siguiente en la lista y, por lo tanto, imbuyendo cada nueva clave con evidencia de que debe ser tan confiable como las claves anteriores.
La estructura de datos de certificados antiguos de confianza propia se construye agregando indicadores a cada nodo que indican su pertenencia y propiedades en el conjunto. Por ejemplo, puede haber una marca que indique que el certificado de firma en un nodo determinado es de confianza para obtener permisos de firma de Android. Esta marca permite que a otras aplicaciones firmadas por el certificado anterior se les siga otorgando un permiso de firma definido por una aplicación 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 de signer
v3, está protegido por la clave utilizada para firmar el apk que lo contiene.
Este formato excluye varias claves de firma y la convergencia de diferentes certificados de firma de ancestros en uno (múltiples nodos de inicio en un receptor común).
Formato
La prueba de rotación se almacena dentro del bloque APK Signature Scheme v3 con el ID 0x3ba06f8c
. Su formato es:
- 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 (formulario ASN.1 DER) -
signature algorithm ID
(uint32): algoritmo utilizado por cert en el nivel anterior
-
-
flags
(uint32): indicadores que indican si este certificado debe estar o no en la estructura self-trusted-old-certs 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 lossigned data
anteriormente
-
Múltiples certificados
Android actualmente trata un APK firmado con varios certificados como si tuviera una identidad de firma única separada de los certificados que lo componen. Por lo tanto, el atributo de prueba de rotación en la sección de datos firmados forma un gráfico acíclico dirigido, que podría verse mejor como una lista de enlaces simples, en la que cada conjunto de firmantes para una versión determinada representa un nodo. Esto agrega complejidad adicional a la estructura de prueba de rotación (versión de múltiples firmantes a continuación). En particular, ordenar se convierte en una preocupación. Además, ya no es posible firmar APK de forma independiente, porque la estructura de prueba de rotación debe tener los certificados de firma antiguos firmando el nuevo conjunto de certificados, en lugar de firmarlos uno por uno. Por ejemplo, un APK firmado por la clave A que desea estar firmado por dos nuevas claves B y C no puede hacer que el firmante B solo incluya una firma de A o B, porque esa es una identidad de firma diferente a la de B y C. Esto sería significa que los firmantes deben coordinarse antes de construir tal estructura.
Atributo de prueba de rotación de varios firmantes
- secuencia con prefijo de longitud de
sets
con prefijo de longitud:-
signed data
(por conjunto anterior, si existe)- secuencia de
certificates
con prefijo de longitud-
certificate
X.509 con prefijo de longitud (formulario ASN.1 DER)
-
- Secuencia de
signature algorithm IDs
(uint32): uno para cada certificado del conjunto anterior, en el mismo orden.
- secuencia de
-
flags
(uint32): indicadores que indican si este conjunto de certificados debe estar o no en la estructura self-trusted-old-certs y para qué operaciones. - Secuencia con prefijo de longitud de
signatures
con prefijo de longitud:-
signature algorithm ID
(uint32): debe coincidir con el de la sección de datos firmados -
signature
con prefijo de longitud sobre lossigned data
anteriormente
-
-
Antepasados múltiples en la estructura de prueba de rotación
El esquema v3 tampoco maneja dos claves diferentes que rotan a la misma clave de firma para la misma aplicación. Esto difiere del caso de una adquisición, donde la empresa adquirente quisiera mover la aplicación adquirida para usar su clave de firma para compartir permisos. La adquisición se considera un caso de uso compatible porque la nueva aplicación se distinguiría por el nombre de su paquete y podría contener su propia estructura de prueba de rotación. El caso no compatible, en el que la misma aplicación tiene dos rutas diferentes para llegar al mismo certificado, rompe muchas de las suposiciones hechas en el diseño de rotación de claves.
Verificación
En Android 9 y versiones posteriores, los APK se pueden verificar de acuerdo con el esquema de firma de APK v3, el esquema v2 o el esquema v1. Las plataformas más antiguas ignoran las firmas v3 e intentan verificar las firmas v2, luego v1.
Verificación del esquema de firma APK v3
- Ubique el bloque de firma de APK y verifique que:
- Dos campos de tamaño del bloque de firma de APK contienen el mismo valor.
- El ZIP Central Directory es seguido inmediatamente por el registro ZIP End of Central Directory.
- ZIP End of Central Directory no es seguido por más datos.
- Localice el primer bloque del esquema de firma de APK v3 dentro del bloque de firma de APK. Si el bloque v3 está presente, continúe con el paso 3. De lo contrario, vuelva a verificar el APK usando el esquema v2 .
- Para cada
signer
en el bloque APK Signature Scheme v3 con una versión mínima y máxima de SDK que esté dentro del rango de la plataforma actual:- Elija el
signature algorithm ID
de firma más compatible de lassignatures
. El orden de fuerza depende de cada versión de implementación/plataforma. - Verifique la
signature
correspondiente de lassignatures
contrasigned data
usandopublic key
. (Ahora es seguro analizarsigned data
). - Verifique que las versiones mínima y máxima del SDK en los datos firmados coincidan con las especificadas para el
signer
. - Verifique que la lista ordenada de ID de algoritmos de firma en
digests
ysignatures
sea idéntica. (Esto es para evitar la eliminación/adición de firmas). - Calcule el resumen de los contenidos del APK usando el mismo algoritmo de resumen que el algoritmo de resumen usado por el algoritmo de firma.
- Verifique que el resumen calculado sea idéntico al
digest
correspondiente dedigests
. - Verifique que SubjectPublicKeyInfo del primer
certificate
decertificates
sea idéntico apublic key
. - Si el atributo de prueba de rotación existe para el
signer
, verifique que la estructura sea válida y que estesigner
sea el último certificado de la lista.
- Elija el
- La verificación tiene éxito si se encontró exactamente un
signer
en el rango de la plataforma actual y el paso 3 fue exitoso para esesigner
.
Validación
Para probar que su dispositivo es compatible con v3 correctamente, ejecute las pruebas CTS de PkgInstallSignatureVerificationTest.java
en cts/hostsidetests/appsecurity/src/android/appsecurity/cts/
.