Segurança moderna no Android (parte 2)

Tempo de leitura: 4 minutes

No último post desta série falamos sobre o Google trabalhando em uma nova biblioteca que será entregue no Android Jetpack: androidx.security:security-crypto
Bem, o tempo passou e, finalmente, security-crypto está agora em uma fase de alpha a lançamento!

Então agora é: androidx.security:security-crypto:1.1.0-alpha02

 

Você pode perguntar por que precisamos ter uma nova biblioteca para criptografia se já temos android.security.keystore, o que nos dá a chance de criar uma chave de dois tipos, um par de chaves assimétricas ou chaves simétricas, esta nova biblioteca usa o builder pattern fornecido pelo Keystore, mas em um estilo diferente, para fornecer configurações seguras para a criação de chaves, levando em consideração que precisamos de uma boa criptografia com bom desempenho.

Então, no iOS, existe algo chamado KeyChain, ele armazena chaves e valores para os usuários, no Android, temos KeyStore, e uma das coisas que você precisa saber é que você precisa criar um Provider para isso. O sistema Android Keystore permite armazenar chaves criptográficas em um contêiner para dificultar a extração do dispositivo. Uma vez que as chaves estão no Keystore, elas podem ser usadas para operações criptográficas com o material da chave permanecendo não exportável. Além disso, oferece recursos para restringir quando e como as chaves podem ser usadas, como exigir autenticação do usuário para uso da chave ou restringir chaves para serem usadas apenas em determinados modos criptográficos.

 

Como funciona?

O KeyStore tem duas coisas a proteger, a própria chave e a “chave” que se refere ao valor. Usar o KeyStore significa que você não vazará nenhuma informação em seu aplicativo, porque o material da chave nunca entra no processo de aplicação. Quando seu aplicativo deseja realizar alguma operação criptográfica, por trás da cifra são alimentados um processo do sistema que realiza as operações criptográficas.

O que é um sistema apoiado por hardware?

Usando o KeyStore, você pode vincular esse processo ao hardware seguro, há tantos deles, mas basicamente é um TEE (ambiente de execução confiável), que é um domínio de execução isolado que fornece recursos de segurança quando esse recurso é habilitado para uma chave que o material nunca é exposto fora do hardware seguro. Se o sistema operacional Android estiver comprometido ou um invasor puder ler o armazenamento interno do dispositivo, o invasor poderá usar qualquer chave do Android Keystore do aplicativo no dispositivo Android, mas não extraí-las do dispositivo.
O problema da criptografia no Android

De alguma forma, a clareza do processo de criptografia e descriptografia não era clara o suficiente, a quantidade de um algoritmo suportado por diferentes versões do SDK do Android e o número de bytes suportados por esses algoritmos eram informações demais. Por exemplo, o uso da API Keychain é sobre credenciais de todo o sistema. Quando um aplicativo solicita o uso de qualquer credencial, os usuários podem escolher quais credenciais um aplicativo pode acessar. Mas o provedor Keystore permite que um aplicativo individual armazene as credenciais que apenas o próprio aplicativo pode acessar.

O KeyStore foi introduzido na API 1 do Android, mas o Android KeyStore Provider foi introduzido até a API 18, mais tarde com a API 28, o Google introduziu o StrongBox para dispositivos com um Chip Seguro, embora a solução mencionada TEE seja boa o suficiente, este mecanismo de uso um Elemento Seguro (SE) é o mais seguro, pois é baseado em um chip diferente (CPU, memória, armazenamento) projetado para fins de segurança, isso aumentará o tempo das operações, mas é provavelmente a forma mais segura de fazê-lo.

Na próxima essência, você pode ver como criar um certificado autoassinado e uma chave para começar a usá-lo

KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore").apply {
    val certBuilder = KeyGenParameterSpec.Builder(alias, KeyProperties.PURPOSE_ENCRYPT)
        .setKeyValidityStart(keyValidityStart)
        .setKeyValidityEnd(keyValidityEnd)
        .setCertificateSerialNumber(BigInteger.valueOf(1L))
        .setCertificateSubject(X500Principal("CN=MyCompany"))
        .setUserAuthenticationRequired(true)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        initialize(
            certBuilder
                .setIsStrongBoxBacked(true) 
                .build()
        )
    } else {
        initialize(certBuilder.build())
    }
}.also {
    val keyPair = it.generateKeyPair()
    //Continue here
}

 

O que torna o androidx.security diferente?

Não é que KeyStore e Jetpack Security sejam diferentes, eles são um complemento um do outro, a nova biblioteca usa KeyStore para implementar um sistema de operação de duas etapas de chaves e chaves mestras com a adição de que você pode usá-lo para criptografar facilmente um arquivo ou um preferência compartilhada.

  • A primeira etapa é a parte azul que representa a chave que vamos criar para criptografar os dados, e os dados que queremos criptografar (pode ser um arquivo ou preferência compartilhada [Mapa de valor-chave]), essas informações serão arredondadas para um conjunto de chaves (a parte verde) que contém uma ou mais chaves para criptografar dados. O conjunto de chaves é armazenado nas preferências compartilhadas
  • A segunda etapa deste sistema é a amarela, arredondada a cada conjunto de chaves, temos uma chave mestra que criptografa todos os conjuntos de chaves. Esta chave mestra é armazenada usando o Key Store

Para começar a usar a segurança Jetpack, você pode verificar a próxima essência:

val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)

 

Isso cria a chave mestra que você precisa para os conjuntos de chaves, MasterKeys é uma classe auxiliar que permite ao desenvolvedor criar uma chave mestra e, em seguida, obter um alias para ela, a recomendação é usar o algoritmo AES256-GCM que gera uma chave simétrica, mas você pode definir sua própria especificação de parâmetro de geração de chave, exatamente como a API KeyStore na parte superior, incluindo tempos limite, caixa forte e prompts biométricos que serão discutidos posteriormente nesta série.

Na próxima parte, discutiremos os arquivos e preferências compartilhadas que você pode usar no Jetpack Security

Isso é tudo para esta parte da postagem, se você precisar de ajuda: