Voltar ao blog
Segurança 8 min

Como implementar SSL Pinning no Android

10 de novembro de 2025

O que é SSL Pinning e por que ele importa

Em uma conexão HTTPS comum, o Android valida o certificado do servidor contra a lista de Autoridades Certificadoras (CAs) confiáveis do sistema operacional. Isso é suficiente para a maioria dos casos, mas cria um vetor de ataque: qualquer CA comprometida — ou um certificado instalado pelo usuário/atacante — pode ser usado para interceptar o tráfego.

SSL Pinning resolve isso fixando (pinando) o certificado ou a chave pública esperada diretamente no código do aplicativo. Se o certificado apresentado pelo servidor não corresponder ao que está "pinado", a conexão é recusada — mesmo que seja tecnicamente válido para o sistema operacional.

Isso é especialmente crítico em apps financeiros, de saúde e qualquer sistema que trafegue dados sensíveis.


Tipos de SSL Pinning

Certificate Pinning

Fija o certificado completo (arquivo .cer / .pem). É mais restritivo, mas exige atualização do app a cada renovação de certificado.

Public Key Pinning (recomendado)

Fija apenas a chave pública do certificado. Como a chave pública muda raramente (mesmo com renovação de certificado), essa abordagem requer menos manutenção e é considerada a melhor prática.


Implementação com OkHttp e CertificatePinner

A forma mais comum de implementar pinning no Android é via OkHttp, a biblioteca HTTP padrão do ecossistema.

1. Obtenha o hash da chave pública

# Extrai o hash SHA-256 da chave pública do certificado
openssl s_client -connect api.seudominio.com.br:443 -servername api.seudominio.com.br \
  </dev/null 2>/dev/null \
  | openssl x509 -pubkey -noout \
  | openssl pkey -pubin -outform der \
  | openssl dgst -sha256 -binary \
  | base64

O resultado será algo como: abc123XYZ456def789GHI012jkl345MNO678pqr901STU=

2. Configure o CertificatePinner

import okhttp3.CertificatePinner
import okhttp3.OkHttpClient

val certificatePinner = CertificatePinner.Builder()
    .add(
        "api.seudominio.com.br",
        "sha256/abc123XYZ456def789GHI012jkl345MNO678pqr901STU=",
        "sha256/BACKUP_HASH_AQUI=" // sempre inclua um pin de backup
    )
    .build()

val client = OkHttpClient.Builder()
    .certificatePinner(certificatePinner)
    .build()

3. Sempre inclua um pin de backup

Se o servidor precisar trocar de chave e você não tiver um pin de backup no app, todos os usuários da versão com o pin antigo perderão acesso até atualizarem o app. Por isso:

  • Gere antecipadamente um par de chaves de backup
  • Inclua o hash da chave pública de backup no CertificatePinner
  • Antes de rotacionar a chave principal, certifique-se de que a versão com o backup publicada alcançou a maioria dos usuários

Implementação via Network Security Config (Android 7+)

Outra abordagem, sem código Kotlin/Java, é usar o arquivo XML de configuração de segurança de rede:

<!-- res/xml/network_security_config.xml -->
<network-security-config>
    <domain-config>
        <domain includeSubdomains="false">api.seudominio.com.br</domain>
        <pin-set expiration="2026-12-31">
            <pin digest="SHA-256">abc123XYZ456def789GHI012jkl345MNO678pqr901STU=</pin>
            <!-- pin de backup obrigatório -->
            <pin digest="SHA-256">BACKUP_HASH_AQUI=</pin>
        </pin-set>
    </domain-config>
</network-security-config>

Declare no AndroidManifest.xml:

<application
    android:networkSecurityConfig="@xml/network_security_config"
    ...>

Vantagem: mais simples, configuração declarativa.
Desvantagem: a data de expiração exige atualização do app antes de vencer.


Proteção contra bypass

SSL Pinning por si só não é suficiente se o app puder ser manipulado. Em ambientes de alta segurança, combine com:

  • Root Detection — verificar se o dispositivo está rooteado (RootBeer, SafetyNet, Play Integrity)
  • Anti-debugging — detectar se um debugger está anexado
  • Obfuscação de código — usar ProGuard/R8 para dificultar engenharia reversa
  • Play Integrity API — atestar integridade do dispositivo e do app no servidor

Testando o pinning

Para validar que o pinning está funcionando, use o mitmproxy ou o Burp Suite:

  1. Instale o certificado do proxy no Android como CA confiável do usuário
  2. Configure o proxy no dispositivo
  3. Tente fazer uma requisição pelo app — ela deve ser recusada se o pinning estiver correto

Se a requisição passar, o pinning não está funcionando como esperado.


Conclusão

SSL Pinning é uma camada essencial de defesa em profundidade para apps que lidam com dados sensíveis. A abordagem de Public Key Pinning com OkHttp é a mais robusta e fácil de manter, desde que você sempre inclua pins de backup antes de qualquer rotação de chaves.

Combinado com Play Integrity, root detection e obfuscação de código, você eleva significativamente a barreira para ataques de interceptação de tráfego.

Gostou do conteúdo?

Se você está construindo um sistema nesta área, podemos ajudar. Fale com um especialista.

Agendar Consultoria
Como implementar SSL Pinning no Android — APCosta — APCosta