Preferências criptografadas no Android

Boa tarde Meu nome é Dmitry e sou professor do curso básico "Desenvolvedor Android" em Otus. Hoje decidi compartilhar uma tradução do artigo, que acho interessante e acho que pode ser útil para muitos leitores do nosso blog.







Armazenar dados em SharedPreferences é muito rápido e conveniente. Também é fácil para os invasores observar os dados armazenados nas Preferências Compartilhadas ... portanto, tenha cuidado com o que você coloca lá, e talvez seja necessário pensar em como armazenar os dados em um formato criptografado.

Para pequenas quantidades de dados que não justificam o uso de um mecanismo de banco de dados, como o SqlCipher, nossos recursos eram limitados:

  • Métodos de criptografia nativa (se você souber o que está fazendo)
  • Soluções prontas, como preferências seguras, outras preferências seguras, tatu, etc.
  • Como combater os problemas mais estranhos do ciclo de vida do sistema Keystore Android em todas as versões do Android

Isso funcionou antes, mas agora temos a solução certa e oficial .
Embora ainda seja alfa, funcionou bem por um tempo quando o usei em meus projetos. O uso de EncryptedSharedPreferences é bem - vindo (ou você pode usá-lo), para todos com min-sdk 23+ .

Vejamos um exemplo de como usá-lo:

Exemplo de EncryptedSharedPreferences


SDK mínimo


Hoje 23 (Android 6.0)

minSdkVersion 23 

Adicionar dependências


 implementation "androidx.security:security-crypto:1.0.0-alpha02" 

Inicializar / Abrir


Basta criar ou recuperar a chave mestra do keystore Android e usá-la para inicializar / abrir a instância EncryptedSharedPreferences:

 //  1:    -   /  val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC) //  2.  /   EncryptedSharedPreferences val sharedPreferences = EncryptedSharedPreferences.create( "PreferencesFilename", masterKeyAlias, applicationContext, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) 

Salvar registros


Salve os dados como sempre fazia com SharedPreferences:

 //  3.    EncryptedSharedPreferences sharedPreferences.edit() .putString("DATA", saveText.text.toString()) .apply() 


Ler notas


Leia os dados como sempre fazia com SharedPreferences:
 //  3:    EncryptedSharedPreferences val value = sharedPreferences.getString("DATA", "") 

As configurações estão realmente criptografadas?


Sim, e muito bem criptografado.

Digamos que eu coloquei o valor akaita em akaita . Aqui está a aparência do arquivo:

 <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="DATA">akaita</string> </map> 

