Warning! The SafetyNet Attestation API is deprecated and has been replaced by the Play Integrity API. Learn more.

API SafetyNet Attestation

A API SafetyNet Attestation é uma API antiabuso que permite que os desenvolvedores de apps avaliem o dispositivo Android em que o app deles está sendo executado. A API precisa ser usada como parte do seu sistema de detecção de abuso para ajudar a determinar se seus servidores estão interagindo com seu aplicativo original em execução em um dispositivo Android genuíno.

A API SafetyNet Attestation fornece um atestado assinado criptograficamente, que avalia a integridade do dispositivo. Para criar o atestado, a API examina o ambiente de software e hardware do dispositivo, procurando problemas de integridade e o comparando com os dados de referência para dispositivos Android aprovados. O atestado gerado está vinculado ao nonce que o app autor da chamada fornece. O atestado também contém um carimbo de data/hora de geração e metadados sobre o app solicitante.

A API não foi projetada para os seguintes casos de uso:

  • Atuar como mecanismo autônomo antiabuso ou de segurança de apps. Use-a em combinação com as práticas recomendadas para segurança de apps e o conjunto de indicadores antiabuso específicos do produto.
  • Funcionar quando o dispositivo não está conectado à Internet. Nesse caso, a API retorna um erro.
  • Ter a resposta interpretada diretamente no app de chamada. Mova toda a lógica de decisão antiabuso para um servidor sob seu controle.
  • Fornecer indicadores minuciosos sobre as modificações do sistema. A API oferece valores booleanos que expressam diferentes níveis de integridade do sistema.
  • Conter sinais para casos de uso específicos de aplicativos, como identificadores de dispositivos, status de emulação de GPS e status de bloqueio de tela.
  • Substituir ou implementar verificações fortes de DRM.
  • Apenas verificar se o dispositivo tem acesso root. A API foi projetada para verificar a integridade geral do dispositivo.

Visão geral

A API SafetyNet Attestation usa o seguinte fluxo de trabalho:

  1. A API SafetyNet Attestation recebe uma chamada do seu app. Essa chamada inclui um valor de uso único.
  2. O serviço SafetyNet Attestation avalia o ambiente de execução e solicita um atestado assinado dos resultados da avaliação dos servidores do Google.
  3. Os servidores do Google enviam o atestado assinado ao serviço SafetyNet Attestation do dispositivo.
  4. O serviço SafetyNet Attestation retorna esse atestado assinado ao seu aplicativo.
  5. Seu app encaminha o atestado assinado para o servidor.
  6. Esse servidor valida a resposta e a usa para decisões antiabuso. Seu servidor comunica as descobertas ao seu aplicativo.

Uma representação gráfica desse processo é mostrada na Figura 1:

Figure 1. Protocolo da API SafetyNet Attestation

Observação: outros documentos e lista de verificação

Durante a inicialização, configuração e ativação da API SafetyNet Attestation e de forma complementar a esta documentação principal, esteja ciente das seguintes recomendações e as obedeça:

Receber uma chave de API

Para chamar os métodos da API SafetyNet Attestation, use uma chave de API. Para criar uma chave e incorporá-la, siga as seguintes etapas:

  1. Acesse a página da Biblioteca no Console de APIs do Google.
  2. Procure e selecione a API Android Device Verification. A tela do painel dessa API será exibida.
  3. Se a API não estiver habilitada, clique em Ativar.
  4. Se o botão Criar credenciais for exibido, clique nele para gerar uma chave de API. Caso contrário, clique na lista suspensa Todas as credenciais de API e, em seguida, selecione a chave de API associada ao seu projeto que ativou a API Android Device Verification.
  5. Na barra lateral à esquerda, clique em Credenciais. Copie a chave de API que será exibida.
  6. Use essa chave de API ao chamar o método attest() da classe SafetyNetClient.

Depois de criar essa chave de API, entre na lista de e-mails dos clientes da API SafetyNet.

Monitoramento e cota da API

Importante: a atribuição de cota padrão (por projeto) para chamar a API SafetyNet Attestation é de 10.000 solicitações por dia.

