Préférences chiffrées dans Android

Bon après-midi Je m'appelle Dmitry et je suis professeur du cours de base "Android Developer" à Otus. Aujourd'hui, j'ai décidé de partager une traduction de l'article, que je trouve intéressante et je pense qu'elle peut être utile à de nombreux lecteurs de notre blog.







Le stockage de données dans SharedPreferences est très rapide et pratique. Il est également facile pour les cybercriminels de regarder les données stockées dans SharedPreferences ... alors faites attention à ce que vous y mettez, et vous devrez peut-être réfléchir à la façon de stocker les données dans un format crypté.

Pour de petites quantités de données qui ne justifient pas l'utilisation d'un moteur de base de données, tel que SqlCipher, nos capacités étaient limitées:

  • Méthodes de cryptage natives (si vous savez ce que vous faites)
  • Solutions prêtes à l'emploi telles que Secure-preferences, autres Secure-preferences, Armadillo, etc.
  • Lutter contre les problèmes de cycle de vie du système Android Keystore les plus étranges dans chaque version d'Android

Cela fonctionnait auparavant, mais nous avons maintenant la bonne solution officielle .
Bien qu'encore alpha, cela a bien fonctionné pendant un certain temps lorsque je l'ai utilisé dans mes projets. L'utilisation d' EncryptedSharedPreferences est la bienvenue (ou vous pouvez l'utiliser), pour tous les vôtres avec min-sdk 23+ .

Voyons un exemple d'utilisation:

Exemple EncryptedSharedPreferences


SDK minimum


Aujourd'hui 23 (Android 6.0)

minSdkVersion 23 

Ajouter des dépendances


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

Initialiser / Ouvrir


Il suffit de créer ou de récupérer la clé principale à partir du magasin de clés Android et de l'utiliser pour initialiser / ouvrir l'instance 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 ) 

Enregistrer les enregistrements


Enregistrez les données comme vous l'avez toujours fait avec SharedPreferences:

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


Lire les notes


Lisez les données comme vous l'avez toujours fait avec SharedPreferences:
 //  3:    EncryptedSharedPreferences val value = sharedPreferences.getString("DATA", "") 

Les paramètres sont-ils vraiment cryptés?


Oui, et vraiment assez bien chiffré.

Disons que j'ai mis la valeur SharedPreferences dans SharedPreferences . Voici à quoi ressemblera le fichier:

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

Si j'ajoute la valeur akaita à EncryptedSharedPreferences , j'obtiens quelque chose de complètement différent:

 <?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> 

De plus, le fichier crypté changera à chaque enregistrement, ce qui rend son accès difficile.

Grande mise en garde: performances


Il existe une différence de performances significative entre SharedPreferences et EncryptedSharedPreferences.

Vous pouvez le vérifier vous-même à l'aide de mon exemple de code ou simplement télécharger l'exemple d'application à partir du Play Store. Je réalise moi-même plusieurs tests sur un appareil réel, obtenant les résultats suivants:


EncryptedSharedPreferences vs SharedPreferences


Graphique "EncryptedSharedPreferences versus SharedPreferences"

Conclusion


EncryptedSharedPreferences est une solution fiable et très simple pour Android 6.0 et supérieur.

Il a deux gros avantages:

  1. nous n'avons pas besoin d'encoder quoi que ce soit dans notre code. Il utilise simplement Android Keystore pour nous, éliminant ainsi le besoin de s'en occuper.
  2. l'utilisateur n'a pas besoin de définir un écran de verrouillage. EncryptedSharedPreferences fonctionnera aussi bien sans verrouillage d'écran

Il s'agit d'un remplacement presque complet pour SharedPreferences. Assurez-vous simplement que l'initialisation / ouverture d'EncryptedSharedPreferences n'affecte pas négativement vos utilisateurs.

Cette décision restera définitivement. J'utilise ceci dans n'importe quel scénario approprié. Maintenant, je veux juste dire que les gars d'Android amélioreront ses performances, nous pouvons donc nous inquiéter encore moins :)

Exemple d'application


Juste pour faciliter le test et m'assurer que tout est bien connecté, j'ai créé une application pour vous. Téléchargez-le ou compilez et essayez-le!

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

Mettez un plus si vous trouvez l'article utile, et je serai heureux de répondre à vos questions dans les commentaires.

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


All Articles