As web or application developers it is advisable to never transmit or store passwords as plain text. If unencrypted, a person could intentionally (or unintentionally) discover somebody else’s password. The technique described in this post is certainly not 100% secure but it makes password cracking difficult. To obtain a person’s original password the hacker must have the encrypted password and the key embedded in the client application.
The code included below will work in both Silverlight and .NET. An Advanced Encryption Standard (AES) symmetric algorithm is used to scramble/descramble text as shown in the screenshot above.
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Windows;
namespace TestPasswordEncryption {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
// Encrypt Text
this.ButtonEncrypt.Click += (s, e) => {
this.TextBoxEncrypted.Text =
Scrambler.Encrypt(this.TextBoxOriginal.Text);
};
// Decrypt Text
this.ButtonDecrypt.Click += (s, e) => {
this.TextBoxDecrypted.Text =
Scrambler.Decrypt(this.TextBoxEncrypted.Text);
};
}
}
internal class Scrambler {
private const string PASS = "6D114A94-375E-4FFD-9F48-CF2C7A12620F";
private const string SALT = "E5A8DB1B-5EAB-4C62-B322-CE24CE274303";
internal static string Encrypt(string input) {
// Test data
byte[] utfdata = UTF8Encoding.UTF8.GetBytes(input);
byte[] saltBytes = UTF8Encoding.UTF8.GetBytes(Scrambler.SALT);
// We're using the PBKDF2 standard for password-based key generation
Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(
Scrambler.PASS, saltBytes, 1000);
// Our symmetric encryption algorithm
AesManaged aes = new AesManaged();
aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
aes.KeySize = aes.LegalKeySizes[0].MaxSize;
aes.Key = rfc.GetBytes(aes.KeySize / 8);
aes.IV = rfc.GetBytes(aes.BlockSize / 8);
// Encryption
ICryptoTransform encryptTransf = aes.CreateEncryptor();
// Output stream, can be also a FileStream
MemoryStream encryptStream = new MemoryStream();
CryptoStream encryptor = new CryptoStream(
encryptStream, encryptTransf, CryptoStreamMode.Write);
encryptor.Write(utfdata, 0, utfdata.Length);
encryptor.Flush();
encryptor.Close();
// Showing our encrypted content
byte[] encryptBytes = encryptStream.ToArray();
string encryptedString = Convert.ToBase64String(encryptBytes);
// Close stream
encryptStream.Close();
// Return encrypted text
return encryptedString;
}
internal static string Decrypt(string base64Input) {
// Get inputs as bytes
byte[] encryptBytes = Convert.FromBase64String(base64Input);
byte[] saltBytes = Encoding.UTF8.GetBytes(Scrambler.SALT);
// We're using the PBKDF2 standard for password-based key generation
Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(
Scrambler.PASS, saltBytes);
// Our symmetric encryption algorithm
AesManaged aes = new AesManaged();
aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
aes.KeySize = aes.LegalKeySizes[0].MaxSize;
aes.Key = rfc.GetBytes(aes.KeySize / 8);
aes.IV = rfc.GetBytes(aes.BlockSize / 8);
// Now, decryption
ICryptoTransform decryptTrans = aes.CreateDecryptor();
// Output stream, can be also a FileStream
MemoryStream decryptStream = new MemoryStream();
CryptoStream decryptor = new CryptoStream(
decryptStream, decryptTrans, CryptoStreamMode.Write);
decryptor.Write(encryptBytes, 0, encryptBytes.Length);
decryptor.Flush();
decryptor.Close();
// Showing our decrypted content
byte[] decryptBytes = decryptStream.ToArray();
string decryptedString = UTF8Encoding.UTF8.GetString(
decryptBytes, 0, decryptBytes.Length);
// Close Stream
decryptStream.Close();
// Return decrypted text
return decryptedString;
}
}
}