Мне нужно зашифровать / расшифровать некоторые строки. Я создал свой класс-оболочку в соответствии с документация msdn, но с некоторыми изменениями.
Поскольку я хочу зашифровать / расшифровать данные с помощью заданной строки / парольной фразы, я не использую AesManaged
для создания ключа. (Пользователь должен иметь возможность шифровать / дешифровать ключом, который он вводит, поэтому я не могу использовать ключ из AesManaged
и не могу сохранить ключ).
Вместо этого я создаю ключ, используя Rfc2898DeriveBytes
(PBKDF2) с заданной солью. Данная соль используется, так как я не храню ключ, и я думаю, из-за этого соль всегда должна быть одинаковой.
Затем я создаю IV, шифрую данную строку и объединяю IV и зашифрованную строку. В конечном итоге это будет сохранено в файле. Это означает, что IV сохраняется вместе с зашифрованными данными.
Вопросы:
- Можно ли хранить IV вместе с зашифрованными данными?
- Есть ли другой способ создать ключ, не используя каждый раз одну и ту же соль (на основе заданной кодовой фразы)?
- Это шифрование выполняется с использованием AES128 или AES256?
- Будет ли IV всегда 16 байтов, или это может измениться?
static void Main(string[] args)
{
const string stringToEncrypt = "String to be encrypted/decrypted. Encryption is done via AesManaged";
const string password = "m1Sup3rS3cre!Password";
string encrypted = EncryptString(stringToEncrypt, password);
string roundtrip = DecryptStringFromBytes_Aes(encrypted, password);
Console.WriteLine("Original: {0}", stringToEncrypt);
Console.WriteLine("Round Trip: {0}", roundtrip);
Console.ReadLine();
}
static string EncryptString(string plainText, string password)
{
string encryptedString;
using (AesManaged aesAlg = new AesManaged())
{
aesAlg.Key = PasswordAsByte(password);
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
var encrypted = msEncrypt.ToArray();
encryptedString = Encoding.Default.GetString(aesAlg.IV);
encryptedString += Encoding.Default.GetString(encrypted);
}
}
}
return encryptedString;
}
static string DecryptStringFromBytes_Aes(string cipherText, string password)
{
using (AesManaged aesAlg = new AesManaged())
{
aesAlg.Key = PasswordAsByte(password);
aesAlg.IV = Encoding.Default.GetBytes(cipherText).Take(16).ToArray();
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
var encryptedByteArray = Encoding.Default.GetBytes(cipherText).Skip(16).ToArray();
using (MemoryStream msDecrypt = new MemoryStream(encryptedByteArray))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
return srDecrypt.ReadToEnd();
}
}
}
}
}
private static byte[] PasswordAsByte(string password)
{
byte[] salt = Encoding.Default.GetBytes("foobar42");
Rfc2898DeriveBytes passwordBytes = new Rfc2898DeriveBytes(password, salt);
return passwordBytes.GetBytes(32);
}