nix
nix

Reputation: 2285

How to securely store key in Xamarin?

Say, I want to save a couple of key-value entries locally, securely, on a mobile device. As it seems, I can use Android's KeyStore and iOS's Keychain and inject ILocalStorage implementation into PCL. However, I haven't found any examples of usage of those two. Could you show how me how I can do that or provide with the resource? Or maybe tell me a better way to achieve what I'm trying to implement? Thanks in advance.

Upvotes: 2

Views: 3187

Answers (2)

Nitesh
Nitesh

Reputation: 328

You have a couple options.

Sq Lite. This option is cross-platform and works well if you have a lot of data. You get the added bonus of transaction support and async support as well. Well documented here:https://github.com/oysteinkrog/SQLite.Net-PCL

There's also Application properties implemented in Xamarin.Forms that allow simple Key-Value pairs of data. you'll have to investigate and find out which route serves your needs best.

As far as security, that depends on where you put your data on each device. Android stores app data in a secure app folder by default (not all that secure if you're rooted). iOS has several different folders for data storage based on different needs.

Upvotes: 2

Athul Harikumar
Athul Harikumar

Reputation: 2491

Hi Please refer to the example in https://developer.xamarin.com/recipes/cross-platform/xamarin-forms/general/store-credentials/ It utilizes kestore in android and key chain in iOS

apart from that I have done this implementation in MVVM cross

public class PersistantStorageHelper<T>
    {
        IMvxFileStoreAsync _mvxFileStoreAsync;
        IMvxFileStore _mvxFileStore;
        EDEngine bcEngine = new EDEngine(new AesEngine(), Encoding.UTF8);
        string currentkey_temp_dev = "AthulHarikumar00";//This static key is not being used it is a just a place holder

        public PersistantStorageHelper() {
            this._mvxFileStore = Mvx.Resolve<IMvxFileStore>();
            this._mvxFileStoreAsync = Mvx.Resolve<IMvxFileStoreAsync>();
            bcEngine.SetPadding(new Pkcs7Padding());
            currentkey_temp_dev = Constants.PassPhrase.Substring(4, 12)+"Road";
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public async Task<T> GetPersistantObject(T obj)
        {
            var fileName = (typeof(T).ToString().Replace(".", "_"));
           var x= await GetPersistantObject(obj, fileName);
            return x;
        }
        /// <summary>
        /// If object exists returns the object else saves a plain object and returns it
        /// </summary>
        /// <param name="obj">empty placeholder object</param>
        /// <returns>Filesystem object</returns>
        public async Task<T> GetPersistantObject( T obj,string fileName) {

            List<string> files = new List<string>(_mvxFileStore.GetFilesIn(_mvxFileStore.NativePath("")));
            fileName = _mvxFileStore.NativePath(fileName);

            if (!files.Contains(fileName))
            {
                var objJson = Newtonsoft.Json.JsonConvert.SerializeObject(obj);

                objJson= bcEngine.Encrypt(objJson, currentkey_temp_dev);
                await _mvxFileStoreAsync.WriteFileAsync(fileName,objJson);
            }
            else {
                try
                {

                    var temp = await _mvxFileStoreAsync.TryReadTextFileAsync(fileName);
                    var str = bcEngine.Decrypt(temp.Result, currentkey_temp_dev);
                    obj = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(str);
                }
                catch(Exception e) {
                    var objJson = Newtonsoft.Json.JsonConvert.SerializeObject(obj);

                    objJson = bcEngine.Encrypt(objJson, currentkey_temp_dev);
                    await _mvxFileStoreAsync.WriteFileAsync(fileName, objJson);
                }
            }

            return obj;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public async Task<T> SetPersistantObject(T obj)
        {
            var fileName = _mvxFileStore.NativePath(typeof(T).ToString().Replace(".", "_"));
            var temp = await SetPersistantObject(obj, fileName);
            return temp;

        }
        /// <summary>
        /// Saves object to persistant storage with encryption
        /// </summary>
        /// <param name="obj">object to be stored</param>
        /// <returns>Saved object</returns>
        public async Task<T> SetPersistantObject(T obj,string fileName)
        {

            List<string> files = new List<string>(_mvxFileStore.GetFilesIn(_mvxFileStore.NativePath("")));
             fileName = _mvxFileStore.NativePath(fileName);


                var objJson = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
            objJson = bcEngine.Encrypt(objJson, currentkey_temp_dev);
            await _mvxFileStoreAsync.WriteFileAsync(fileName, objJson);



            return obj;
        }
    }

inject the pass phrase as a GUID when initialy created save that in Keystore/Keychain/Vault this will encrypt the data and store with the pass phrase provided any object you provide

Upvotes: 4

Related Questions