tags:

views:

13104

answers:

11

Currently I'm writing it in clear text oops!, it's an in house program so it's not that bad but I'd like to do it right. How should I go about encrypting this when writing to the registry and how do I decrypt it?

OurKey.SetValue("Password", textBoxPassword.Text);

Thanks guys

+10  A: 

One option would be to store the hash (SHA1, MD5) of the password instead of the clear-text password, and whenever you want to see if the password is good, just compare it to that hash.

If you need secure storage (for example for a password that you will use to connect to a service), then the problem is more complicated.

If it is just for authentication, then it would be enough to use the hash.

Bogdan Maxim
+17  A: 

You don't decrypt authentication passwords!

Hash them using something like the MD5 provider and when you have to challenge, hash the input from the user and see if the two hashes match.

System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] data = System.Text.Encoding.ASCII.GetBytes(yourString);
data = x.ComputeHash(data);
String md5Hash = System.Text.Encoding.ASCII.GetString(data);

Regarding the down-votes: justify your decision, please... Leaving passwords reversible is a really horrible model.

Edit2: I thought we were just talking about front-line authentication. Sure there are cases where you want to encrypt passwords for other things that need to be reversible but there should be a 1-way lock on top of it all (with a very few exceptions).

Oli
What if you're saving it because you need to connect to a network drive when the computer starts, for example? The question wasn't specific enough to say if using a hash would be possible.
tloach
Generally, it is a bad idea to store passwords, but there are legitimate reasons to do so. Maybe not in the registry, but... For example, I have a web application that needs to access a web service using a service id/password. I store that encrypted in the web config.
tvanfosson
I see, yes, I should have clarified the statement with "authentication". *Edits*
Oli
The point is, *you* don't store passwords anywhere because 11 times out of 10 *you* are guaranteed to do it no better than if you had just stored it in cleartext. If you store keyed or salted hashes, then the original passwords can never be recovered (that's a good thing)!
Justice
Why demand justification for down votes? If you think it should be mandatory vote for the change to UI.
"Leaving passwords reversible is a really horrible model." - if you want to save passwords needed to authenticate to an external service, there's no alternative. CredUI is provided for secure storage of encrypted passwords.
Joe
+3  A: 

There's an answer in a related question - Simple 2 way encryption for C#

Richard Dorman
+1  A: 

Rather than encrypt/decrypt, you should be passing the password through a hashing algorithm, md5/sha512, or similar. What you would ideally do is hash the password and store the hash, then when the password is needed, you hash the entry and compare the entries. A password will then never be "decrypted", simply hashed and then compared.

Jeremy B.
+6  A: 

If you want to be able to decrypt the password, I think the easiest way would be to use DPAPI (user store mode) to encrypt/decrypt. This way you don't have to fiddle with encryption keys, store them somewhere or hard-code them in your code - in both cases somebody can discover them by looking into registry, user settings or using Reflector.

Otherwise use hashes SHA1 or MD5 like others have said here.

liggett78
+2  A: 

..NET provides cryptographics services in class contained in the System.Security.Cryptography namespace.

osp70
A: 

If you need more than this, for example securing a connection string (for connection to a database), check this article, as it provides the best "option" for this.

Oli's answer is also good, as it shows how you can create a hash for a string.

Bogdan Maxim
+2  A: 

Please also consider "salting" your hash (not a culinary concept!). Basically, that means appending some random text to the password before you hash it.

"The salt value helps to slow an attacker perform a dictionary attack should your credential store be compromised, giving you additional time to detect and react to the compromise."

To store password hashes:

a) Generate a random salt value:

byte[] salt = new byte[32];
System.Security.Cryptography.RNGCryptoServiceProvider.Create().GetBytes(salt);

b) Append the salt to the password.

// Convert the plain string pwd into bytes
byte[] plainTextBytes = System.Text UnicodeEncoding.Unicode.GetBytes(plainText);
// Append salt to pwd before hashing
byte[] combinedBytes = new byte[plainTextBytes.Length + salt.Length];
System.Buffer.BlockCopy(plainTextBytes, 0, combinedBytes, 0, plainTextBytes.Length);
System.Buffer.BlockCopy(salt, 0, combinedBytes, plainTextBytes.Length, salt.Length);

c) Hash the combined password & salt:

// Create hash for the pwd+salt
System.Security.Cryptography.HashAlgorithm hashAlgo = new System.Security.Cryptography.SHA256Managed();
byte[] hash = hashAlgo.ComputeHash(combinedBytes);

