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 w
I have looked all over for a good example of encryption and decryption process but most were overly complex.
Anyhow there are many reasons someone may want to decrypt some text values including passwords. The reason I need to decrypt the password on the site I am working on currently is because they want to make sure when someone is forced to change their password when it expires that we do not let them change it with a close variant of the same password they used in the last x months.
So I wrote up a process that will do this in a simplified manner. I hope this code is beneficial to someone. For all I know I may end up using this at another time for a different 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);
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.
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.
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.
Edit: As raw computing power becomes cheaper and faster, the value of hashing -- or salting hashes -- has declined. Jeff Atwood has an excellent 2012 update too lengthy to repeat in its entirety here which states:
This (using salted hashes) will provide the illusion of security more than any actual security. Since you need both the salt and the choice of hash algorithm to generate the hash, and to check the hash, it's unlikely an attacker would have one but not the other. If you've been compromised to the point that an attacker has your password database, it's reasonable to assume they either have or can get your secret, hidden salt.
The first rule of security is to always assume and plan for the worst. Should you use a salt, ideally a random salt for each user? Sure, it's definitely a good practice, and at the very least it lets you disambiguate two users who have the same password. But these days, salts alone can no longer save you from a person willing to spend a few thousand dollars on video card hardware, and if you think they can, you're in trouble.
..NET provides cryptographics services in class contained in the System.Security.Cryptography namespace.
Hash them using something like the 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);
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).
I've upgraded the hashing algorithm but for the best possible strength you want to keep a private salt and add that to your input before hashing it. You would do this again when you compare. This adds another layer making it even harder for somebody to reverse.