29

What's the best way of saving sensitive data to a local file in Windows 8? I'm developing a C# application that needs to store oAuth tokens/passwords. I've heard it was common in .NET to encrypt/decrypt data, but I don't have any experience with those mechanics. Is encryption still recommended/neccesary given that Windows 8 apps have their own personal/protected storage area similar to Windows Phone?

Also, doesn't encrypting/decrypting each time when you request the data causes a performance issue? (would it be better to write a custom/lite algorithm?)

Charles
  • 50,943
  • 13
  • 104
  • 142
Nick
  • 607
  • 1
  • 7
  • 14
  • Who is the attacker in your threat model? The admin of the system, or unprivileged rogue software? – CodesInChaos Jan 29 '12 at 11:03
  • 9
    **I highly recommend to not develop your own security system** To store passwords in Windows, there is the _Credential Manager_ (since Win7). _WinRt_ has the corresponding API in the [`Windows.Security.Credentials`](http://msdn.microsoft.com/library/windows/apps/windows.security.credentials.aspx) namespace, _it's still poorly documented though._ – ordag Jan 29 '12 at 11:19

3 Answers3

49

UPDATE: Please be aware that while modern/metro apps are restricted from poking at each other's stuff, desktop applications will have unrestricted access to all data stored through these APIs. See http://www.hanselman.com/blog/SavingAndRetrievingBrowserAndOtherPasswords.aspx which includes code demonstrating this.


Win8 has a new API called PasswordVault that's designed for taking care of all these hard problems for you. Really easy to use, secure, and can be configured by users to roam between their machines so they only have to enter credentials once. I've successfully used this for OAuth tokens

Retrieving credentials (note the stupid exception that WinRT raises... they really should just return null):

const string VAULT_RESOURCE = "[My App] Credentials";
string UserName { get; set; };
string Password { get; set; };
var vault = new PasswordVault();

try
{
   var creds = vault.FindAllByResource(VAULT_RESOURCE).FirstOrDefault();
   if (creds != null)
   {
      UserName = creds.UserName;
      Password = vault.Retrieve(VAULT_RESOURCE, UserName).Password;
   }
}
catch(COMException) 
{
   // this exception likely means that no credentials have been stored
}

Storing credentials:

vault.Add(new PasswordCredential(VAULT_RESOURCE, UserName, Password));

Removing credentials (when the user clicks the logout button in your app):

vault.Remove(_vault.Retrieve(VAULT_RESOURCE, UserName));
Robert Levy
  • 28,747
  • 6
  • 62
  • 94
  • @RobertLevy Could you please advise where I can find info about the possible exception thrown by password vault operations? THX – louis.luo Jan 04 '13 at 01:55
  • @Louis_PIG - in the preview versions of Win8, a generic COMException was thrown if you tried to loop up something that didnt exist in the vault. I'm not sure if this is still the case in the final RTM version of Win8 – Robert Levy Jan 04 '13 at 14:07
  • @RobertLevy Can you elaborate on how you're storing OAuth tokens? Do you simply use the "access token" as the username and the "token secret" as the password? – Matt Hamilton Jan 17 '13 at 06:59
  • @MattHamilton since there is a control panel that lets users see the the username field, i would put the string "Access Token" (or the user's actual username if feasible) in the username field and then in the password field store access_token+" "+secret which would can then .split() when you read it back out later – Robert Levy Jan 17 '13 at 16:14
  • Is there a way to disable roaming of credentials? For storing a device-specific OTP, this is an unwanted feature. – sgdesmet Jun 10 '14 at 12:11
  • 1
    no, users can disable all roaming but you can't do it per-credential. but you could make the username field also be device specific so when you lookup the value from another device, it won't be found – Robert Levy Jun 10 '14 at 12:58
  • If the VAULT_RESOURCE string is leaked, any other app can access that.People can take appx and get the source code out of it, and can easily recognize the hard coded key. – CodeR Oct 19 '15 at 18:24
  • @CodeR I don't believe that is correct. Can you share a test case or reference for this? – Robert Levy Oct 19 '15 at 18:26
  • 1
    @CodeR: "The Credential Locker is unique to each Windows PC user *and access to a credential is limited to the app that stored it*" http://blogs.msdn.com/b/windowsappdev/archive/2013/05/30/credential-locker-your-solution-for-handling-usernames-and-passwords-in-your-windows-store-app.aspx – Robert Levy Oct 19 '15 at 18:45
  • Need to catch Exception instead of COMException in .NET Native. – Der_Meister Jan 01 '16 at 19:44
  • Be aware that, according to the documentation, PasswordVault can only store 10 credentials. Not a problem for most apps, but can be an issue in some cases. – Yort Feb 09 '16 at 01:38
  • I believe that 10 credentials limitation only applies to WinRT/UWP apps and is per app, as clearly the vault itself can store more than that. – Yort Feb 09 '16 at 01:49
  • I submitted the suggestion [No exception from PasswordVault.FindAllByResource when there are no results](https://wpdev.uservoice.com/forums/110705-universal-windows-platform/suggestions/32922646-no-exception-from-passwordvault-findallbyresource). – Sam Hobbs Jan 13 '18 at 20:38
0

It depends on what you need, if you realy need to store the passwords you should use a 2-way encryption algorithm like 3DES/RC2/Rijndael etc.

However, if all you need to be able to do is verify if a password is correct it is recommended to use a oneway function to store a hash.

When dealing with sensitive data I realy recommend the encrypt/hash it, even if you use windows 8. Encryption does mean extra overhead but in most cases you will not notice the speed difference.

Would it be better to write your own custom/lite algorithm? As a security guy I advise against it. People spend years testing, improving and trying to find holes in existing algoritms. The ones that survived are therefore quite good.

  • Thanks, my app is a Twitter application which needs to provide oAuth tokens with each request. These tokens need to be saved when first acquiring them. Now I have the tokens in an XML file, without any encryption and I was "scared" of using Windows 8's encryption APIs given the lack of information and my lack of knowledge on encryption. I understand though that it's good practice to use encryption, even in Windows 8, I'll try to make my way trough the Windows.Security.Credentials API. Thanks for all the help – Nick Jan 29 '12 at 13:38
-4

you could encrypt like this:

    public static string EncodePassword(string password)
    {
        byte[] bytes = Encoding.Unicode.GetBytes(password);
        byte[] inArray = HashAlgorithm.Create("SHA1").ComputeHash(bytes);
        return Convert.ToBase64String(inArray);
    }

And when checking the user input, you also trow it into this method and check for it to match.

In case of data that you put in an xml (for example) that you want to encrypt/decrypt you can use RijndaelManaged.

-Edit1-

An example: if you have a small login screen that pops up (ShowDialog) you can is it like this snip-it:

private void settings_Click(object sender, RoutedEventArgs e)
{
    Login log = new Login();    //login window
    log.ShowDialog();           //show the login window
    string un = log.userName.Text;  //the user input from the username field
    string pw = log.passWord.Password; //the userinput from the password input
    if (EncodePassword(un) == Properties.Settings.Default.adminUsername && EncodePassword(pw) == Properties.Settings.Default.adminPassword) //in my case, i stored it in the app settings, but this could also be somewhere else.
    {
        //login was correct
        //do something
    }
    else
    {
        //login was not correct
    }
}
Dante1986
  • 58,291
  • 13
  • 39
  • 54
  • 2
    Nick's "developing a C# application that needs to store oAuth tokens/passwords", so chances are the app needs to produce those tokens and passwords again, in which case storing the checksum and discarding the original won't help. – Lumi Jan 29 '12 at 10:39
  • depending on its use. if its used as a password, you can throw the user input into the method, and compare the output string to the stored string. This is exactly how i do it in one of my applications too. – Dante1986 Jan 29 '12 at 10:45
  • 1
    @Dante1986: Sure, but I guess (and I might be guessing wrong) that Nick needs to store credentials *for some other application*, like a web site - so, as a security client, not as a server. Nick might elaborate on his description of the problem to clarify this. – Lumi Jan 29 '12 at 11:07
  • 2
    Aaah, from his question i thought he meant storing passes for and in the same application he is making. The above wouldn't work indeed, if he wants to store them like a database or something. – Dante1986 Jan 29 '12 at 11:09