Se seu app precisar de uma cota maior, faça uma solicitação antes da implantação do app para os usuários. Para isso, siga estas etapas:

  1. Leia a documentação fornecida para a API. As solicitações que não estiverem em conformidade com as práticas recomendadas poderão ser rejeitadas.
  2. Preencha o formulário de solicitação de cota (link em inglês).
  3. Aguarde um e-mail de confirmação indicando quando sua solicitação foi processada. Geralmente, você pode esperar que sua solicitação seja processada em dois ou três dias úteis.

Observação: independentemente da cota provisionada para seu projeto, as instâncias de apps individuais são limitadas a um máximo de cinco solicitações por minuto. Se o limite for excedido, todas as solicitações restantes durante esse minuto retornarão um erro.

Tenha esse comportamento em mente ao implementar o mecanismo de nova tentativa do seu app.

Independentemente da cota de API do seu app, recomendamos definir um monitoramento e alertas de cota.

Verificar a versão do Google Play Services

Antes de usar a API SafetyNet Attestation, é imprescindível garantir que a versão correta do Google Play Services esteja instalada no dispositivo do usuário. Se uma versão incorreta estiver instalada, o app poderá parar de responder depois de chamar a API. Se o app detectar que uma versão incorreta está instalada, peça ao usuário para atualizar o Google Play Services no dispositivo dele.

Para verificar se a versão instalada do Google Play Services é compatível com a versão do SDK do Android que está sendo usada, chame o método isGooglePlayServicesAvailable(), como mostrado no snippet de código a seguir:

if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
            == ConnectionResult.SUCCESS) {
      // The SafetyNet Attestation API is available.
    } else {
      // Prompt user to update Google Play services.
    }
    

Em dispositivos que executam o Google Play Services 13.0 e versões mais recentes, a API SafetyNet Attestation também é compatível com chaves de API restritas a apps. Esse recurso reduz o risco de uso acidental ou não autorizado de chaves de API com restrição de cota. Para usar esse recurso opcional, verifique se a versão mínima do Google Play Services do dispositivo é pelo menos a versão 13.0, conforme mostrado no snippet de código a seguir:

if (GoogleApiAvailability.getInstance()
        .isGooglePlayServicesAvailable(context, 13000000) ==
        ConnectionResult.SUCCESS) {
      // The SafetyNet Attestation API is available.
    } else {
      // Prompt user to update Google Play Services.
    }
    

Solicitar um atestado SafetyNet

Depois de conseguir uma chave de API válida para a API Android Device Verification no Console de APIs do Google, o app pode usar o serviço SafetyNet Attestation. Para isso, realize as seguintes etapas:

  1. Tenha um nonce.
  2. Solicite um atestado SafetyNet.
  3. Transfira a resposta para seu servidor.
  4. Use a resposta no seu servidor, assim como seus outros indicadores antiabuso, para controlar o comportamento do seu app.

Para manter seu app responsivo, execute essas etapas fora da linha de execução principal dele. Para saber mais sobre como criar linhas de execução diferentes, consulte Enviar operações para várias linhas de execução.

Realize essa verificação para proteger todas as ações importantes no app, incluindo logins, eventos de compra e aquisição de novos produtos no aplicativo. As chamadas para a API SafetyNet Attestation aumentam a latência, o uso de dados móveis e o uso da bateria. Por isso, o interessante é encontrar um equilíbrio entre segurança e usabilidade. Por exemplo, você pode decidir solicitar um atestado SafetyNet após o login e executar verificações posteriores a cada 30 minutos, no máximo. Também é possível permitir que seu servidor decida quando o app solicitará um atestado para que os adversários tenham mais dificuldade em prever o momento da verificação.

Ter um nonce

Transmita um nonce ao chamar a API SafetyNet Attestation. O atestado resultante contém esse nonce, permitindo que você determine que o atestado pertence à chamada de API e não é repetido por um invasor.

Um nonce usado com uma solicitação SafetyNet precisa ter pelo menos 16 bytes. Introduza a variabilidade no seu nonce, garantindo que o mesmo nonce nunca seja usado duas vezes. Como prática recomendada, extraia parte do nonce a partir dos dados enviados aos seus servidores. Por exemplo, concatene o hash do nome de usuário com o carimbo de data/hora da solicitação para formar o nonce.

Importante: inclua o máximo de dados possível no nonce. Ao fazer isso, você torna mais difícil para os invasores realizar ataques iguais. Por exemplo, derivar o nonce do nome de usuário limita os ataques iguais à mesma conta. No entanto, derivar o nonce de todos os detalhes de um evento de compra limita o uso da mensagem de resposta da API a esse evento de compra.

