A closer look at Xamarin.Essential’s SecureStorage

If you are serious about mobile development with Xamarin/.NET or code sharing in general and have not heard or read about Xamarin.Essentials, you have definitely missed out on a great Nuget package.

What’s it all about?

Xamarin.Essentials is a collection of cross-platform APIs allowing you to access features that are available on Windows, iOS and Android but only through very different platform specific implementations. It includes:

  • Compass
  • Device information
  • Text to speech transformation
  • SMS
  • …and many more! The list is growing – the project is under active development.

You can find out more about Xamarin.Essentials on Github.

Storing data securely

In this blog post I’m going to focus on a set of APIs built around secure data storage. Microsoft documentation covers this here. The idea behind it is pretty simple:

Securely store key-value-pair data on a device.

For example, this can be useful for scenarios where you want to remember the username of a login screen. Or maybe you’d like to store an access token for some cloud backend. To generalize it: with the secure storage APIs, you can persist small pieces of information that should not stored in cleartext and require a reasonable amount of protection.

The focus in this post is not the show the actual usage of the APIs – there are plenty of examples out there and also very good documentation – rather I’m going to dive a bit deeper want to discuss what exactly is happening on the three platforms and give you an impression of the level of security that will be applied to data you are storing.

The iOS keychain

When using SecureStorage on iOS, data will be written to the platform’s keychain, an encrypted database which can store different types of data like passwords, notes and certificate keys. Keychain data is protected by encrypting it with a key derived from the device’s PIN or password. Some notes about the iOS specific implementation:

  • By default it is using the security category SecAccesible.AfterFirstUnlock which means data is only available after the first time the device has been unlocked after booting. This is recommended if data is required while an app is in the background. Data will also move to a new device if a device’s backup is restored on a new device. You can change the security category by setting SecureStorage’s static property SecureStorage.DefaultAccessible in your iOS head project (public static SecAccessible DefaultAccessible { get; set; } = SecAccessible.AfterFirstUnlock;)
  • Data stored with SecureStorage will survive even if the corresponding app gets uninstalled. If you reinstall the app, you will be able to access your data again as long as you are using the same application identifier.
  • Data stored with SecureStorage will not be synced via iCloud. This would require setting the Synchronizable property of the generated record to TRUE but Xamarin.Essentials has currently no support to do this.

Android’s KeyStore and shared preferences

On Android a combination of KeyStore and SharedPreferences is used to persist data. This split is necessary because the recommended way of storing data is to use SharedPreferences – however, they are not protected. Any additional protection needs to be implemented manually and that’s where KeyStore comes handy. KeyStore allows to securely store cryptographic keys. In the case of Xamarin.Essentials, a (random) key will be generated and used to encrypt data. The key will then be stored inside keystore. Similar to iOS where keychain content is protected by the user’s PIN, Android’s keystore has additional levels of protection, such as keeping key materials outside of the application’s process

  • Starting with API level 23 a symmetric key will be used directly; for older platforms this key is wrapped into an asymmetric key and then stored. This is due to a limitation of the older keystore APIs. The actual encryption will always use AES, meaning: the level of security is the same on all API levels.
  • Data stored in the shared preferences will be written using private mode: data will only be available to the app.
  • One interesting detail of the Android implementation is how data values are identified. SecureStorage’s API let’s you specify key-value-pairs but the key is not saved into the preferences. Instead, an MD5 hash is generated. This means you will not be able to get any useful information when enumerating existing preferences. While this can be interpreted as an additional level of security it also prevents you from storing and retrieving dynamic key-value-pairs.
  • Xamarin.Essentials is using the Android Keystore provider that let’s an individual app store its own credentials that only the app itself can access.
  • Unlike on iOS where stored values survive app deletion, all stored values will be removed when the app is uninstalled.
  • There is currently no support in the Android implementation for advanced protection of the encryption key, like mandatory user authentication.

Windows / UWP

The APIs used to securely store data on Windows is available through the DataProtectionProvider class and is surprisingly easy to use. There are methods to protect data and to unprotect it – that’s all. Data will be stored locally to the app and thus be removed if the app is deleted. Because of the lack of configurable options, there is not much to comment here. If you have additional information about details, feel free to send it my way and I will update this post.

Conclusion

Xamarin.Essentials provides a very convenient way of storing sensitive data across all platforms. Please keep in mind that you should always think twice before collecting and persisting and type of sensitive data and ask yourself if it is really necessary and in the interest of your users.

Leave a Reply

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