O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Assinando Builds para Lançamento

As imagens do sistema operacional Android usam assinaturas criptográficas em dois lugares:

  1. Cada .apk arquivo dentro da imagem deve ser assinado. Gerenciador de Pacotes do Android usa um .apk assinatura de duas maneiras:
    • Quando um aplicativo é substituído, ele deve ser assinado com a mesma chave do aplicativo antigo para obter acesso aos dados do aplicativo antigo. Isto é válido tanto para atualizar aplicativos do usuário, substituindo o .apk , e para substituir um aplicativo do sistema com uma versão mais recente instalado sob /data .
    • Se dois ou mais aplicativos desejam compartilhar uma ID de usuário (para que possam compartilhar dados, etc.), eles devem ser assinados com a mesma chave.
  2. Os pacotes de atualização OTA devem ser assinados com uma das chaves esperadas pelo sistema ou o processo de instalação irá rejeitá-los.

Teclas de liberação

A árvore Android inclui test-chaves sob build/target/product/security . Construir uma imagem do sistema operacional Android usando make irá assinar todos .apk arquivos usando as teclas de teste. Como as chaves de teste são conhecidas publicamente, qualquer pessoa pode assinar seus próprios arquivos .apk com as mesmas chaves, o que pode permitir que eles substituam ou sequestrem aplicativos do sistema integrados à imagem do seu sistema operacional. Por esta razão, é fundamental para assinar qualquer imagem de sistema operacional Android lançado ou implantado publicamente com um conjunto especial de release-chaves que só você tem acesso.

Para gerar seu próprio conjunto exclusivo de chaves de liberação, execute estes comandos a partir da raiz de sua árvore 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 deve ser alterado para refletir a informação da sua organização. Você pode usar qualquer diretório, mas tome cuidado ao escolher um local seguro e com backup. Alguns fornecedores optam por criptografar sua chave privada com uma senha forte e armazenar a chave criptografada no controle de origem; outros armazenam suas chaves de liberação em outro lugar inteiramente, como em um computador com air-gap.

Para gerar uma imagem de lançamento, use:

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

O sign_target_files_apks roteiro leva-alvo arquivos .zip como entrada e produz um novo alvo-arquivos .zip no qual todos os .apk arquivos foram assinados com novas chaves. As imagens recém-assinado pode ser encontrado em IMAGES/ em signed-target_files.zip .

Assinando pacotes OTA

A assinados-alvo arquivos zip pode ser convertido em um zip atualização OTA assinado usando o seguinte procedimento:
ota_from_target_files \
-k  (--package_key) 
signed-target_files.zip \
signed-ota_update.zip

Assinaturas e sideload

O sideload não ignora o mecanismo normal de verificação de assinatura de pacote de recuperação - antes de instalar um pacote, a recuperação verificará se ele está assinado com uma das chaves privadas correspondentes às chaves públicas armazenadas na partição de recuperação, assim como faria para um pacote entregue no -ar.

Pacotes de atualização recebidas do sistema principal são normalmente verificada duas vezes: uma pelo sistema principal, usando o RecoverySystem.verifyPackage() método na API do Android, e depois novamente por recuperação. As verificações RecoverySystem API a assinatura contra chaves públicas armazenados no sistema principal, no arquivo /system/etc/security/otacerts.zip (por padrão). Cheques de recuperação da assinatura contra as chaves públicas armazenadas no disco RAM partição de recuperação, no arquivo /res/keys .

Por padrão, os arquivos-alvo .zip produzida pelos conjuntos construir o certificado de OTA para coincidir com a chave de teste. Em uma imagem liberada, um certificado diferente deve ser usado para que os dispositivos possam verificar a autenticidade do pacote de atualização. Passando a -o bandeira para sign_target_files_apks , como mostrado na seção anterior, substitui o certificado de chave de teste com o certificado de chave de liberação do seu certs.

