Порой у разработчиков появляется необходимость шифровать текстовые данные для защиты пользователя от перехвата данных.
В этом кратком уроке я расскажу вам о некоторых способах шифровки этих данных и их расшифровки.
Криптографический алгоритм AES
это т. н. «симметричный» алгоритм шифрования, принятый в качестве стандарта и широко используемый в различных областях IT и вообще практически во всех сферах нашей, немыслимой без современных технологий, жизни.
Такую популярность AES завоевал благодаря (относительной) простоте, эффективности выполнения своей основной задачи по шифрованию информации, открытости, надёжности и проверенности временем и конечно благодаря стандартизации и признанию на официальном уровне.
В данный момент AES используется для шифрования информации в интернете, для передачи данных в различных сетях проводным и беспроводным способом, в различных устройствах и гаджетах и т. д., то есть везде, где нужно качественно шифровать информацию, затрачивая при этом минимум вычислительной мощности.
AES относится к так называемым «симметричным» алгоритмам, которые для шифрования и расшифровывания информации используют один и тот же криптографический ключ. Вообще, подобный тип шифрования является одним из самых распространённых и давно используемых.
При работе по принципу симметричного шифрования, секретный ключ имеется у обеих сторон взаимодействия (отправителя и получателя информации) и должен храниться и передаваться соответствующим безопасным образом.
Длина ключей в AES может выбираться из нескольких стандартных значений 128,192, 256 бит, в зависимости от решаемой задачи и необходимого уровня защиты данных.
Существуют также и другие алгоритмы шифрования, например, т. н. «несимметричное шифрование» в котором для шифрования и расшифровки используются разные ключи. Каждый тип алгоритма имеет свои достоинства и недостатки и свои области применения, в которых показывают себя наилучшим образом.
Пример реализации на C#
Теперь давайте попробуем реализовать метод шифрования:
Где EncryptionKey = "MAKV2SPBNI99212" это ключ шифрования
public static string Encrypt(string clearText)
{
string EncryptionKey = "MAKV2SPBNI99212";
byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
}
return clearText;
}
А также метод расшифровки:
public static string Decrypt(string cipherText)
{
try
{
string EncryptionKey = "MAKV2SPBNI99212";
byte[] cipherBytes = Convert.FromBase64String(cipherText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
}
cipherText = Encoding.Unicode.GetString(ms.ToArray());
}
}
return cipherText;
} catch { return String.Empty; }
}
Этот метод использует симметричное шифрование Rijndael/AES в режиме CBC (Cipher Block Chaining) с генерацией ключа через PasswordDeriveBytes.
public string Encrypt(string plainText, string password, string salt = "Kosher", string hashAlgorithm = "SHA1", int passwordIterations = 2, string initialVector = "OFRna73m*aze01xY", int keySize = 256)
{
if (string.IsNullOrEmpty(plainText))
return "";
byte[] initialVectorBytes = Encoding.ASCII.GetBytes(initialVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(salt);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
PasswordDeriveBytes derivedPassword = new PasswordDeriveBytes(password, saltValueBytes, hashAlgorithm, passwordIterations);
byte[] keyBytes = derivedPassword.GetBytes(keySize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
byte[] cipherTextBytes = null;
using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initialVectorBytes))
{
using (MemoryStream memStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
cipherTextBytes = memStream.ToArray();
memStream.Close();
cryptoStream.Close();
}
}
}
symmetricKey.Clear();
return Convert.ToBase64String(cipherTextBytes);
}
public string Decrypt(string cipherText, string password, string salt = "Kosher", string hashAlgorithm = "SHA1", int passwordIterations = 2, string initialVector = "OFRna73m*aze01xY", int keySize = 256)
{
if (string.IsNullOrEmpty(cipherText))
return "";
byte[] initialVectorBytes = Encoding.ASCII.GetBytes(initialVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(salt);
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
PasswordDeriveBytes derivedPassword = new PasswordDeriveBytes(password, saltValueBytes, hashAlgorithm, passwordIterations);
byte[] keyBytes = derivedPassword.GetBytes(keySize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int byteCount = 0;
using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initialVectorBytes))
{
using (MemoryStream memStream = new MemoryStream(cipherTextBytes))
{
using (CryptoStream cryptoStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read))
{
byteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memStream.Close();
cryptoStream.Close();
}
}
}
symmetricKey.Clear();
return Encoding.UTF8.GetString(plainTextBytes, 0, byteCount);
}