d) Append the salt to the resultant hash.

// Append the salt to the hash
byte[] hashPlusSalt = new byte[hash.Length + salt.Length];
System.Buffer.BlockCopy(hash, 0, hashPlusSalt, 0, hash.Length);
System.Buffer.BlockCopy(salt, 0, hashPlusSalt, hash.Length, salt.Length);

e) Store the result in your user store database.

This approach means you don't need to store the salt separately and then recompute the hash using the salt value and the plaintext password value obtained from the user.

DOK
"appending some random text" makes it sound a little dodgy. The text is static for the database, no? The challenge has to go through the same process so.. yeah.. Store the salt or use a salt based on static data (username, user ID, etc).
Oli
I've done both static and random text. I believe the argument for random is that if a really determined hacker manages to figure out the static salt text, then they know the salt for all passwords. OTOH, there is a performance hit involved in generating the random salt text.
DOK
He's been storing this in plaintext and you're worried about salt? Seriously?
@DOK Generating a random salt is overkill. UserID will make it unique per user. If you want to change it periodically the last login timestamp will provide a series of continually changing values.
Dan Neely
DOK
+4  A: 

If it's a password used for authentication by your application, then hash the password as others suggest.

If you're storing passwords for an external resource, you'll often want to be able to prompt the user for these credentials and give him the opportunity to save them securely. Windows provides the Credentials UI (CredUI) for this purpose - there are a number of samples showing how to use this in .NET, including this one on MSDN.

Joe
+5  A: 

This is what you would like to do:

OurKey.SetValue("Password", StringEncryptor.EncryptString(textBoxPassword.Text));
OurKey.GetValue("Password", StringEncryptor.DecryptString(textBoxPassword.Text));

You can do that with this the following classes. This class is a generic class is the client endpoint. It enables IOC of various encryption algorithms using Ninject.

public class StringEncryptor
{
    private static IKernel _kernel;

    static StringEncryptor()
    {
        _kernel = new StandardKernel(new EncryptionModule());
    }

    public static string EncryptString(string plainText)
    {
        return _kernel.Get<IStringEncryptor>().EncryptString(plainText);
    }

    public static string DecryptString(string encryptedText)
    {
        return _kernel.Get<IStringEncryptor>().DecryptString(encryptedText);
    }
}

This next class is the ninject class that allows you to inject the various algorithms:

public class EncryptionModule : StandardModule
{
    public override void Load()
    {
        Bind<IStringEncryptor>().To<TripleDESStringEncryptor>();
    }
}

This is the interface that any algorithm needs to implement to encrypt/decrypt strings:

public interface IStringEncryptor
{
    string EncryptString(string plainText);
    string DecryptString(string encryptedText);
}

This is a implementation using the TripleDES algorithm:

public class TripleDESStringEncryptor : IStringEncryptor
{
    private byte[] _key;
    private byte[] _iv;
    private TripleDESCryptoServiceProvider _provider;

    public TripleDESStringEncryptor()
    {
        _key = System.Text.ASCIIEncoding.ASCII.GetBytes("GSYAHAGCBDUUADIADKOPAAAW");
        _iv = System.Text.ASCIIEncoding.ASCII.GetBytes("USAZBGAW");
        _provider = new TripleDESCryptoServiceProvider();
    }

    #region IStringEncryptor Members

    public string EncryptString(string plainText)
    {
        return Transform(plainText, _provider.CreateEncryptor(_key, _iv));
    }

    public string DecryptString(string encryptedText)
    {
        return Transform(encryptedText, _provider.CreateDecryptor(_key, _iv));
    }

    #endregion

    private string Transform(string text, ICryptoTransform transform)
    {
        if (text == null)
        {
            return null;
        }
        using (MemoryStream stream = new MemoryStream())
        {
            using (CryptoStream cryptoStream = new CryptoStream(stream, transform, CryptoStreamMode.Write))
            {
                byte[] input = Encoding.Default.GetBytes(text);
                cryptoStream.Write(input, 0, input.Length);
                cryptoStream.FlushFinalBlock();

                return Encoding.Default.GetString(stream.ToArray());
            }
        }
    }
}

You can watch my video and download the code for this at : http://www.wrightin.gs/2008/11/how-to-encryptdecrypt-sensitive-column-contents-in-nhibernateactive-record-video.html

Jamie Wright
+2  A: 

Like ligget78 said, DPAPI would be a good way to go for storing passwords. Here's an MSDN link:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.protecteddata.aspx

Beau