Code Signing (assinatura de código) é um mecanismo de assinatura digital para arquivos executáveis que garante a autenticidade do desenvolvedor e a integridade do aplicativo. No Android, cada arquivo APK deve ser assinado com um certificado antes da instalação no dispositivo ou publicação no Google Play. De acordo com Google, 2024, o Android suporta quatro gerações de esquemas de assinatura: desde v1 baseado em JAR até v4 para instalação por streaming.
Pontos principais
Code Signing é um processo criptográfico no qual o desenvolvedor assina o código executável com seu certificado digital. A assinatura é criada usando criptografia assimétrica: a chave privada do desenvolvedor gera uma assinatura digital, e a chave pública é incorporada ao certificado. Qualquer pessoa pode verificar a assinatura usando a chave pública, mas modificar o código sem quebrar a assinatura é impossível.
No desenvolvimento mobile, a assinatura de código desempenha três funções. Primeira — autenticação: o usuário e a plataforma podem identificar o desenvolvedor do aplicativo. Segunda — integridade: qualquer alteração no APK após a assinatura invalida a assinatura. Terceira — atualização confiável: a plataforma só permite atualizar um aplicativo com APKs assinados com o mesmo certificado da versão instalada.
A assinatura digital de aplicativos Android tem importância legal. De acordo com a legislação russa (63-FZ) e a europeia eIDAS, uma assinatura eletrônica qualificada equivale a uma assinatura manuscrita. No entanto, assinar um APK com um certificado autoassinado (prática comum no Android) não é qualificado — ele confirma a integridade, mas não a identidade do desenvolvedor do ponto de vista legal.
O Android suporta quatro esquemas de assinatura APK, cada um resolvendo os problemas da versão anterior e adicionando novos recursos. Todos os esquemas podem coexistir em um único APK — isso é necessário para compatibilidade reversa com versões antigas do Android.
O esquema v1 (JAR signing) apareceu no Android 1.0. Ele assina arquivos individuais dentro do arquivo APK usando entradas em META-INF/MANIFEST.MF. A desvantagem: um invasor pode modificar o APK (adicionar ou remover arquivos) e reassinar apenas os modificados sem tocar no restante. Isso torna o v1 vulnerável a certos ataques. O esquema v2 (APK Signature Scheme), introduzido no Android 7.0, assina todo o arquivo APK como um todo, incluindo todos os bytes exceto a própria assinatura, eliminando a possibilidade de modificação seletiva.
| Esquema | Android | Característica | Rotação de chave |
|---|---|---|---|
| v1 (JAR) | 1.0+ | Assinatura por arquivo | Não |
| v2 | 7.0+ | Assinatura completa do APK | Não |
| v3 | 9.0+ | Assinatura + rotação | Sim |
| v4 | 11.0+ | Streaming + ADB | Sim |
O esquema v3, introduzido no Android 9.0, resolve um problema antigo: o que fazer se a chave de assinatura for comprometida ou expirar? Anteriormente, alterar a chave de assinatura significava que o aplicativo era tratado como novo — não podia ser instalado sobre um existente. O v3 adiciona um mecanismo de rotação: o APK pode incluir uma prova de rotação (proof-of-rotation), assinada pela chave antiga. O sistema verifica a cadeia e permite atualizar o aplicativo assinado com a nova chave.
Keystore é um contêiner seguro que contém chaves privadas e certificados para assinar aplicativos. No desenvolvimento Android, usa-se o formato JKS (Java KeyStore) ou PKCS12. O keystore é criado com o utilitário keytool, que faz parte do JDK. Cada chave no repositório é identificada por um alias e protegida por uma senha.
O certificado em um keystore contém a chave pública e informações do proprietário: nome da organização, país, período de validade. Para aplicativos Android, o certificado pode ser autoassinado — o Google não exige uma autoridade certificadora (CA), o que diferencia o Android do iOS. No entanto, a validade do certificado deve ser de pelo menos 25 anos, pois o aplicativo será atualizado com a mesma chave.
# Criando um novo keystore para assinatura
keytool -genkey -v -keystore my-release.keystore \
-alias my-app-alias \
-keyalg RSA \
-keysize 2048 \
-validity 10000
# Visualizando o conteúdo do keystore
keytool -list -v -keystore my-release.keystore
O Android suporta dois algoritmos para chaves de assinatura: RSA e ECDSA. RSA com tamanho de chave de 2048 bits é o padrão de fato, suportado por todas as versões do Android. ECDSA (Algoritmo de Assinatura Digital com Curva Elíptica) com a curva P-256 fornece a mesma força criptográfica com um tamanho de chave menor. Desde o Android 9.0, recomenda-se o ECDSA, pois é mais rápido na verificação em dispositivos móveis.
No Android Gradle Plugin, a assinatura é configurada através do bloco signingConfigs no build.gradle do nível do módulo. Para compilações de depuração, o Android Studio cria automaticamente um keystore de depuração com senhas conhecidas. Para compilações de lançamento, o desenvolvedor especifica o caminho para seu keystore, o alias da chave e as senhas. Recomenda-se armazenar as senhas em arquivos de configuração separados, excluídos do controle de versão.
Uma prática moderna é o gerenciamento centralizado de assinatura via CI/CD. Jenkins, GitLab CI ou GitHub Actions podem armazenar o keystore como um artefato protegido e as senhas como segredos de ambiente. Isso evita vazamento de chaves através do repositório e simplifica a rotação de chaves quando necessário.
// build.gradle (nível do app) — configuração de assinatura
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 compatibilidade, um APK deve ser assinado com todos os três esquemas (v1 + v2 + v3). O Android Gradle Plugin inclui todos os esquemas por padrão. APKs assinados apenas com v2 não serão instalados no Android 6.0 e versões anteriores. APKs apenas com v1 não obterão os benefícios de integridade do v2 no Android 7.0+. Incluir todos os esquemas não aumenta o tamanho do APK em mais de 1–2% e garante compatibilidade com qualquer dispositivo.
Play App Signing é um serviço do Google Play que gerencia centralizadamente as chaves de assinatura de aplicativos. O desenvolvedor envia um APK assinado com uma chave de upload (upload key) para o Google Play Console, e o Google Play o reassina com uma chave de distribuição (distribution key) antes de entregá-lo aos usuários. Isso protege a chave de distribuição contra perda ou comprometimento.
Vantagens do Play App Signing: segurança — a chave de distribuição é armazenada no armazenamento protegido do Google; rotação — pode-se solicitar uma alteração de chave através do console; recuperação — se a chave de upload for perdida, uma nova pode ser gerada. Desvantagem: para aplicativos que existiam antes da introdução do Play App Signing, a migração exige a criação de um novo aplicativo, pois a chave de distribuição antiga já está em uso.
# Obtendo a impressão digital do certificado (SHA-256)
keytool -list -v -keystore my-release.keystore \
-alias my-app-alias | grep "SHA256"
# Verificando a assinatura do APK com apksigner
apksigner verify --verbose app-release.apk
Se a chave de assinatura for perdida e o Play App Signing não estiver sendo usado, é impossível restaurar a capacidade de atualizar o aplicativo — será necessário criar um novo aplicativo com um novo nome de pacote. Esta é uma das principais razões para usar o Play App Signing. O Google recomenda manter uma cópia de backup do keystore em um armazenamento offline seguro (unidade USB criptografada, cofre bancário).
Ao instalar um APK, o Android realiza a verificação de assinatura em várias etapas. Primeira — verificação do certificado: se expirou e o formato está correto. Segunda — verificação da assinatura: se a assinatura criptográfica corresponde ao conteúdo do APK. Terceira — comparação do certificado com a versão instalada: se o aplicativo já existe no dispositivo, o certificado deve corresponder, caso contrário a instalação é bloqueada.
O sistema de verificação está integrado no PackageManagerService. Ao processar uma solicitação de instalação, o PMS extrai a assinatura do APK, verifica-a usando a classe android.util.PackageParser e a compara com a assinatura armazenada do aplicativo instalado (se existir). Em caso de incompatibilidade, o usuário recebe o erro “INSTALL_FAILED_UPDATE_INCOMPATIBLE”. Esse mecanismo previne ataques de substituição (malware não pode substituir um aplicativo legítimo por sua própria versão).
Um desenvolvedor pode verificar independentemente a assinatura do APK usando o utilitário apksigner do Android SDK Build Tools. O comando apksigner verify --verbose app.apk mostra com quais esquemas o APK está assinado, se os certificados são válidos e se as assinaturas correspondem ao conteúdo. Para verificação programática da assinatura de um aplicativo instalado, usa-se PackageManager.getPackageInfo() com a flag GET_SIGNATURES.
// Verificação programática da assinatura de um aplicativo instalado
fun getAppSignature(context: Context, packageName: String): String? {
val pm = context.packageManager
val info = pm.getPackageInfo(
packageName,
PackageManager.GET_SIGNATURES
)
return info.signatures?.firstOrNull()?.toCharsString()
}
A segurança da chave de assinatura é um aspecto crítico do desenvolvimento Android. O comprometimento da chave permite que um invasor assine atualizações do seu aplicativo com seu próprio código. As regras principais: nunca armazene a chave em um repositório, não use uma mesma chave para diferentes aplicativos, não transfira a chave por canais não seguros (e-mail, mensageiros).
A prática recomendada é a separação de chaves. Use uma chave separada para cada aplicativo e uma chave separada para upload no Google Play (upload key). Para compilações de depuração, o Android Studio cria um debug.keystore compartilhado — ele não deve ser usado para compilações de lançamento. A validade do certificado deve ser de 25 a 30 anos (padrão atual, confirmado pelo Google).
| Prática | Recomendação |
|---|---|
| Armazenamento de chave | Mídia criptografada, segredos CI/CD |
| Validade do certificado | Pelo menos 25 anos |
| Algoritmo | RSA 2048+ ou ECDSA P-256 |
| Separação | Chave separada por aplicativo |
| Backup | Cópia offline do keystore |
Verifique regularmente a integridade da cadeia de assinatura. Quando funcionários com acesso às chaves saem, atualize a chave de upload através do Google Play Console. Use ferramentas como a Google Play Integrity API para verificar se seu aplicativo não foi adulterado nos dispositivos dos usuários. A API retorna dados sobre a assinatura e integridade, enviando-os ao servidor para verificação.
Perguntas frequentes
Code Signing é uma assinatura digital de um arquivo APK que confirma que o aplicativo foi criado por um desenvolvedor específico e não foi modificado após a assinatura. Sem assinatura, o APK não será instalado no dispositivo.
Use o utilitário keytool do JDK: keytool -genkey -v -keystore my-release.keystore -alias my-alias -keyalg RSA -keysize 2048 -validity 10000. Especifique o keystore resultante no build.gradle no bloco signingConfigs.
Se a chave for perdida e você não estiver usando o Play App Signing, a atualização do aplicativo se torna impossível. Você terá que criar um novo aplicativo no Google Play com um novo nome de pacote. Use o Play App Signing para se proteger contra perda de chave.
v1 assina cada arquivo dentro do APK individualmente — um invasor pode modificar um arquivo e reassinar apenas esse. v2 assina o APK inteiro como um todo — qualquer alteração invalida a assinatura, proporcionando um nível mais alto de segurança.
Play App Signing é um serviço do Google Play que armazena centralizadamente a chave de distribuição dos aplicativos. O desenvolvedor envia um APK assinado com uma chave de upload, e o Google o reassina antes de entregar aos usuários, protegendo a chave contra perda ou roubo.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também