Ao receber a resposta assinada da API, sempre compare o nonce na resposta assinada com a que você reconstruir a partir do restante da mensagem enviada aos seus servidores. Essa verificação garante que os invasores não possam reutilizar atestados assinados coletados de dispositivos adequados para outras solicitações de intuito malicioso.

Para saber mais sobre o uso de funções de criptografia, consulte o guia sobre como usar criptografia.

Solicitar o atestado

Depois de estabelecer uma conexão com o Google Play Services e criar um valor de uso único, estará tudo pronto para fazer uma solicitação de atestado da SafetyNet. A resposta à sua solicitação pode não ser imediata, então é recomendável configurar um listener de callback para gerenciar a resposta do serviço. Veja um exemplo de listener no snippet de código a seguir:

Kotlin

    SafetyNet.getClient(this).attest(nonce, API_KEY)
        .addOnSuccessListener(this) {
            // Indicates communication with the service was successful.
            // Use response.getJwsResult() to get the result data.
        }
        .addOnFailureListener(this) { e ->
            // An error occurred while communicating with the service.
            if (e is ApiException) {
                // An error with the Google Play services API contains some
                // additional details.
                val apiException = e as ApiException

                // You can retrieve the status code using the
                // apiException.statusCode property.
            } else {
                // A different, unknown type of error occurred.
                Log.d(FragmentActivity.TAG, "Error: " + e.message)
            }
        }
    

Java

    // The nonce should be at least 16 bytes in length.
    // You must generate the value of API_KEY in the Google APIs dashboard.
    SafetyNet.getClient(this).attest(nonce, API_KEY)
        .addOnSuccessListener(this,
            new OnSuccessListener<SafetyNetApi.AttestationResponse>() {
                @Override
                public void onSuccess(SafetyNetApi.AttestationResponse response) {
                    // Indicates communication with the service was successful.
                    // Use response.getJwsResult() to get the result data.
                }
            })
        .addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // An error occurred while communicating with the service.
                if (e instanceof ApiException) {
                    // An error with the Google Play services API contains some
                    // additional details.
                    ApiException apiException = (ApiException) e;
                    // You can retrieve the status code using the
                    // apiException.getStatusCode() method.
                } else {
                    // A different, unknown type of error occurred.
                    Log.d(TAG, "Error: " + e.getMessage());
                }
            }
        });
    

O método onSuccess() indica que a comunicação com o serviço foi bem-sucedida, mas não indica se o dispositivo transmitiu o atestado SafetyNet. A próxima seção discute como ler o resultado do atestado e verificar a integridade dele.

Transferir a resposta do atestado SafetyNet para seu servidor

Quando seu app se comunica com a SafetyNet, o serviço fornece uma resposta contendo o resultado do atestado SafetyNet e inclui mais informações para ajudar a verificar a integridade da mensagem. O resultado é fornecido como um objeto SafetyNetApi.AttestationResponse. Use esse o método getJwsResult() desse objeto para receber os dados da solicitação. A resposta é formatada como uma JSON Web Signature (JWS) (link em inglês).

Envie o objeto JWS de volta ao seu servidor para validação e uso.

Usar a resposta do atestado SafetyNet no seu servidor

O seguinte trecho da JWS mostra o formato e conteúdo de amostra dos dados de payload:

