Storing Sensitive User Security Data

Hi All,

I'm currently researching the best way to store sensitive data on the various mobile platforms. My web service implementation uses OAuth2 for security so the plan is to initially ask for a users credentials to obtain the tokens (access and refresh) and then I'm going to store these instead of the users actual username and password.

iOS

Obviously iOS has had the KeyChain forever so that platform is a no brainer on the approach.

Android

Since we are targeting Android 4.0+ (API level 14+) this platform also has a KeyChain so we are good to go here as well.

Windows Phone

Is there a similar approach on the WP platform?

I was initially thinking about using plain encryption but this would still require some input from the user or a static password embedded in the application that would complete defeat the entire exercise and it seems a little daft when there are device enabled approaches to leverage in order to properly hand off some of the security concerns to the hardware. The problem is I cannot identify if the WP platform has a similar feature that could be used.

Any info would be great.

TIA,

J

Posts

  • SKallSKall USMember ✭✭✭✭

    There is ProtectedData class in WP for the encryption/decryption. You can take a look at the ISecureStorage abstraction on XLabs.Platform for a sample.

    http://forums.xamarin.com/discussion/comment/122888/#Comment_122888

  • JamesGreen.8031JamesGreen.8031 GBMember ✭✭

    What an excellent thread! Many thanks Sami.

  • KMullinsKMullins USMember, Xamarin Team Xamurai

    Hi @JamesGreen.8031,

    Personally, I've gotten a lot of mileage out of this little routine:

    using System;
    using System.Security.Cryptography;
    using System.Text;
    using System.IO;
    
    namespace System.Security.Cryptography
    {
        /// <summary>
        /// The <see cref="System.Security.Cryptography.Crypto"/> provides an easy way encrypt and decrypt
        /// data using a simple password.
        /// </summary>
        /// <remarks>
        /// Code based on the book "C# 3.0 in a nutshell by Joseph Albahari" (pages 630-632)
        /// and from this StackOverflow post by somebody called Brett
        /// http://stackoverflow.com/questions/202011/encrypt-decrypt-string-in-net/2791259#2791259
        /// </remarks>
        static internal class Crypto
        {
            // Define the secret salt value for encrypting data
            private static readonly byte[] salt = Encoding.ASCII.GetBytes("Xamarin.iOS Version: 7.0.6.168");
    
            /// <summary>
            /// Takes the given text string and encrypts it using the given password.
            /// </summary>
            /// <param name="textToEncrypt">Text to encrypt.</param>
            /// <param name="encryptionPassword">Encryption password.</param>
            internal static string Encrypt(string textToEncrypt, string encryptionPassword)
            {
                var algorithm = GetAlgorithm(encryptionPassword);
    
                //Anything to process?
                if (textToEncrypt==null || textToEncrypt=="") return "";
    
                byte[] encryptedBytes;
                using (ICryptoTransform encryptor = algorithm.CreateEncryptor(algorithm.Key, algorithm.IV))
                {
                    byte[] bytesToEncrypt = Encoding.UTF8.GetBytes(textToEncrypt);
                    encryptedBytes = InMemoryCrypt(bytesToEncrypt, encryptor);
                }
                return Convert.ToBase64String(encryptedBytes);
            }
    
            /// <summary>
            /// Takes the given encrypted text string and decrypts it using the given password
            /// </summary>
            /// <param name="encryptedText">Encrypted text.</param>
            /// <param name="encryptionPassword">Encryption password.</param>
            internal static string Decrypt(string encryptedText, string encryptionPassword)
            {
                var algorithm = GetAlgorithm(encryptionPassword);
    
                //Anything to process?
                if (encryptedText==null || encryptedText=="") return "";
    
                byte[] descryptedBytes;
                using (ICryptoTransform decryptor = algorithm.CreateDecryptor(algorithm.Key, algorithm.IV))
                {
                    byte[] encryptedBytes = Convert.FromBase64String(encryptedText);
                    descryptedBytes = InMemoryCrypt(encryptedBytes, decryptor);
                }
                return Encoding.UTF8.GetString(descryptedBytes);
            }
    
            /// <summary>
            /// Performs an in-memory encrypt/decrypt transformation on a byte array.
            /// </summary>
            /// <returns>The memory crypt.</returns>
            /// <param name="data">Data.</param>
            /// <param name="transform">Transform.</param>
            private static byte[] InMemoryCrypt(byte[] data, ICryptoTransform transform)
            {
                MemoryStream memory = new MemoryStream();
                using (Stream stream = new CryptoStream(memory, transform, CryptoStreamMode.Write))
                {
                    stream.Write(data, 0, data.Length);
                }
                return memory.ToArray();
            }
    
            /// <summary>
            /// Defines a RijndaelManaged algorithm and sets its key and Initialization Vector (IV) 
            /// values based on the encryptionPassword received.
            /// </summary>
            /// <returns>The algorithm.</returns>
            /// <param name="encryptionPassword">Encryption password.</param>
            private static RijndaelManaged GetAlgorithm(string encryptionPassword)
            {
                // Create an encryption key from the encryptionPassword and salt.
                var key = new Rfc2898DeriveBytes(encryptionPassword, salt);
    
                // Declare that we are going to use the Rijndael algorithm with the key that we've just got.
                var algorithm = new RijndaelManaged();
                int bytesForKey = algorithm.KeySize / 8;
                int bytesForIV = algorithm.BlockSize / 8;
                algorithm.Key = key.GetBytes(bytesForKey);
                algorithm.IV = key.GetBytes(bytesForIV);
                return algorithm;
            }
    
        }
    
    }
    

    By using it to encrypt/decrypt individual string values and storing them using the usual methods.

    Kevin

  • SKallSKall USMember ✭✭✭✭

    @KMullins that's very useful class. Good alternative if you want to keep things lightweight and not include too many dependencies. For a more comprehensive crypting library there is PCLCrypto as unfortunately the System.Security.Cryptography namespace is very limited on WP.

  • KMullinsKMullins USMember, Xamarin Team Xamurai

    @SKall,

    Good catch and addition to the conversation.

    Thanks,

    Kevin

  • JamesGreen.8031JamesGreen.8031 GBMember ✭✭
    edited June 2015

    I've been looking at both of these (Kevin I found this class in another thread) and also started to implement something using this but it requires a users password.

    To me it just seemed to be moving the issue. If I hard code a password that would be negating some of the benefits, if I use a user password where would I store this so that I didn't have to bug the user for this password. That's essentially what I'm trying to avoid doing by storing the Tokens.

    Or am I missing something? Thanks for all the input guys, much appreciated.

  • JamesGreen.8031JamesGreen.8031 GBMember ✭✭

    Also Kevin I don't know if this is related to my relative inexperience with the Xamarin/MvvmCross/PCL way of building apps but I couldn't get your class to work.

    I can get it to work if I include it in the Android application directly as that has access to the Cryptography namespace but used in a pure PCL environment (using the PCLCrypto lib from Andrew Arnott) it needs a bit of refactoring but could be done.

    That said I feel making use of the device native secure storage feels "more right" in the context of OAuth2 tokens.

  • SKallSKall USMember ✭✭✭✭

    If you want to add some extra security instead of storing with embedded code then you could do a "PIN" + salt. The user enters short PIN number instead of the full password and that is used together with a salt. The security risk is you would still need to hardcode or store the salt somewhere. There are many ways to make it more (or less) secure but it is always a compromise between security and convenience.

    https://crackstation.net/hashing-security.htm

  • JamesGreen.8031JamesGreen.8031 GBMember ✭✭

    Hi Sami,

    Indeed I did think about doing the PIN thing as well. I'm still not settled on a solution yet. My server uses randomly generated salts and, like you suggest, all passwords are hashed prior to storage.

    More thinking needed! (as ever!) Thanks.

  • JamesGreen.8031JamesGreen.8031 GBMember ✭✭

    Wow ... going through all the various options there really are a plethora of approaches and options.

    Sami, I really like your approach using the ISecureStorage interface however it looks like the Android KeyVaultStorage class makes use of a password argument in the constructor (not a problem of course just something to bear in mind at implementation time).

    Whereas the iOS SecureStorage class does not require a password and it looks like the WP8 version uses an SecureStorage class with an entropy option.

    I then had a look at the way Xamarin.Auth handles this and it looks like on iOS they make use of SecRecord and use the SecKind.GenericPassword option on Andoird they actually embed a password in the source (AndroidAccountStore class) which seems a little odd.

    I'm think I'm going to author my own Interface based MvvmPlugin and tailor it. So many options!!

  • JamesGreen.8031JamesGreen.8031 GBMember ✭✭

    Ahhh ... I've just found this ticket on GitHub talking about the hard coded Android KeyStore password.

    How that ever made it into any released version is beyond me. The source code is bit of a mess in general to be honest.

  • JamesGreen.8031JamesGreen.8031 GBMember ✭✭
    edited June 2015

    Oh, talking to myself again ... Just found this:

    ChristianRuiz/MvvmCross-SecureStorage

    EDIT

    Scratch using this library, this is not storing things in a secure manner at all and should not be used. On the Android platform it simply uses a private instance of ShardPreferences which is not in any way secured in terms of encryption.

  • SKallSKall USMember ✭✭✭✭
    edited June 2015

    You can use the WP version with or without additional entropy (I think I put in a default null in there to mark it optional). If you need a parameterless constructor for IoC (should not be the case as most IoC containers will allow Func's) then you can always inherit from them with a custom class and embed the hardcoded password there.

    This is how I injected it for Android on XLabs sample: https://github.com/XLabs/Xamarin-Forms-Labs/blob/master/Samples/XLabs.Sample.Droid/MainActivity.cs#L113

    I wouldn't recommend using the device Id of course as that's just a demo application...

  • JamesGreen.8031JamesGreen.8031 GBMember ✭✭

    Indeed, it seems from what I've read getting a consistent unique ID from the hardware is anything but straight forward as I was going to use that as a password.

    That said it seems that he most reliable way is through the TelephonyManager which my app will require as a permission so ...

    I don't like the idea of hard coding anything I don't have to, Then again the trade off is to be considered as well.

    Thanks Sami.

  • JamesGreen.8031JamesGreen.8031 GBMember ✭✭
    edited June 2015

    This is the thread I mentioned where I found the TelephonyManager ID information

    Is there a unique Android device ID?

    I'm considering writing a class to handle the generation of this that could be run once to perform a setup routine on the secure storage, with a catchall "fallback" value if nothing is generated from the device. Could prove more trouble than it's worth however.

  • navysparksnavysparks USMember ✭✭

    I am dealing with this now as well, and I believe starting with Windows Phone 8.1 you can use the "Credential Locker" API which functions like the KeyChain on the other platforms (app specific storage and retrieval). See: https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh465069.aspx

  • dot_lydot_ly USMember ✭✭

    @JamesGreen.8031 Hi James, dealing with these issues now myself...I don't like that most Android keystore solutions use the password in code...did you come up with a better solution?

    I was going to use Xamarin.Auth , because they don't seem to use a password for the Android keystore.. but on reading this post, its clear that they do (hardcoded).

  • sameerksameerk USMember ✭✭
  • RushAidRushAid USMember ✭✭

    @sameerk . I want to try your Secure Storage Plugin. Right now I'm stuck at the Android require password. Can you clarify about : "In Android, it is required that the password is set by the application prior to use" ?

    I have set the password in Android, but the apps still require set password. What does password here means? My Mac password? My project password?

  • sameerksameerk USMember ✭✭

    This is the password app would use to protect the data. You can assign the value of your choice. But obfuscate the app, so if someone reverse engineers the app, it cannot be retrieved. The new version of the Nuget 2.0 has a built in password for Android. This is the hardware id of the device. It can be reverse engineered (unless obfuscated.). But it is unique per device and not common for all apps. Hope this+ samples on GitHub help you.

  • sameerksameerk USMember ✭✭

    Ver 2.0 of the package is now available. It supports:
    . net standard
    UWP
    MacOS and
    Tizen

    The blog about whats new is here:
    https://sameer.blog/2018/01/19/whats-new-in-secure-storage-2-0/

  • KhalTechKhalTech MAMember ✭✭
    edited May 2018

    @sameerk

    I used your plugin yesterday or the day before and it works really nicely (macOS for now).

    Now the issue being on how to correctly handle passwords in memory, without risking malwares getting a hold of them.

    https://stackoverflow.com/questions/50500885/c-sharp-xamarin-essentials-secure-storage

  • sameerksameerk USMember ✭✭

    Glad that the plugin was useful to you. The best practice to store sensitive data securely in memory is to use SecureString. I would retrieve the data using Secure Storage plug-in and store it in memory in SecureString. Hope that helps.

Sign In or Register to comment.