Se eu adicionar o valor akaita ao EncryptedSharedPreferences , recebo algo completamente diferente:

 <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="AVz2qCVxm1KudCCJKYuxuoaAXoPeWKjG0w==">ASnO9uni11t3m9sNgDJbiYllL/tE+i99TYKfQ0h8XV6AUN0O3rBxBsMmcpw2DCY=</string> <string name="__androidx_security_crypto_encrypted_prefs_key_keyset__">12a901eb372af4775b09f5b51d20d49428931c5d8e0b17dd103d2169c1879b8b13958274d7e25d3cc052f301461495fd40b70806ae244f456726802460318bdf19dce444e7a60f20c903c5a57140ea8e90a19a1b48559961d145a50000d1c0e22ca918b02ea0cc34e433900f44c00e9c791ecb678f26d293c0226d6c2a9e25e610616ec34241b06410481427a850eeedf85ee4c725d5dbd715b5a8d0e017be9a568a9f960989271d14d2d0531a4408a5d0dae705123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b6579100118a5d0dae7052001</string> <string name="__androidx_security_crypto_encrypted_prefs_value_keyset__">12880189e734bbbf9cfa3bc15b5e53ea8df03341269cf97112a60a1f6482732dd33248b3f821397fb04ef3372ff54336e9045a0b0c0fb7afdf475dbc98a1107d09de66afcc5ad063e5e5b59a7d616e14834e19769bc84de7e5c8716a811814a6cd7a6d72a1c64ce4317f2f482181c437b70f010219ca6407a98bac18f1101c02fd8e2c4a9009ad2a1ebbdc1a4408e9edbbce02123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b6579100118e9edbbce022001</string> </map> "> 12a901eb372af4775b09f5b51d20d49428931c5d8e0b17dd103d2169c1879b8b13958274d7e25d3cc052f301461495fd40b70806ae244f456726802460318bdf19dce444e7a60f20c903c5a57140ea8e90a19a1b48559961d145a50000d1c0e22ca918b02ea0cc34e433900f44c00e9c791ecb678f26d293c0226d6c2a9e25e610616ec34241b06410481427a850eeedf85ee4c725d5dbd715b5a8d0e017be9a568a9f960989271d14d2d0531a4408a5d0dae705123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b6579100118a5d0dae7052001 </ string> <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="AVz2qCVxm1KudCCJKYuxuoaAXoPeWKjG0w==">ASnO9uni11t3m9sNgDJbiYllL/tE+i99TYKfQ0h8XV6AUN0O3rBxBsMmcpw2DCY=</string> <string name="__androidx_security_crypto_encrypted_prefs_key_keyset__">12a901eb372af4775b09f5b51d20d49428931c5d8e0b17dd103d2169c1879b8b13958274d7e25d3cc052f301461495fd40b70806ae244f456726802460318bdf19dce444e7a60f20c903c5a57140ea8e90a19a1b48559961d145a50000d1c0e22ca918b02ea0cc34e433900f44c00e9c791ecb678f26d293c0226d6c2a9e25e610616ec34241b06410481427a850eeedf85ee4c725d5dbd715b5a8d0e017be9a568a9f960989271d14d2d0531a4408a5d0dae705123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b6579100118a5d0dae7052001</string> <string name="__androidx_security_crypto_encrypted_prefs_value_keyset__">12880189e734bbbf9cfa3bc15b5e53ea8df03341269cf97112a60a1f6482732dd33248b3f821397fb04ef3372ff54336e9045a0b0c0fb7afdf475dbc98a1107d09de66afcc5ad063e5e5b59a7d616e14834e19769bc84de7e5c8716a811814a6cd7a6d72a1c64ce4317f2f482181c437b70f010219ca6407a98bac18f1101c02fd8e2c4a9009ad2a1ebbdc1a4408e9edbbce02123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b6579100118e9edbbce022001</string> </map> "> 12880189e734bbbf9cfa3bc15b5e53ea8df03341269cf97112a60a1f6482732dd33248b3f821397fb04ef3372ff54336e9045a0b0c0fb7afdf475dbc98a1107d09de66afcc5ad063e5e5b59a7d616e14834e19769bc84de7e5c8716a811814a6cd7a6d72a1c64ce4317f2f482181c437b70f010219ca6407a98bac18f1101c02fd8e2c4a9009ad2a1ebbdc1a4408e9edbbce02123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b6579100118e9edbbce022001 </ string> <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="AVz2qCVxm1KudCCJKYuxuoaAXoPeWKjG0w==">ASnO9uni11t3m9sNgDJbiYllL/tE+i99TYKfQ0h8XV6AUN0O3rBxBsMmcpw2DCY=</string> <string name="__androidx_security_crypto_encrypted_prefs_key_keyset__">12a901eb372af4775b09f5b51d20d49428931c5d8e0b17dd103d2169c1879b8b13958274d7e25d3cc052f301461495fd40b70806ae244f456726802460318bdf19dce444e7a60f20c903c5a57140ea8e90a19a1b48559961d145a50000d1c0e22ca918b02ea0cc34e433900f44c00e9c791ecb678f26d293c0226d6c2a9e25e610616ec34241b06410481427a850eeedf85ee4c725d5dbd715b5a8d0e017be9a568a9f960989271d14d2d0531a4408a5d0dae705123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b6579100118a5d0dae7052001</string> <string name="__androidx_security_crypto_encrypted_prefs_value_keyset__">12880189e734bbbf9cfa3bc15b5e53ea8df03341269cf97112a60a1f6482732dd33248b3f821397fb04ef3372ff54336e9045a0b0c0fb7afdf475dbc98a1107d09de66afcc5ad063e5e5b59a7d616e14834e19769bc84de7e5c8716a811814a6cd7a6d72a1c64ce4317f2f482181c437b70f010219ca6407a98bac18f1101c02fd8e2c4a9009ad2a1ebbdc1a4408e9edbbce02123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b6579100118e9edbbce022001</string> </map> 

Além disso, o arquivo criptografado será alterado sempre que salvar, o que dificulta o acesso.

Grande advertência: desempenho


Há uma diferença significativa de desempenho entre SharedPreferences e EncryptedSharedPreferences.

Você pode verificar usando o meu código de amostra ou apenas fazendo o download do aplicativo de amostra na Play Store. Eu mesmo realizo vários testes em um dispositivo real, obtendo os seguintes resultados:


EncryptedSharedPreferences vs. SharedPreferences


Gráfico "EncryptedSharedPreferences versus SharedPreferences"

Conclusão


EncryptedSharedPreferences é uma solução confiável e muito simples para Android 6.0 e superior.

Tem duas grandes vantagens:

  1. não precisamos codificar nada em nosso código. Ele apenas usa o Android Keystore para nós, eliminando a necessidade de lidar com isso.
  2. o usuário não precisa definir uma tela de bloqueio. EncryptedSharedPreferences funcionará tão bem sem um bloqueio de tela

Este é um substituto quase completo para SharedPreferences. Apenas verifique se a inicialização / abertura de EncryptedSharedPreferences não afeta adversamente seus usuários.

Esta decisão definitivamente permanecerá. Eu uso isso em qualquer cenário adequado. Agora só quero dizer que os caras do Android melhorarão seu desempenho, para que possamos nos preocupar ainda menos :)

Exemplo de aplicação


Apenas para facilitar o teste e garantir que tudo esteja bem conectado, criei um aplicativo para você. Faça o download ou compile e experimente!

https://github.com/akaita/encryptedsharedpreferences-example

Coloque uma vantagem se achar o artigo útil, e terei prazer em responder a quaisquer perguntas nos comentários.

Source: https://habr.com/ru/post/pt473562/


All Articles