tags:

views:

2478

answers:

13

Hi all,

I'm using the code below to save a password to the registry, how do I convert it back? The code below isn't mine but it encrypts well.

Thanks

using System.Security.Cryptography;

public static string EncodePasswordToBase64(string password)
{  byte[] bytes   = Encoding.Unicode.GetBytes(password);
   byte[] dst     = new byte[bytes.Length];
   byte[] inArray = HashAlgorithm.Create("SHA1").ComputeHash(dst);
   return Convert.ToBase64String(inArray);
}
+8  A: 

Take whatever the user enters as a password to gain access to the system, encrypt it the same way and then compare the encrypted values, that's the normal approach. I'm pretty sure that SHA1 is a trapdoor encryption, i.e. can't be back-tracked.

Lazarus
+2  A: 

I think one of the points of using hashes is that they can't be computed back.

As someone else said, calculate the hash from the user's password and compare to the stored hash value.

Giovanni Galbo
+28  A: 

SHA1 is a hash algorithm, not an encryption algorithm. A hash algorithm is a one-way function which transforms data into a hash of that data, but the original data cannot be gotten back from the hash. An encryption algorithm is a two-way function which transforms data into encrypted data, and the encrypted data can then be transformed back into the original data.

Justice
+7  A: 

You don't.

SHA1 is a hash, not encryption. It is a one-way operation; conversion back is not possible.

(Ok this is not strictly true; if you have a table of possible SHA1 values and plain text values, a rainbow table then you might be luck)

Also you should be salting your hashes, because you are, right now, vulnerable to rainbow table attacks. Jeff talks about this a little more on his blog

blowdart
He's way more vulnerable than that. Any password of the same length will hash to the same value.
Kevin
+3  A: 

Okay, so I know this isn't answering your specific Q, but why do you want to convert it back?

If it's to compare in order to provide authentication, the standard approach is to encrypt this text ALSO, and compare the stored password to the supplied password.

This is more secure as it means that the original password never needs to be decrypted.

Duncan
A: 

OK so I may be barking up the wrong tree, what I want to do is save a password to the registry and then read it back to authenticate against an internal system but I don't want to store the password in clear text. What method should I use?

Thanks

You should close this question, marking someone as answering it; and ask this as a new question.
blowdart
Use the ProtectedData class, as per http://stackoverflow.com/questions/269101/c-reading-back-encrypted-passwords#269218
Bradley Grainger
+1  A: 

Um, just curious but wouldn't that return the same hash for all passwords of the same length?

Kevin
+3  A: 

To securely store a password so that it can be read back, use the ProtectedData class.

public static string ProtectPassword(string password)
{
    byte[] bytes = Encoding.Unicode.GetBytes(password);
    byte[] protectedPassword = ProtectedData.Protect(bytes, null, DataProtectionScope.CurrentUser);
    return Convert.ToBase64String(protectedPassword);
}

public static string UnprotectPassword(string protectedPassword)
{
    byte[] bytes = Convert.FromBase64String(protectedPassword);
    byte[] password = ProtectedData.Unprotect(bytes, null, DataProtectionScope.CurrentUser);
    return Encoding.Unicode.GetString(password);
}
Bradley Grainger
A: 

Using your own code snippet above, what you want to do is call that method when the user initially chooses a password - but add to the password what is called a salt somewhere in the password string (usually at the beginning or end). Then, when the user is attempting to authenticate later, they enter their password, you run that one along with the hash through this same method and if the two hashes are equal, it's a statistically excellent chance the passwords are equal and valid.

This being said, SHA1 is known to have weaknesses and you should choose a stronger algorithm. If you want to stay in the SHA family, SHA512 is pretty good.

Jesse C. Slicer
A: 

You want to use encryption not hashing. SHA is fine but use the encryption methods for it. The problem with encryption is always where to put the key for it. You didn't mention whether this was a workstation or server you were doing this on. On a server, I find it better to just use ACL's to restrict access to the reg key. Admins can usually access the encryption key anyway...you have to have some trust somewhere. On a workstation then you can go with encryption and store the key in code or use a certificate and restrict access to it at least in a corp environment...not for sale software).

You can use the ProtectedData class but be aware that it uses user profiles for its key usage and as such you have to make sure you are impersonating the user who has the profile with the key you need. This may or may not be trivial and may or may not cause headaches and security issues.

DancesWithBamboo
A: 

Hi,

I've decided to use the ProtectedData class but I get the error "The name 'ProtectedData' does not exist in the current context" yet I do have the System.Security.Cryptography declared. What am I missing?

using System.Security.Cryptography;

        public static string ProtectPassword(string password)
        {
            byte[] bytes = System.Text.Encoding.Unicode.GetBytes(password);
            byte[] protectedPassword = ProtectedData.Protect(bytes, null, DataProtectionScope.CurrentUser);
            return Convert.ToBase64String(protectedPassword);
        }
You need to add a reference to System.Security.dll. In the future, ask new questions like this by creating a new SO question, rather than by adding an answer to your own question.
Bradley Grainger
A: 

In order to use the System.Security.Cryptography.ProtectedData class, you must add a reference to System.Security to your project.

(Right mouse click on the References folder, choose "Add Reference...", find System.Security on the .NET Tab)

A: 

I noticed the recent addition of the XMLEncryptedData class. For encrypting data to an XML file, is the XMLEncryptedData method more desirable than the DPAPI method?