I am using the AES class (which I think I got from another post on Stack Overflow) for encrypting strings to a database. How robust and secure (would it be easy to break) is this class? Is there any way I can improve it as it is storing usernames and passwords?
Please be gentle as I have to be honest although I have spent a few days looking into AES encryption. It's still all a little murky and just looking for some advice\input.
When I encrypt a string, the same password is used but the salt is always different.
Example usage:
AES encrypt = new AES("password","Unique string");
encrypt.Encrypt(stringtoencrypt);
Class:
public class AES
{
// Symmetric algorithm interface is used to store the AES service provider
private SymmetricAlgorithm AESProvider;
/// <summary>
/// Constructor for AES class that takes a byte array for the key
/// </summary>
/// <param name="key">256 bit key (32 bytes)</param>
public AES(byte[] key)
{
// Throw error if key is not 256 bits
if (key.Length != 32) throw new CryptographicException("Key must be 256 bits (32 bytes)");
// Initialize AESProvider with AES algorithm service
AESProvider = new AesCryptoServiceProvider();
AESProvider.KeySize = 256;
// Set the key for AESProvider
AESProvider.Key = key;
}
/// <summary>
/// Constructor for AES class that generates the key from a hashed, salted password
/// </summary>
/// <param name="password">Password used to generate the key (Minimum of 8 characters)</param>
/// <param name="salt">Salt used to secure hash from rainbow table attacks (Minimum of 8 characters)</param>
public AES(string password, string salt)
{
// Throw error if the password or salt are too short
if (password.Length < 8) throw new CryptographicException("Password must be at least 8 characters long");
if (salt.Length < 8) throw new CryptographicException("Salt must be at least 8 characters long");
// Initialize AESProvider with AES algorithm service
AESProvider = new AesCryptoServiceProvider();
AESProvider.KeySize = 256;
// Initialize a hasher with the 256 bit SHA algorithm
SHA256 sha256 = System.Security.Cryptography.SHA256.Create();
// Hash salted password
byte[] key = sha256.ComputeHash(UnicodeEncoding.Unicode.GetBytes(password + salt));
// Set the key for AESProvider
AESProvider.Key = key;
}
/// <summary>
/// Encrypts a string with AES algorithm
/// </summary>
/// <param name="plainText">String to encrypt</param>
/// <returns>Encrypted string with IV prefix</returns>
public string Encrypt(string plainText)
{
// Create new random IV
AESProvider.GenerateIV();
// Initialize encryptor now that the IV is set
ICryptoTransform encryptor = AESProvider.CreateEncryptor();
// Convert string to bytes
byte[] plainBytes = UnicodeEncoding.Unicode.GetBytes(plainText);
// Encrypt plain bytes
byte[] secureBytes = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
// Add IV to the beginning of the encrypted bytes
secureBytes = AESProvider.IV.Concat(secureBytes).ToArray();
// Return encrypted bytes as a string
return Convert.ToBase64String(secureBytes);
}
/// <summary>
/// Decrypts a string with AES algorithm
/// </summary>
/// <param name="secureText">Encrypted string with IV prefix</param>
/// <returns>Decrypted string</returns>
public string Decrypt(string secureText)
{
// Convert encrypted string to bytes
byte[] secureBytes = Convert.FromBase64String(secureText);
byte[] plainBytes = null;
// Take IV from beginning of secureBytes
AESProvider.IV = secureBytes.Take(16).ToArray();
// Initialize decryptor now that the IV is set
ICryptoTransform decryptor = AESProvider.CreateDecryptor();
// Decrypt bytes after the IV
try
{
plainBytes = decryptor.TransformFinalBlock(secureBytes, 16, secureBytes.Length - 16);
}
catch (Exception e)
{
Logger log = new Logger(DateTime.Now, "Decrypt Error", e.Message);
log.WriteErrorLog();
}
// Return decrypted bytes as a string
try
{
return UnicodeEncoding.Unicode.GetString(plainBytes);
}
catch (Exception ex)
{
Logger log = new Logger(DateTime.Now, "Decrypt Error - Possible wrong password", ex.Message);
log.WriteErrorLog();
return "#1Error#1";
}
}
}
IDisposable
, such asICryptoTransform
, ensure you wrap everything in appropriateusing()
blocks. \$\endgroup\$