Normalmente, a imagem do sistema e a imagem de recuperação armazenam o mesmo conjunto de chaves públicas OTA. Ao adicionar uma chave para apenas o conjunto de recuperação de chaves, é possível assinar os pacotes que podem ser instalados somente via sideloading (assumindo mecanismo de download de atualização do sistema principal está correctamente fazer a verificação contra otacerts.zip). Você pode especificar chaves extras para serem incluídas apenas na recuperação, definindo a variável PRODUCT_EXTRA_RECOVERY_KEYS em sua definição de produto:

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

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

Isto inclui a chave pública vendor/yoyodyne/security/tardis/sideload.x509.pem no arquivo de chaves de recuperação para que ele possa instalar pacotes assinados com ele. A chave extra não está incluído no entanto otacerts.zip, por isso os sistemas que verificar corretamente os pacotes baixados não invocação de recuperação para pacotes assinados com esta chave.

Certificados e chaves privadas

Cada chave vem em dois arquivos: O certificado, que tem a .x509.pem extensão, ea chave privada, que tem a .pk8 extensão. A chave privada deve ser mantida em segredo e é necessária para assinar um pacote. A própria chave pode ser protegida por uma senha. O certificado, por outro lado, contém apenas a metade pública da chave, portanto, pode ser amplamente distribuído. É usado para verificar se um pacote foi assinado pela chave privada correspondente.

A construção padrão do Android usa cinco chaves, os quais residem em build/target/product/security :

chave de teste
Chave padrão genérica para pacotes que não especificam uma chave de outra forma.
plataforma
Chave de teste para pacotes que fazem parte da plataforma principal.
compartilhado
Chave de teste para coisas que são compartilhadas no processo de casa / contatos.
meios de comunicação
Chave de teste para pacotes que fazem parte do sistema de mídia / download.
pilha de rede
Chave de teste para pacotes que fazem parte do sistema de rede. A chave networkstack é usada para assinar binários concebidos como Modular System Components . Se as atualizações do seu módulo forem construídas separadamente e integradas como pré-compilados na imagem do seu dispositivo, você pode não precisar gerar uma chave de pilha de rede na árvore de origem do Android.

Pacotes individuais especificam uma dessas chaves definindo LOCAL_CERTIFICATE em seu arquivo Android.mk. (a chave de teste é usada se esta variável não for definida.) Você também pode especificar uma chave totalmente diferente por nome de caminho, por exemplo:

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

LOCAL_CERTIFICATE := device/yoyodyne/security/special

Agora, a construção utiliza o device/yoyodyne/security/special.{x509.pem,pk8} chave para assinar SpecialApp.apk. A construção pode usar apenas as chaves privadas que não são protegidos por senha.

Opções avançadas de assinatura

Substituição da chave de assinatura do APK

O script assinatura sign_target_files_apks trabalha nos arquivos de destino gerados para uma compilação. Todas as informações sobre certificados e chaves privadas usadas em tempo de construção são incluídas nos arquivos de destino. Ao executar o script de assinatura para assinar para liberação, as chaves de assinatura podem ser substituídas com base no nome da chave ou no nome do APK.

Use as --key_mapping e --default_key_mappings bandeiras para especificar substituição de chave com base em nomes-chave:

  • O --key_mapping src_key = dest_key sinalizador especifica o substituto para uma tecla de cada vez.
  • O --default_key_mappings dir sinalizador especifica um diretório com cinco chaves para substituir todas as chaves em build/target/product/security ; é equivalente a usar --key_mapping cinco vezes para especificar os mapeamentos.
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

Use o --extra_apks apk_name1,apk_name2,... = key bandeira para especificar as substituições chave de assinatura com base em nomes APK. Se key é deixado vazio, o trata de script os APKs especificados como pré-assinado.

Para o produto tardis hipotética, você precisa de seis teclas protegidas por senha: cinco para substituir a cinco em build/target/product/security , e um para substituir a chave adicional device/yoyodyne/security/special exigido por SpecialApp no exemplo acima. Se as chaves estivessem nos seguintes arquivos:

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

Em seguida, você assinaria todos os aplicativos como este:

./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

