[Anatomy of Android] Gestão de Certificados no Android

Existe um site que sou muito fã, que mesmo com seu pouco período de atividade (só 2 meses), publicou ótimos posts sobre a anatomia do nosso amigo robozinho. Por isso tomei a liberdade de traduzir as publicações e colocá-las aqui no blog. Ao final de cada tradução estará o link para a publicação original. Então vamos lá, e para começar vamos falar sobre como o android gerencia os seus certificados.

Boa leitura…

Esse post não é sobre certificados. Não é uma análise dos diferentes formatos de certificados de segurança nem como eles são gerados.

Esse post é sobre como o Android lida com certificados de segurança e como mudá-los para ter mais segurança.

Existem principalmente dois arquivos fonte que você precisa verificar para entender isso melhor (NativeCrypto.java e TrustedCertificateStore.java). Isso tudo faz parte do Apache Harmony para Android Open Source Project.

O Android, como qualquer outro sistema operacional móvel possui CA root para armazenamento de certificados de segurança, que usa para validar a identidade de seus pares remotos. É da mesma forma que um browser de internet faz. Existe um diretório (/etc/security/cacerts), onde o Android armazena os certificados. Sendo chamado de Certificates Store. Quando uma aplicação contata um servidor remoto, este envia suas identificações para o dispositivo Android. Então o Android valida ou rejeita-o com base nos certificados confiáveis armazenados no Certificates Store.

Certificados são formatados em PEM. Eles também incluem a versão de leitura para humanos (human readable). A forma como o Android nomeia esses certificados é utilizando um hash MD5, baseado em um valor único para o nome do certificado. Isso significa que o nome do arquivo para o certificado com o campo assunto igual a “C=US, O=GeoTrust Inc., CN=GeoTrust Global CA” é 7999be0d.0

Como nós podemos ver no próximo código TrustedCertificateStore.java, o método de pesquisa vai primeiro solicitar o hash MD5 e então vai realizar a busca no Certificates Store.

private String hash(X500Principal name) {
    int hash = NativeCrypto.X509_NAME_hash_old(name);
    return IntegralToString.intToHexString(hash, false, 8);
}

Como fazer isso mais seguro

Há algumas coisas que você pode fazer se você quiser seu Android mais seguro. E há razões para isso. Isso é algo que está totalmente quebrado e ninguém deve usá-lo mais. Apache Harmony fornece outro método para calcular o SHA1 em vez de MD5.

O algoritmo de hash MD5 está quebrado. É surpreendente que o Google ainda use esse algoritmo de hash MD5. Para fazer isso:

  1. Use NativeCrypto.x509_NAME_hash(name) em vez de NativeCrypto.X509_NAME_hash_old(name);
  2. Renomeie todos seus certificados para usar um nome baseado SHA1. Cuidado aqui se você usa openssl para fazer isso. Openssl gera um hash SHA1 diferente do que o Apache Harmony framework. Por que? Apache Harmony baseia o hash MD5 e SHA1 no nome da entidade do certificado. Antes de calcular o hash, que transforma essa sequência em um formato ASN1 DER. Isso é feito tanto para MD5 e SHA1 e é normal em diferentes frameworks.

A ferramenta de linha de comando openssl não se comporta assim. Criptografia é como lavagem de dinheiro, quanto mais mãos o dinheiro passar, mais difícil é, em teoria, rastreá-lo até sua origem. O pessoal da Openssl acreditava corretamente que SHA1 não era seguro o suficiente então eles decidiram passá-lo por mais um filtro. Ele primeiro calcula o formato CANONICAL da sequência. Então você pega essa sequência e gera o formato ASN1 DER dele. Em seguida, ele passa a sequência codificada com o algoritmo SHA1 para cálculo. Sim, bastante desagradável. Eu acreditava que a biblioteca openssl.1.0.1e já incluia todas essas mudanças. Mas se você estiver usando as mais antigas terá que modificá-los para poder calcular programaticamente o SHA1 de um certificado. Você pode ler um pouco mais sobre como fazer isso neste tópico da lista de discussão openssl.

Eu espero que eventualmente, melhor mais cedo ou mais tarde, que o Google decida ir para, pelo menos SHA1. Neste ponto SHA1 não é seguro, mais ei, isso é melhor do que MD5.

Atualização 17/09/2019: Historicamente o Android foi um grande usuário do Apache Harmony, porém desde o Android Nougat ele vem dependendo cada vez mais das bibliotecas do OpenJDK. Por isso algumas das informações desse post podem está desatualizadas.

Publicação original

Leave a Comment

Your email address will not be published. Required fields are marked *