What is the easiest way to encrypt a password when I save it in the registry?

I am currently writing this in pure oops! Text, this is in a home program, so this is not so bad, but I would like to do it right. How should this be encrypted when writing to the registry and how to decrypt it?

OurKey.SetValue("Password", textBoxPassword.Text); 
+49
c # passwords encryption
Oct 17 '08 at 14:55
source share
12 answers

You do not decrypt authentication passwords!

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

 byte[] data = System.Text.Encoding.ASCII.GetBytes(inputString); data = new System.Security.Cryptography.SHA256Managed().ComputeHash(data); String hash = System.Text.Encoding.ASCII.GetString(data); 

Recovering passwords is really a terrible model.

Edit2: I thought we were just talking about front-line authentication. Of course, there are cases when you want to encrypt passwords for other things that should be reversible, but there should be a lock with one move on top of everything (with very few exceptions).

I updated the hash algorithm, but for the best possible strength you want to keep the private salt and add this to your input before hashing it . You will do it again when you compare. This adds another layer, making it even harder to change.

+107
Oct 17 '08 at 15:00
source share

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

" The value of salt helps slow down the dictionary attack attack if your credential store is compromised, giving you extra time to detect and respond to a compromise. "

To save password hashes:

a) Create a random salt value:

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

b) Add 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 and salt:

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

d) Add salt to the resulting 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) Save the result in the database of your store.

This approach means that you do not need to store the salt separately and then recalculate the hash using the salt value and plaintext password value received from the user.

Change As the original computing power becomes cheaper and faster, the value of hashing or salting ridges decreases. Jeff Atwood has a great 2012 update , too long to be fully repeated here, which says:

This (using salted hashes) will provide the illusion of security more than any real security. Since you need salt and the choice of a hash algorithm to generate the hash, and to verify the hash, it is unlikely that the attacker will have one, and not the other. If you have been compromised to the point where the attacker has your password database, it is reasonable to assume that they have or can get your secret, hidden salt.

The first security rule is to always assume and plan for the worst. Should you use salt, ideally a random salt for each user? Of course, this is definitely good practice, and at least it allows you to disambiguate two users who have the same password. But these days, salts alone can no longer save you from a person who wants to spend several thousand dollars on hardware for a video card, and if you think they can, you have problems.

+21
Oct 17 '08 at 15:13
source share

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 this with the following classes. This class is a general client endpoint class. It allows IOC 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, which allows you to introduce various algorithms:

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

This is the interface that any algorithm for encrypting / decrypting strings should implement:

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

This is an 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

+11
Nov 07 '08 at 14:31
source share

One option is to save the password hash (SHA1, MD5) instead of the password with clear text and whenever you want to know if the password is good, just compare it with this hash.

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

If it's just for authentication, then using a hash is enough.

+10
Oct 17 '08 at 14:59
source share

If you want to decrypt the password, I think the easiest way would be to use DPAPI (user repository mode) for encryption / decryption. Thus, you do not need to bother with encryption keys, store them somewhere or hard-code them in your code - in both cases, someone can detect them by looking at the registry, user settings, or using Reflector.

Otherwise, you can use SHA1 or MD5 hashes, like others.

+9
Oct 17 '08 at 15:02
source share

Like ligget78, DPAPI will be a good way to store passwords. Check the ProtectedData class on MSDN for example usage.

+6
Mar 23 '09 at 17:04
source share

If this is the password used for authentication by your application, enter the password hash, as others suggest.

If you store passwords for an external resource, you will often want to ask the user for these credentials and enable him to save them securely. Windows provides the Credential User Interface (CredUI) for this purpose - there are a number of examples showing how to use this in .NET, including this one on MSDN .

+5
Oct 17 '08 at 17:21
source share
Tom Scott correctly understood how to (not) store passwords on Computerphile.

https://www.youtube.com/watch?v=8ZtInClXe1Q

  • If you cannot avoid this at all, do not try to store passwords yourself. Use a separate, pre-installed, reliable user authentication platform (for example, OAuth providers, your company Active Directory Domain, etc.).

  • If you must store passwords, do not follow the instructions here. At least not without consulting with more recent and authoritative publications that apply to your choice. p>

Here, of course, there are a lot of smart people and probably even some good recommendations. But the chances are strong that by the time you read this, all the answers here (including this one) are already out of date.




The correct way to store passwords changes over time.

Perhaps more often than some people change their underwear.




All that said, here is some general guidance that I hope will remain useful for a while.

  • Do not encrypt passwords. Any storage method that allows you to restore saved data is inherently unsafe for storing passwords - all forms of encryption are included.
  • Process passwords exactly as it was entered by the user during the creation process. Everything you do with a password before sending it to the cryptography module may just weaken it. Doing any of the following also simply complicates the process of storing and verifying passwords, which may cause other problems (possibly even introduce vulnerabilities) in the future.

    • Do not convert to all-uppercase / all-lowercase.
    • Do not remove spaces.
    • Do not remove unacceptable characters or lines.
    • Do not change text encoding.
    • Do not perform any characters or string substitutions.
    • Do not truncate passwords of any length.
  • Reject the creation of any passwords that cannot be saved unchanged. Strengthening the above. If there is any reason, your password storage mechanism cannot properly process certain characters, spaces, lines or lengths of passwords, and then return an error and inform the user about the limitations of the system so that they can try again with the password that is placed in them. For the best user experience, create a list of the restrictions that are available to the user. Don’t even bother, not to mention hiding the list from intruders - they will understand this on their own anyway.

  • Use a long, random and unique salt for each account. Passwords without two accounts will never look the same in the vault, even if the passwords are actually identical.
  • Use slow and cryptographically strong hashing algorithms designed for use with passwords. MD5, of course, is missing. SHA-1 / SHA-2 do not go. But I'm not going to tell you what you should use here. (See First Bullet No. 2 in this post.)
  • Iterate as much as you can endure. . While your system may have better things related to processor cycles than hash passwords all day, people who crack your passwords have systems, etc. Make it as difficult as you can without doing it "too hard "on you.



The most important thing...

Do not listen to anyone here.

Look for a reliable and very recent publication on the right password storage methods for your language of choice. In fact, you should find several recent publications from several separate sources that are in agreement before you agree to one method.

It is extremely possible that everything that everyone said here (including me) has already been replaced by the best technologies or turned out to be unsure of the new attack methods. Go find what most likely will not.

+5
Oct 23 '15 at 21:38
source share

I looked through the entire example for a good example of the encryption and decryption process, but most of them were overly complex.

In any case, there are many reasons why someone might want to decrypt some text values, including passwords. The reason I need to decrypt the password on the site I'm currently working on is because they want to make sure that when someone is forced to change their password when it expires, we do not allow them to change it with a loved one they have been used with the same password option for the past six months.

So, I wrote a process that will do this in a simplified way. Hope this code is useful to someone. As far as I know, I can end up using this at another time for another company / site.

 public string GenerateAPassKey(string passphrase) { // Pass Phrase can be any string string passPhrase = passphrase; // Salt Value can be any string(for simplicity use the same value as used for the pass phrase) string saltValue = passphrase; // Hash Algorithm can be "SHA1 or MD5" string hashAlgorithm = "SHA1"; // Password Iterations can be any number int passwordIterations = 2; // Key Size can be 128,192 or 256 int keySize = 256; // Convert Salt passphrase string to a Byte Array byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue); // Using System.Security.Cryptography.PasswordDeriveBytes to create the Key PasswordDeriveBytes pdb = new PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations); //When creating a Key Byte array from the base64 string the Key must have 32 dimensions. byte[] Key = pdb.GetBytes(keySize / 11); String KeyString = Convert.ToBase64String(Key); return KeyString; } //Save the keystring some place like your database and use it to decrypt and encrypt //any text string or text file etc. Make sure you dont lose it though. private static string Encrypt(string plainStr, string KeyString) { RijndaelManaged aesEncryption = new RijndaelManaged(); aesEncryption.KeySize = 256; aesEncryption.BlockSize = 128; aesEncryption.Mode = CipherMode.ECB; aesEncryption.Padding = PaddingMode.ISO10126; byte[] KeyInBytes = Encoding.UTF8.GetBytes(KeyString); aesEncryption.Key = KeyInBytes; byte[] plainText = ASCIIEncoding.UTF8.GetBytes(plainStr); ICryptoTransform crypto = aesEncryption.CreateEncryptor(); byte[] cipherText = crypto.TransformFinalBlock(plainText, 0, plainText.Length); return Convert.ToBase64String(cipherText); } private static string Decrypt(string encryptedText, string KeyString) { RijndaelManaged aesEncryption = new RijndaelManaged(); aesEncryption.KeySize = 256; aesEncryption.BlockSize = 128; aesEncryption.Mode = CipherMode.ECB; aesEncryption.Padding = PaddingMode.ISO10126; byte[] KeyInBytes = Encoding.UTF8.GetBytes(KeyString); aesEncryption.Key = KeyInBytes; ICryptoTransform decrypto = aesEncryption.CreateDecryptor(); byte[] encryptedBytes = Convert.FromBase64CharArray(encryptedText.ToCharArray(), 0, encryptedText.Length); return ASCIIEncoding.UTF8.GetString(decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length)); } String KeyString = GenerateAPassKey("PassKey"); String EncryptedPassword = Encrypt("25Characterlengthpassword!", KeyString); String DecryptedPassword = Decrypt(EncryptedPassword, KeyString); 
+4
May 27 '11 at 20:20
source share

If you need more of this, for example, to protect the connection string (to connect to the 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.

+1
Oct 17 '08 at 15:06
source share

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

0
Oct 17 '08 at 15:02
source share

Instead of encrypting / decrypting, you should pass the password through a hash algorithm, md5 / sha512 or the like. What you ideally do is a hash password and saving the hash, then when you need a password, you record and compare entries. The password will never be "decrypted", just hashed, and then compare.

-one
Oct 17 '08 at 15:01
source share



All Articles