{
      "timestampMs": 9860437986543,
      "nonce": "R2Rra24fVm5xa2Mg",
      "apkPackageName": "com.package.name.of.requesting.app",
      "apkCertificateDigestSha256": ["base64 encoded, SHA-256 hash of the
                                      certificate used to sign requesting app"],
      "ctsProfileMatch": true,
      "basicIntegrity": true,
    }
    

O payload de um atestado assinado geralmente contém os seguintes campos:

Carimbo de data/hora da resposta

  • timestampMs: milissegundos após a época do UNIX em que a mensagem de resposta do JWS foi gerada pelos servidores do Google.

Dados fornecidos pelo app de chamada

  • nonce: token de uso único que o app de chamada transmite para a API.

Dados sobre o app de chamada

  • apkPackageName: nome do pacote do app de chamada.
  • apkCertificateDigestSha256: representações codificadas de base 64 do hash SHA-256 para os certificados de assinatura do app de chamada

Veredito de integridade

  • ctsProfileMatch: veredito mais rigoroso da integridade do dispositivo. Se o valor de ctsProfileMatch é true, o perfil do dispositivo que executa o app corresponde ao perfil de um dispositivo que passou no teste de compatibilidade do Android.
  • basicIntegrity: um veredito mais brando da integridade do dispositivo. Se apenas o valor de basicIntegrity é true, o dispositivo que executa o app provavelmente não foi adulterado. No entanto, o dispositivo não necessariamente passou no teste de compatibilidade do Android.

    Para mais informações sobre os testes de compatibilidade do Android, consulte Projetar um dispositivo Android e Teste de compatibilidade do Android (CTS, na sigla em inglês).

Campos opcionais

  • error: informações de erro codificadas relevantes para a solicitação de API atual.
  • advice: sugestão de como recuperar o bom estado de um dispositivo.

Possíveis vereditos de integridade

A mensagem JWS contém dois parâmetros que indicam o resultado da verificação de compatibilidade do dispositivo: ctsProfileMatch e basicIntegrity. O status do dispositivo que executa seu app pode afetar o valor de cada parâmetro, conforme mostrado na Tabela 1:

Tabela 1. Exemplos de como o status do dispositivo pode afetar os valores de basicIntegrity e ctsProfileMatch

Status do dispositivo Valor de ctsProfileMatch Valor de basicIntegrity
Dispositivo autêntico certificado e aprovado no CTS true true
Dispositivo certificado com carregador de inicialização desbloqueado false true
Dispositivo autêntico, mas não certificado, como quando o fabricante não solicita a certificação false true
Dispositivo com ROM personalizada (sem acesso root) false true
Emulador false false
Nenhum dispositivo, como um script de emulação de protocolo false false
Indicadores de comprometimento da integridade do sistema, um dos quais pode estar impedindo o acesso root false false
Indicadores de outros ataques ativos, como hooking de API false false

Casos de erro

A mensagem JWS também pode mostrar vários tipos de condições de erro:

  • Um resultado null indica que a chamada para o serviço não foi concluída.
  • Um parâmetro de erro na JWS indica que ocorreu um problema, como um erro de rede ou um erro que um invasor simulou. A maioria dos erros é transitória e desaparecerá se você fizer outra chamada para o serviço. Tente novamente mais algumas vezes aumentando o tempo entre cada nova tentativa.
  • Se o dispositivo for adulterado, isto é, se basicIntegrity for definida como falsa na resposta, o veredito poderá não conter dados sobre o app de chamada, como apkPackageName e apkCertificateDigestSha256. Isso ocorre quando nossos sistemas não conseguem determinar o app de chamada de forma confiável.

O que fazer quando o atestado assinado informar um erro?

  • Tentar novamente. Erros em dispositivos legítimos são temporários e desaparecem se você fizer outra chamada para o serviço.
  • Verifique se seu app não chama a API mais de cinco vezes por segundo nos dispositivos afetados e se a cota de API do seu projeto ainda não foi esgotada.
  • Presuma que possa ser um invasor provocando intencionalmente um caso de erro para mascarar a atividade dele.

Parâmetro de aconselhamento para transmitir verificações futuras

Quando presente, o parâmetro advice oferece informações para ajudar a explicar por que a API SafetyNet Attestation definiu ctsProfileMatch ou basicIntegrity como falso em um determinado resultado. O valor do parâmetro contém uma lista de strings, como as do exemplo a seguir:

{"advice": "LOCK_BOOTLOADER,RESTORE_TO_FACTORY_ROM"}
    

No seu app, você pode traduzir os valores no parâmetro de aconselhamento em mensagens fáceis para ajudar o usuário a transmitir futuros atestados SafetyNet, conforme mostrado na lista a seguir:

LOCK_BOOTLOADER
O usuário precisa bloquear o carregador de inicialização do dispositivo.
RESTORE_TO_FACTORY_ROM
O usuário precisa restaurar o dispositivo para uma ROM de fábrica limpa.

Verificar a resposta do atestado SafetyNet

Tome medidas para garantir que a resposta do atestado SafetyNet seja proveniente do serviço SafetyNet e inclua dados que correspondam à sua solicitação.

Para verificar a origem da mensagem JWS, siga as seguintes etapas:

  1. Extraia a cadeia de certificados SSL da mensagem JWS.
  2. Valide a cadeia de certificados SSL e use um nome de host SSL correspondente para verificar se o certificado de folha foi emitido para o nome de host attest.android.com.
  3. Use o certificado para verificar a assinatura da mensagem JWS.
  4. Verifique os dados da mensagem JWS para confirmar se ela corresponde aos dados da solicitação original. Verifique especialmente se o carimbo de data/hora foi validado e se o valor de uso único, o nome do pacote e os hashes do certificado de assinatura do app correspondem aos valores esperados.

Verifique a declaração JWS usando soluções de criptografia padrão, como as encontradas no uso da API de amostra android-play-safetynet (link em inglês), disponível no GitHub.

Durante os testes e o desenvolvimento iniciais, mas não na produção, você pode chamar uma API on-line para verificar a assinatura da declaração JWS. Esse processo também foi mostrado no uso da API de amostra android-play-safetynet (link em inglês), disponível no GitHub. Observe que a API de verificação on-line é exclusiva para testes em estágio inicial, e você tem uma cota fixa de 10.000 solicitações por dia.

Importante: o uso da API de verificação on-line só valida que a mensagem JWS foi assinada pelos servidores da API SafetyNet Attestation. Essa API on-line não pode verificar se os campos no payload correspondem aos valores esperados pelo seu serviço.

Como se preparar para situações inesperadas

Recomendamos que você planeje seu uso de forma que ele considere as mudanças e interrupções.

Mudanças na API
Campos novos (experimentais) podem aparecer no veredito a qualquer momento. Esses campos extras não podem interromper o analisador ou a lógica de uso. Em especial, não confie em campos experimentais antes de eles serem anunciados na lista de e-mails de clientes da API SafetyNet.
A API SafetyNet Attestation está inativa

No caso improvável da API SafetyNet Attestation ficar indisponível, é altamente recomendado que os usuários dessa API criem recursos no lado do servidor para controlar dinamicamente a dependência da disponibilidade, bem como a qualidade dessa API e da resposta dela.

As estratégias comuns precisam incluir a capacidade de instruir seus apps dinamicamente a parar de chamar essa API, assim como instruir listas de permissões com base em dispositivos e usuários a ignorar os resultados da API SafetyNet Attestation para determinados tipos de dispositivos e usuários.

Código de amostra

Para mais orientações sobre como trabalhar com as APIs SafetyNet, veja a amostra de código (link em inglês) que está disponível no GitHub.

Lista de comunicados

É altamente recomendável participar da lista de e-mails de clientes da API SafetyNet para receber atualizações sobre a API SafetyNet Attestation.

Feedback

Forneça seu feedback (link em inglês) para essa API. Usaremos seus comentários para priorizar novos recursos para ela.

Saiba mais

Para saber mais sobre as práticas recomendadas ao usar a API SafetyNet Attestation, consulte os seguintes links:

Outros Termos de Serviço

Ao acessar ou usar as APIs SafetyNet, você concorda com os Termos de Serviço das APIs do Google e com estes Outros Termos. Leia e entenda todos os termos e políticas aplicáveis antes de acessar as APIs.

Termos de Serviço da SafetyNet

Assim como acontece com todos os dados coletados em grande volume por meio da observação em campo, há uma chance de haver falsos positivos e falsos negativos. Apresentamos os dados da melhor forma possível. Testamos extensivamente nossos mecanismos de detecção para garantir a precisão e estamos comprometidos em melhorar esses métodos ao longo do tempo para garantir que eles continuem sendo precisos.

Você aceita obedecer a todas as leis, regulamentações e direitos de terceiros aplicáveis, incluindo, sem limitação, leis relativas à importação ou exportação de dados ou leis locais, de software e de privacidade. Você não usará as APIs para incentivar ou promover atividades ilegais ou violações de direitos de terceiros. Você não violará nenhum outro termo de serviço do Google (ou dos afiliados dele).

Você reconhece e entende que a API Safetynet funciona coletando informações de hardware e software, como dados de dispositivos e aplicativos e os resultados dos atestados da SafetyNet, e enviando esses dados ao Google para análise. Conforme a Seção 3(d) dos Termos de Serviço das APIs do Google, você concorda que, ao usar as APIs, é sua responsabilidade fornecer os avisos ou consentimentos necessários para coleta e compartilhamento desses dados com o Google.