Isso traz o seguinte:

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.

Depois de avisar o usuário para senhas para todas as chaves protegidas por senha, o script re-sinais todos os arquivos APK no destino entrada .zip com as chaves de libertação. Antes de executar o comando, você também pode definir o ANDROID_PW_FILE variável de ambiente para um nome de arquivo temporário; o script então invoca seu editor para permitir que você insira senhas para todas as chaves (esta pode ser uma maneira mais conveniente de inserir senhas).

Substituição da chave de assinatura APEX

Android 10 introduz o formato de arquivo APEX para a instalação de módulos do sistema de nível inferior. Como explicado na assinatura APEX , cada arquivo APEX é assinado com duas chaves: uma para a imagem do sistema arquivo mini dentro de uma APEX eo outro para toda a APEX.

Ao assinar para liberação, as duas chaves de assinatura para um arquivo APEX são substituídas por chaves de liberação. A chave de carga do sistema de arquivos é especificado com o --extra_apex_payload bandeira e toda a chave de assinatura de arquivo APEX é especificado com o --extra_apks bandeira.

Para o produto tardis, suponha que você tem a seguinte configuração de chave para o com.android.conscrypt.apex , com.android.media.apex e com.android.runtime.release.apex arquivos 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"

E você tem os seguintes arquivos que contêm as chaves de lançamento:

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

O seguinte comando substitui as chaves de assinatura para com.android.runtime.release.apex e com.android.tzdata.apex durante a assinatura de liberação. Em particular, com.android.runtime.release.apex é assinado com as chaves de libertação especificada ( runtime_apex_container para o arquivo APEX, e runtime_apex_payload para a imagem de carga de arquivos). com.android.tzdata.apex é tratado como pré-assinado. Todos os outros arquivos APEX são tratados pela configuração padrão, conforme listado nos arquivos 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

A execução do comando acima fornece os seguintes 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)
        [...]

Outras opções

Os sign_target_files_apks assinatura regravações de script a descrição de construção e de impressão digital em arquivos de propriedades de compilação para refletir que a compilação é uma compilação assinado. O --tag_changes controles bandeira o que as edições são feitas com a impressão digital. Executar o script com -h para ver a documentação em todas as bandeiras.

Gerando chaves manualmente

Usa o Android chaves RSA de 2048 bits com expoente público 3. Você pode gerar certificados / pares de chaves privadas usando a ferramenta openssl a partir 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

O comando openssl PKCS8 dado acima cria um arquivo .pk8 sem senha, adequado para uso com o sistema de compilação. Para criar um .pk8 protegido com uma senha (que você deve fazer para todas as chaves de lançamento reais), substitua o -nocrypt discussão com -passout stdin ; então o openssl criptografará a chave privada com uma senha lida da entrada padrão. Nenhum prompt é impresso, portanto, se stdin for o terminal, o programa parecerá travar quando, na verdade, estiver apenas esperando que você digite uma senha. Outros valores podem ser usados ​​para o argumento-passout para ler a senha de outros locais; para mais detalhes, consulte a documentação do OpenSSL .

O arquivo intermediário temp.pem contém a chave privada sem qualquer tipo de proteção por senha, portanto, descarte-a com cuidado ao gerar chaves de liberação. Em particular, o utilitário GNUshred pode não ser eficaz em sistemas de arquivos de rede ou registrados. Você pode usar um diretório de trabalho localizado em um disco RAM (como uma partição tmpfs) ao gerar chaves para garantir que os intermediários não sejam inadvertidamente expostos.

Criação de arquivos de imagem

Depois de ter assinado-target-files.zip, você precisa criar a imagem para colocá-la em um dispositivo. Para criar a imagem assinada a partir dos arquivos de destino, execute o seguinte comando na raiz da árvore Android:

img_from_target_files signed-target-files.zip signed-img.zip
O arquivo resultante, signed-img.zip , contém todos os arquivos .img. Para carregar uma imagem sobre um dispositivo, o uso fastboot como se segue:
fastboot update signed-img.zip