Защита данных в .NET
ОГЛАВЛЕНИЕ
Данная статья кратко объясняет распространенные криптосистемы и подробно описывает два самых популярных шифра с закрытым ключом: DES – наиболее широко используемый, и AES – собирающийся заменить DES.
• Примеры кода .NET по криптологии [исходник - 38.5 Кб] [демо - 9.96 Кб]
• Реализация AES и DES на C# [исходник - 35.7 Кб] [демо - 13.1 Кб]
1. Введение
Криптология – область, занимающаяся обеспечением безопасности и конфиденциальности. Эта область включает в себя много криптосистем, каждая из которых состоит из набора алгоритмов, направленных на обеспечение защиты данных. Сейчас криптосистемы широко применяются во всех областях цифровых технологий. Цифровые подписи, электронная почта и интернет-банкинг – лишь несколько приложений, в которых используются криптосистемы. Данная статья кратко объясняет распространенные криптосистемы и подробно описывает два самых популярных шифра с закрытым ключом: DES – наиболее широко используемый, и AES – собирающийся заменить DES. Следует начать с обзора распространенных криптосистем.
2. Обзор распространенных криптосистем
Три криптосистемы являются основой множества приложений безопасности: симметричные криптосистемы, асимметричные криптосистемы и хеширование.
2.a Симметричные (с закрытым ключом) криптосистемы
Симметричные криптосистемы используют один и тот же ключ в операциях шифрования и расшифровки. Эти две операции обычно похожи. Однако некоторые части данных операций придерживаются обратного порядка относительно друг друга (например, для AES алгоритм расшифровки придерживается обратного порядка относительно алгоритма шифрования, с небольшим изменением в некоторых других методах).
Симметричные криптосистемы делят данные на маленькие блоки и шифруют их по одному с помощью секретного ключа. Затем блоки объединяются и отправляются получателю в совокупности. На стороне получателя применяется операция расшифровки с использованием того же самого ключа, что дает восстановленные данные.
Симметричные алгоритмы очень быстрые по сравнению с асимметричными алгоритмами шифрования и хорошо подходят для выполнения криптографических преобразований над большими потоками данных. Самые популярные алгоритмы симметричного шифрования - DES, AES и TripleDES. TripleDES использует DES три раза подряд с разными ключами. DES и AES будут подробно рассмотрены позже.
Блок-схема симметричных криптосистем
Открытый текст шифруется закрытым ключом, передается, затем расшифровывается тем же самым закрытым ключом.
//простая операция шифрования закрытым ключом
private void buttonEncrypt_Click(object sender, EventArgs e)
{
string password = textBoxKey.Text;
string salt = textBoxSalt.Text;
string plainText = textBoxInput.Text;
byte[]plainBytes=Encoding.ASCII.GetBytes(plainText);
//Rfc2898DeriveBytes: используется для генерации стойких ключей
Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(password,
Encoding.ASCII.GetBytes(salt));
//неанглийские алфавиты не будут работать в кодировке ASCII
SymmetricAlgorithm Alg = GetSelectedAlgorithm();
Alg.Key = rfc.GetBytes(Alg.KeySize / 8);
Alg.IV = rfc.GetBytes(Alg.BlockSize / 8);
MemoryStream strCiphered = new MemoryStream();//для хранения зашифрованных данных
CryptoStream strCrypto = new CryptoStream(strCiphered,
Alg.CreateEncryptor(), CryptoStreamMode.Write);
strCrypto.Write(plainBytes, 0, plainBytes.Length);
strCrypto.Close();
textBoxCiphered.Text = Convert.ToBase64String(strCiphered.ToArray());
strCiphered.Close();
}
private SymmetricAlgorithm GetSelectedAlgorithm()
{
SymmetricAlgorithm Alg = null;
if (comboBoxAlgorithm.SelectedIndex == 0)
Alg = new DESCryptoServiceProvider();
else if (comboBoxAlgorithm.SelectedIndex == 1)
Alg = new RijndaelManaged();//RijndaelManaged: алгоритм AES в .NET
else if (comboBoxAlgorithm.SelectedIndex == 2)
Alg = new TripleDESCryptoServiceProvider();
else
Alg = new RC2CryptoServiceProvider();
return Alg;
}
2.b Асимметричные (с открытым ключом) криптосистемы
Асимметричные криптосистемы выполняют операции шифрования и расшифровки с помощью пар открытых-закрытых ключей, математически связанных друг с другом. В отличие от симметричных криптосистем, данные, зашифрованные открытым ключом, нельзя восстановить без использования закрытого ключа. Если данные шифруются закрытым ключом, то эти данные расшифровываются открытым ключом, и наоборот.
Асимметричные алгоритмы шифрования основаны на тяжелых математических операциях, поэтому они неэффективны в обработке больших блоков данных. Они часто применяются для безопасного обмена маленькими ключами сеанса. Асимметричные шифры используются для аутентификации и конфиденциальности. Самый популярный асимметричный алгоритм шифрования - RSA, понимание которого требует серьезной математической подготовки. Ниже показана структура RSA:
//Генерация открытого и закрытого ключей
Выбрать p,q так, чтобы p и q были двумя разными большими простыми числами
Пусть n=p*q
Пусть m=(p-1)*(q-1)
Выбрать e так, чтобы было 1<e<m и gcd(m,e)=1 (e взаимно-простой с m)
Вычислить такой d, чтобы было (d*e)mod(m) = 1
Открытый ключ: {e,n}
Закрытый ключ:{d,n}
//Шифрование
Открытый текст: M (M<n)
Шифротекст: C = M<sup>e</sup> Mod(n)
//Расшифровка
Шифротекст: C
Открытый текст: M = C<sup>d</sup> Mod(n)
Блок-схема асимметричных криптосистем
Открытый текст шифруется [Бобом] открытым ключом Алисы, передается, затем расшифровывается [Алисой] закрытым ключом Алисы.
/*
* В отличие от симметричных шифров, нельзя свободно выбрать
* пары открытых и закрытых ключей, потому что эти два ключа
* математически связаны друг с другом. Правильный способ
* создания этих ключей в .NET - использовать асимметричный класс,
* генерирующий данные ключи в своем конструкторе.
*/
private void GenerateKeyPairs()
{
//При каждом вызове этого конструктора
//генерируется другая пара открытого и закрытого ключей.
rsaCipher = new RSACryptoServiceProvider();
//извлечь открытые параметры
textBoxPublicKey.Text = rsaCipher.ToXmlString(false);
//извлечь закрытые параметры
textBoxPrivateKey.Text = rsaCipher.ToXmlString(true);
}
private void buttonEncrypt_Click(object sender, EventArgs e)
{
rsaCipher = new RSACryptoServiceProvider();
string publicKey = textBoxPublicKey.Text;
rsaCipher.FromXmlString(publicKey);
string plainText = textBoxPlain.Text;
byte[] plainBytes = Encoding.ASCII.GetBytes(plainText);
byte[] cipheredBytes = rsaCipher.Encrypt(plainBytes, true);
string cipheredText = Convert.ToBase64String(cipheredBytes);
textBoxCiphered.Text = cipheredText;
}
2.c Хеширование
Хеширование – операция взятия контрольной суммы данных. Назначение этого метода – сгенерировать уникальных ключ постоянного размера [из входных данных], который не могут дать никакие другие данные, тем самым делая невозможной генерацию данных из ключа. Хеширование очень полезно для систем баз данных. Представьте базу данных, хранящую пароли пользователей. Хранить пароли в открытом виде не так безопасно, как хранить хеш-значения паролей в таблицах. Даже притом что любое хеш-значение содержится в базе данных, невозможно восстановить оригинальный пароль из этого значения. Данный метод обеспечивает такой же функционал для процессов авторизации. Единственное отличие в том, что хеш пароля пользователя сравнивается со значением в базе данных вместо сравнения самого пароля.
//хешировать ввод и отобразить результат
private void buttonComputeHash_Click(object sender, EventArgs e)
{
byte[] input = Encoding.ASCII.GetBytes(textBoxInput.Text);
HashAlgorithm Alg = GetSelectedAlgorithm();
Alg.ComputeHash(input);
textBoxHash.Text = Convert.ToBase64String(Alg.Hash);
}
private HashAlgorithm GetSelectedAlgorithm()
{
//только для алгоритмов хеширования с помощью ключей
Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(textBoxKey.Text,
Encoding.ASCII.GetBytes(textBoxSalt.Text));
HashAlgorithm Alg = null;
if (comboBoxAlgorithm.SelectedIndex == 0)
Alg = new MD5CryptoServiceProvider();
else if (comboBoxAlgorithm.SelectedIndex == 1)
Alg = new RIPEMD160Managed();
else if (comboBoxAlgorithm.SelectedIndex == 2)
Alg = new SHA1CryptoServiceProvider();
else if (comboBoxAlgorithm.SelectedIndex == 3)
Alg = new SHA256Managed();
else if (comboBoxAlgorithm.SelectedIndex == 4)
Alg = new SHA384Managed();
else if (comboBoxAlgorithm.SelectedIndex == 5)
Alg = new SHA512Managed();
else if (comboBoxAlgorithm.SelectedIndex == 6)
Alg = new MACTripleDES(rfc.GetBytes(16));
else if (comboBoxAlgorithm.SelectedIndex == 7)
Alg = new HMACSHA1(rfc.GetBytes(29));
return Alg;
}
2.d Применения цифровой подписи
Применения цифровой подписи основаны на двух криптографических методах: криптосистема с открытым ключом и хеширование. Они описаны выше, и теперь рассматривается их использование в простом приложении.
Допустим, надо отправить сообщение получателю так, чтобы он был однозначно уверен, что сообщение отправили вы, и что никто не изменил его содержимое во время передачи. Отправка сообщения с его хешем позволит получателю проверить, принадлежит хеш сообщению или нет. Если сообщение не изменено, хеш сообщения будет таким же, как и прикрепленный хеш. Но что если кто-то другой изменит и сообщение, и хеш во время передачи? Тогда надо позаботься о таком случае.
Рисунок ниже изображает блок-схему системы цифровой подписи, составленной из двух фаз: подписание документа (левая часть) и проверка подлинности документа (правая часть). Обе фазы используют криптосистему с открытым ключом для шифрования и расшифровки данных. В фазе подписания хеш сообщение шифруется закрытым ключом отправителя. Это значение (зашифрованный хеш) становится подписью и отправляется получателю вместе с оригинальным сообщением. Потом, в фазе проверки подлинности, получатель расшифровывает подпись (зашифрованный хеш) открытым ключом отправителя. Эта операция дает значение хеша, которое отправитель уже вычислил. Получатель тоже вычисляет хеш полученного сообщения и сравнивает его с хешем отправителя. Если два значение хеша идентичны, то подлинность документов подтверждена, в противном случае нет.
Блок-схема применения цифровой подписи