views:

116

answers:

2

I have a desktop application with a remote interface. The access to the remote interface is secured by a username and password.

What would be the best way to save these password securely, preferably in the registry?

+3  A: 

You would need to save the hashed password (be it in the registry or somewhere else). Then when the user enters their password you check the hashed version of what they enter with the hashed version as stored. If these match then the passwords match and you can let the user in.

This way you're not storing the password in plain text for anyone (including yourself) to get at and gain access as someone else.

As to which hash algorithm to use - I don't know. There are plenty to choose from, so I'm reluctant to recommend one blind. I'd suggest you find several and evaluate them. CSharpFriends has an article which looks like it might be a good starting point.

ChrisF
Which hash algorithm should I use?
Am
The case wasn't about storing a password for a user though, was it? I thought it was a username and password for some external service.
Svish
@Svish, the user/pass is stored to the app itself (an internal web interface for remote access)
Am
+2  A: 

If you do need to store an unhashed password, look at using the ProtectedData class. This makes use of the Data Protection API (DPAPI) which is the best way of securing data on Windows.

Here's a little class that wraps ProtectedData and provides two extension methods on String to Encrypt and Decrypt data:

public static class DataProtectionApiWrapper
{
    /// <summary>
    /// Specifies the data protection scope of the DPAPI.
    /// </summary>
    private const DataProtectionScope Scope = DataProtectionScope.CurrentUser;

    public static string Encrypt(this string text)
    {
        if (text == null)
        {
            throw new ArgumentNullException("text");
        }

        //encrypt data
        var data = Encoding.Unicode.GetBytes(text);
        byte[] encrypted = ProtectedData.Protect(data, null, Scope);

        //return as base64 string
        return Convert.ToBase64String(encrypted);
    }

    public static string Decrypt(this string cipher)
    {
        if (cipher == null)
        {
            throw new ArgumentNullException("cipher");
        }

        //parse base64 string
        byte[] data = Convert.FromBase64String(cipher);

        //decrypt data
        byte[] decrypted = ProtectedData.Unprotect(data, null, Scope);
        return Encoding.Unicode.GetString(decrypted);
    }

}
Samuel Jack
If i understand correctly, any application running in the user's space can decrypt this data. Am I right?
Am
I believe so. You can limit this by passing in some bytes of your own instead of null when calling Protect and Unprotect: I think these act as an additional, application specific key.
Samuel Jack