Firma de compilaciones para el lanzamiento

Las imágenes de SO Android usan firmas criptográficas en dos lugares:

  1. Se debe firmar cada archivo .apk dentro de la imagen. Android El Administrador de paquetes usa una firma .apk de dos maneras:
    • Cuando se reemplaza una aplicación, debe estar firmada por la misma clave que la aplicación antigua para acceder a sus datos. Esto contiene true tanto para actualizar apps del usuario reemplazando .apk como anular una app del sistema con una versión más reciente instalada en /data
    • Si dos o más aplicaciones desean compartir un ID de usuario (para poder compartir datos, etc.), deben firmarse con la misma clave.
  2. Los paquetes de actualización OTA deben firmarse con una de las claves esperadas por el sistema operativo, o el proceso de instalación las rechazará.

Liberar claves

El árbol de Android incluye test-keys en build/target/product/security Cómo compilar una imagen de SO Android con make firmará todos los archivos .apk con el claves de prueba. Debido a que las claves de prueba son de conocimiento público, cualquiera puede firmar las Archivos .apk con las mismas claves, lo que les permite reemplazar o apropiarse del sistema aplicaciones integradas en tu imagen de SO. Por este motivo, es fundamental firmar cualquier una imagen de SO Android lanzada o implementada públicamente con un conjunto especial de release-keys a los que solo tú tienes acceso.

Para generar tu propio conjunto único de claves de lanzamiento, ejecuta estos comandos desde la raíz de tu árbol de Android:

subject='/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
mkdir ~/.android-certs
for x in releasekey platform shared media networkstack; do \
    ./development/tools/make_key ~/.android-certs/$x "$subject"; \
  done

$subject debe cambiarse para reflejar el información. Puedes usar cualquier directorio, pero ten cuidado de elegir un con copia de seguridad y protegida. Algunos proveedores eligen encriptar su clave privada con una frase de contraseña segura y almacenar la clave encriptada en el control de fuentes; otros almacenan sus claves de lanzamiento en un lugar completamente diferente. como en una computadora aislada.

Para generar una imagen de lanzamiento, usa lo siguiente:

make dist
sign_target_files_apks \
-o \    # explained in the next section
--default_key_mappings ~/.android-certs out/dist/*-target_files-*.zip \
signed-target_files.zip

La secuencia de comandos sign_target_files_apks toma un archivo target-files .zip como entrada y produce un nuevo archivo de destino .zip en en el que todos los archivos .apk se firmaron con claves nuevas. El nuevo las imágenes firmadas se encuentran en IMAGES/ en signed-target_files.zip

Firma paquetes inalámbricos

Un ZIP de archivos de destino firmado se puede convertir en un ZIP de actualización OTA firmado. usando el siguiente procedimiento:
ota_from_target_files \
-k  (--package_key) 
signed-target_files.zip \
signed-ota_update.zip

Firmas y sideloading

La transferencia no omite la firma normal del paquete de la recuperación de verificación, antes de instalar un paquete, la recuperación verificará que se firma con una de las claves privadas que coincide con las claves públicas almacenadas la partición de recuperación, tal como lo haría con un paquete que se entrega de forma inalámbrica.

Los paquetes de actualización recibidos del sistema principal normalmente se verifican dos veces: una vez por el sistema principal, con el RecoverySystem.verifyPackage() en la API de Android y, nuevamente recuperación. La API de RecoverySystem compara la firma con claves públicas Se almacena en el sistema principal, en el archivo /system/etc/security/otacerts.zip (de forma predeterminada). La recuperación compara la firma con las claves públicas almacenadas En el disco RAM de partición de recuperación, en el archivo /res/keys.

De forma predeterminada, los archivos de destino .zip que produce la compilación establecen la Certificado OTA que coincida con la clave de prueba. En una imagen publicada, se certificado debe usarse para que los dispositivos puedan verificar la autenticidad del de actualización del paquete. Pasa la marca -o a sign_target_files_apks, como se muestra en la sección anterior, reemplaza el certificado de clave de prueba con el certificado de clave de lanzamiento de tus certificados .

Por lo general, la imagen del sistema y la imagen de recuperación almacenan el mismo conjunto de OTA claves públicas. Si se agrega una clave solo al conjunto de claves de recuperación, se posible firmar paquetes que solo se pueden instalar mediante sideloading (suponiendo que el mecanismo principal de descarga de actualizaciones del sistema funcione correctamente la verificación en otacerts.zip). Puedes especificar claves adicionales solo en la recuperación con la configuración de PRODUCT_EXTRA_RECOVERY_KEYS variable en la definición del producto:

vendor/yoyodyne/tardis/products/tardis.mk
 [...]

PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload

Esto incluye la clave pública vendor/yoyodyne/security/tardis/sideload.x509.pem en la recuperación de claves para instalar paquetes firmados con él. Sin embargo, la clave adicional no se incluye en otacerts.zip, por lo que los sistemas que verifican correctamente los paquetes descargados no invocan la recuperación para paquetes firmados con esta clave.

Certificados y claves privadas

Cada clave viene en dos archivos: el certificado, que tiene el extensión .x509.pem, y la clave privada, que tiene la extensión .pk8. La clave privada debe ser secreta y es necesaria para firmar un paquete. La clave podría estar protegida con una contraseña. El certificado, en contraste, contiene solo la mitad pública de la clave, por lo que se puede distribuir ampliamente. Se usa para verificar que un paquete haya sido firmado por la dirección privada.

La compilación estándar de Android usa cinco claves, que se encuentran en build/target/product/security:

clave de prueba
Clave genérica predeterminada para paquetes que no especifican una clave de otro modo.
plataforma
Claves de prueba para paquetes que forman parte de la plataforma principal.
compartido
Prueba la llave para los elementos que se comparten en el proceso de la casa y los contactos.
contenido multimedia
Claves de prueba para paquetes que forman parte del sistema de contenido multimedia o de descarga.
pila de red
Clave de prueba para paquetes que forman parte del sistema de red. El networkstack se usa para firmar los objetos binarios diseñados como Componentes modulares del sistema Si las actualizaciones de tu módulo se compilan por separado y se integran como compilaciones previas en la imagen de tu dispositivo, es posible que no necesites generar una clave de Networkstack en la Árbol de fuentes de Android.

Los paquetes individuales especifican una de estas claves mediante la configuración de LOCAL_CERTIFICATE en su archivo Android.mk. (se usa testkey si esta variable no está configurada). Tú también puede especificar una clave completamente diferente por nombre de ruta, p.ej.:

device/yoyodyne/apps/SpecialApp/Android.mk
 [...]

LOCAL_CERTIFICATE := device/yoyodyne/security/special

Ahora, la compilación usa la clave device/yoyodyne/security/special.{x509.pem,pk8} para firmar SpecialApp.apk. La compilación solo puede usar claves privadas que no están protegidos por contraseña.

Opciones de firma avanzadas

Reemplazo de la clave de firma de APK

La secuencia de comandos de firma sign_target_files_apks funciona en el destino archivos generados para una compilación. Toda la información sobre certificados y servicios que se usan en el tiempo de compilación se incluyen en los archivos de destino. Cuando ejecutes secuencia de comandos de firma para firmar la liberación; las claves de firma se pueden reemplazar según las claves o el nombre del APK.

Usa --key_mapping y --default_key_mappings. marcas para especificar el reemplazo de clave según los nombres de claves:

  • La marca --key_mapping src_key=dest_key especifica el reemplazo de una clave a la vez.
  • La marca --default_key_mappings dir especifica un con cinco claves para reemplazar todas las claves build/target/product/security; equivale a usar --key_mapping cinco veces para especificar las asignaciones.
build/target/product/security/testkey      = dir/releasekey
build/target/product/security/platform     = dir/platform
build/target/product/security/shared       = dir/shared
build/target/product/security/media        = dir/media
build/target/product/security/networkstack = dir/networkstack

Usa el marca --extra_apks apk_name1,apk_name2,...=key para especificar los reemplazos de claves de firma según los nombres de APK. Si key se deja vacío, la secuencia de comandos trata los APK especificados como prefirmado.

Para el producto hipotético de tardis, necesitas seis claves protegidas con contraseña: cinco para reemplazar los cinco en build/target/product/security y uno para reemplazar la clave adicional device/yoyodyne/security/special que requiere SpecialApp en el ejemplo anterior. Si las claves estuvieran en el siguiente archivos:

vendor/yoyodyne/security/tardis/releasekey.x509.pem
vendor/yoyodyne/security/tardis/releasekey.pk8
vendor/yoyodyne/security/tardis/platform.x509.pem
vendor/yoyodyne/security/tardis/platform.pk8
vendor/yoyodyne/security/tardis/shared.x509.pem
vendor/yoyodyne/security/tardis/shared.pk8
vendor/yoyodyne/security/tardis/media.x509.pem
vendor/yoyodyne/security/tardis/media.pk8
vendor/yoyodyne/security/tardis/networkstack.x509.pem
vendor/yoyodyne/security/tardis/networkstack.pk8
vendor/yoyodyne/security/special.x509.pem
vendor/yoyodyne/security/special.pk8           # NOT password protected
vendor/yoyodyne/security/special-release.x509.pem
vendor/yoyodyne/security/special-release.pk8   # password protected

Luego, firmarías todas las apps de la siguiente manera:

./build/make/tools/releasetools/sign_target_files_apks \
    --default_key_mappings vendor/yoyodyne/security/tardis \
    --key_mapping vendor/yoyodyne/security/special=vendor/yoyodyne/security/special-release \
    --extra_apks PresignedApp= \
    -o tardis-target_files.zip \
    signed-tardis-target_files.zip

Esto muestra lo siguiente:

Enter password for vendor/yoyodyne/security/special-release key>
Enter password for vendor/yoyodyne/security/tardis/networkstack key>
Enter password for vendor/yoyodyne/security/tardis/media key>
Enter password for vendor/yoyodyne/security/tardis/platform key>
Enter password for vendor/yoyodyne/security/tardis/releasekey key>
Enter password for vendor/yoyodyne/security/tardis/shared key>
    signing: Phone.apk (vendor/yoyodyne/security/tardis/platform)
    signing: Camera.apk (vendor/yoyodyne/security/tardis/media)
    signing: NetworkStack.apk (vendor/yoyodyne/security/tardis/networkstack)
    signing: Special.apk (vendor/yoyodyne/security/special-release)
    signing: Email.apk (vendor/yoyodyne/security/tardis/releasekey)
        [...]
    signing: ContactsProvider.apk (vendor/yoyodyne/security/tardis/shared)
    signing: Launcher.apk (vendor/yoyodyne/security/tardis/shared)
NOT signing: PresignedApp.apk
        (skipped due to special cert string)
rewriting SYSTEM/build.prop:
  replace:  ro.build.description=tardis-user Eclair ERC91 15449 test-keys
     with:  ro.build.description=tardis-user Eclair ERC91 15449 release-keys
  replace: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/test-keys
     with: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/release-keys
    signing: framework-res.apk (vendor/yoyodyne/security/tardis/platform)
rewriting RECOVERY/RAMDISK/default.prop:
  replace:  ro.build.description=tardis-user Eclair ERC91 15449 test-keys
     with:  ro.build.description=tardis-user Eclair ERC91 15449 release-keys
  replace: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/test-keys
     with: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/release-keys
using:
    vendor/yoyodyne/security/tardis/releasekey.x509.pem
for OTA package verification
done.

Después de solicitar al usuario las contraseñas de todas las claves protegidas por contraseña, el sistema vuelve a firmar todos los archivos APK en el .zip de destino de entrada con el y lanzar claves de lanzamiento. Antes de ejecutar el comando, también puedes establecer La variable de entorno ANDROID_PW_FILE se convierte en un nombre de archivo temporal. el de comandos invoca al editor para que puedas ingresar las contraseñas de todas las claves. (puede ser una forma más conveniente de ingresar contraseñas).

Reemplazo de la clave de firma de APEX

Android 10 introduce la Formato de archivo APEX para la instalación módulos de sistema de nivel inferior. Como se explica en firma APEX, cada archivo APEX está firmado con dos claves: una para la imagen del sistema de archivos mini dentro de APEX y la y otros para todo el APEX.

Cuando se firma el lanzamiento, se reemplazan las dos claves de firma de un archivo APEX con claves de lanzamiento. La clave de carga útil del sistema de archivos se especifica con el marca --extra_apex_payload y toda la clave de firma del archivo APEX está especificado con la marca --extra_apks.

Para el producto tardis, supongamos que tienes la siguiente configuración de claves para com.android.conscrypt.apex com.android.media.apex y com.android.runtime.release.apex archivos APEX.

name="com.android.conscrypt.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED"
name="com.android.media.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED"
name="com.android.runtime.release.apex" public_key="vendor/yoyodyne/security/testkeys/com.android.runtime.avbpubkey" private_key="vendor/yoyodyne/security/testkeys/com.android.runtime.pem" container_certificate="vendor/yoyodyne/security/testkeys/com.google.android.runtime.release_container.x509.pem" container_private_key="vendor/yoyodyne/security/testkeys/com.google.android.runtime.release_container.pk8"

Además, tienes los siguientes archivos que contienen las claves de lanzamiento:

vendor/yoyodyne/security/runtime_apex_container.x509.pem
vendor/yoyodyne/security/runtime_apex_container.pk8
vendor/yoyodyne/security/runtime_apex_payload.pem

El siguiente comando anula las claves de firma de com.android.runtime.release.apex y com.android.tzdata.apex durante la firma de la versión. En particular, com.android.runtime.release.apex se firma con el valor especificado claves de lanzamiento (runtime_apex_container para el archivo APEX y runtime_apex_payload para la carga útil de la imagen del archivo). com.android.tzdata.apex se trata como firmado previamente. Todos los demás elementos de APEX se manejan con la configuración predeterminada que se indica en los archivos de destino.

./build/make/tools/releasetools/sign_target_files_apks \
    --default_key_mappings   vendor/yoyodyne/security/tardis \
    --extra_apks             com.android.runtime.release.apex=vendor/yoyodyne/security/runtime_apex_container \
    --extra_apex_payload_key com.android.runtime.release.apex=vendor/yoyodyne/security/runtime_apex_payload.pem \
    --extra_apks             com.android.media.apex= \
    --extra_apex_payload_key com.android.media.apex= \
    -o tardis-target_files.zip \
    signed-tardis-target_files.zip

Si ejecutas el comando anterior, obtendrás los siguientes registros:

        [...]
    signing: com.android.runtime.release.apex                  container (vendor/yoyodyne/security/runtime_apex_container)
           : com.android.runtime.release.apex                  payload   (vendor/yoyodyne/security/runtime_apex_payload.pem)
NOT signing: com.android.conscrypt.apex
        (skipped due to special cert string)
NOT signing: com.android.media.apex
        (skipped due to special cert string)
        [...]

Otras opciones

La secuencia de comandos de firma sign_target_files_apks reescribe la compilación. descripción y huella digital en los archivos de propiedades de compilación para reflejar que el es una compilación firmada. La marca --tag_changes controla qué cambios de la huella digital. Ejecuta la secuencia de comandos con -h para ver documentación sobre todas las marcas.

Genera claves de forma manual

Android usa claves RSA de 2,048 bits con exponente público 3. Puedes generar certificado/clave privada con la herramienta openssl desde openssl.org:

# generate RSA key
openssl genrsa -3 -out temp.pem 2048
Generating RSA private key, 2048 bit long modulus
....+++
.....................+++
e is 3 (0x3)

# create a certificate with the public part of the key
openssl req -new -x509 -key temp.pem -out releasekey.x509.pem -days 10000 -subj '/C=US/ST=California/L=San Narciso/O=Yoyodyne, Inc./OU=Yoyodyne Mobility/CN=Yoyodyne/emailAddress=yoyodyne@example.com'

# create a PKCS#8-formatted version of the private key
openssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt

# securely delete the temp.pem file
shred --remove temp.pem

El comando pkcs8 de openssl mencionado anteriormente crea un archivo .pk8 con el valor no. contraseña, adecuada para su uso con el sistema de compilación. Para crear un archivo .pk8 protegido con una contraseña (lo que deberías hacer para todas las claves de lanzamiento reales), reemplaza el argumento -nocrypt con -passout stdin; luego, openssl encriptará la clave privada con una contraseña que se leerá desde una entrada estándar. No se imprime el mensaje, por lo que, si stdin es la terminal, el programa aparecerá colgando cuando solo está esperando que ingreses una contraseña. Otros valores también pueden se utiliza para que el argumento-passout lea la contraseña desde otras ubicaciones; para detalles, consulta la documentación de openssl.

El archivo intermedio temp.pem contiene la clave privada sin ningún tipo de protección por contraseña, por lo que debes desecharla cuidadosamente cuando generes una claves. En particular, la utilidad GNUshred puede no ser eficaz en redes o sistemas de archivos registrados. Puedes usar un directorio de trabajo ubicado en un disco RAM (como una partición tmpfs) cuando se generan claves para garantizar que los no estén expuestos accidentalmente.

Crea archivos de imagen

Cuando tengas signed-target_files.zip, deberás crear la imagen para que puedas colocarla en un dispositivo. Para crear la imagen firmada a partir de los archivos de destino, ejecuta el siguiente comando desde la raíz de Android árbol:

img_from_target_files signed-target_files.zip signed-img.zip
El archivo resultante, signed-img.zip, contiene todos los archivos .img. Para cargar una imagen en un dispositivo, usa fastboot como sigue:
fastboot update signed-img.zip