Введение
Криптография используется для защиты данных от просмотра и
модификации. Основными задачами криптографии являются:
·
Конфиденциальность данных: защита данных от просмотра
·
Целостность данных: защита данных от изменения в процессе
передачи или хранения
·
Аутентификация: гарантия, что данные были отправлены тем, кто их
должен был отправить
Наиболее актуальными вопросы защиты данных являются для
разработчиков Интернет-приложений, особенно, оперирующих коммерческими данными.
Для решения этих задач в 1996 году корпорация Microsoft разработала Cryptography API (CryptoAPI).
Сейчас, когда на арену вышла платформа Microsoft .NET, мы можем насладиться всей мощью криптографических
сервисов, которые раскинулись в пространстве имён System.Security.Cryptography.
Основными элементами криптографии являются шифрование и хеширование
данных. В данной статье мы рассмотрим шифрование.
Шифрование
Существуют два основных типа алгоритмов шифрования: симметричный и
асимметричный. При использовании симметричных алгоритмов шифрования для
шифрования и расшифровки сообщений используется один и тот же ключ. Основное
преимущество симметричного шифрования заключается в быстроте шифрования и
расшифровки сообщений. Однако у него есть один серьёзный недостаток: необходимость
передачи ключа от одной стороны другой. Если при передаче ключ будет захвачен
злоумышленниками, то шифрование потеряет всякий смысл!
Асимметричное шифрование избавлено от этого недостатка. При
асимметричном шифровании используется пара ключей. Сообщение шифруется
публичным ключом, который может быть известен каждому. Но расшифровано оно
может быть только личным ключом, который хранится в секрете. Ключи связаны
математически так, что, зная публичный ключ, нельзя вычислить личный. Это очень
удобно, но за безопасность приходится платить низкой скоростью работы
асимметричного шифрования.
Чаще всего для шифрования данных совместно используют симметричный
и асимметричный алгоритм. Например, по такой схеме. Сначала первая сторона
генерирует пару ключей и отправляет по незащищённому каналу публичный ключ
второй стороне. Вторая сторона создаёт симметричный ключ, шифрует его
асимметричным алгоритмом с помощью полученного от первой стороны, публичного
ключа и отправляет зашифрованный симметричный ключ первой стороне. Затем идёт
обмен информацией, зашифрованной симметричным алгоритмом.
Алгоритмы шифрования, как и алгоритмы хеширования, реализованы
двухуровневым наследованием. На верхнем уровне расположен абстрактный класс (SymmetricAlgrithm для симметричных
алгоритмов и AsymmetricAlgorithm для
асимметричных алгоритмов). От него наследуют классы, реализующие конкретные
алгоритмы (например, Rijndael).
Симметричные алгоритмы
.NET Framework содержит классы,
реализующие следующие симметричные алгоритмы шифрования:
·
DESCryptoServiceProvider
·
RC2CryptoServiceProvider
·
RijndaelManaged
·
TripleDESCryptoServiceProvider
В отличие от асимметричного, симметричное шифрование основано на
потоках и предназначено для шифрования больших объёмов данных. Для шифрования
необходим ключ и вектор инициализации (IV).
Симметричное шифрование используется со специальным потоком CryptoStream, который шифрует данные. Конструктор класса CryptoStream содержит 3 параметра. Первый параметр - поток, в
который будут выводиться данные. Это может быть, например, FileStream,
NetworkStream или MemoryStream. В качестве второго параметра передаётся класс,
реализующий интерфейс ICryptoTransform. Он создаётся из
класса, реализующего алгоритм. При шифровании это делается методом CreateEncryptor, а при расшифровке – CreateDecryptor.
Они имеют одинаковый синтаксис. Оба метода перегружены. Вы можете задать ключ и
вектор инициализации (IV) в параметрах Key и IV соответственно. Если вы этого не сделаете, то будут
использованы ключ и вектор инициализации, заданные свойствами Key и IV объекта, реализующего алгоритм
(метод которого вы вызываете). Третий параметр конструктора класса CryptoStream – режим. Он может принимать значения
перечисления CryptoStreamMode. При шифровании данных
нужно указать значение Write, а при расшифровке – Read.
Ниже приведён пример шифрования и расшифровки данных симметричным
алгоритмом Rijndael.
Dim Key As Byte() = {1, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} 'Ключ
Dim IV As Byte() = {1, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} 'Вектор
инициализации
Private Sub Encrypt ()
'Создаём экземпляр класса
RijndaelManaged
Dim RMCrypto As New Security.Cryptography.RijndaelManaged
'Создаём
FileStream, туда будет записана зашифрованная информация
Dim fs As New IO.FileStream("C:\crypted.dat", IO.FileMode.Create)
'Создаём CryptoStream
Dim CryptStream As New Security.Cryptography.CryptoStream(fs,
RMCrypto.CreateEncryptor(Key, IV), Security.Cryptography.CryptoStreamMode.Write)
'Создаём
StreamWriter для записи данных в CryptoStream
Dim SWriter As
New IO.StreamWriter(CryptStream)
'Пишем что-нибудь в CryptoStream
SWriter.WriteLine("Эта информация зашифрована симметричным алгоритмом Rijndael!")
'Закрываем
все объекты
SWriter.Close()
fs.Close()
CryptStream.Close()
End Sub
Private Sub Decrypt ()
'Создаём экземпляр класса
RijndaelManaged
Dim RMCrypto As New Security.Cryptography.RijndaelManaged
'Создаём
FileStream, оттуда будем читать зашифрованную информацию
Dim fs As New IO.FileStream("C:\crypted.dat", IO.FileMode.Open)
'Создаём CryptoStream
Dim CryptStream As New Security.Cryptography.CryptoStream(fs,
RMCrypto.CreateDecryptor(Key, IV), Security.Cryptography.CryptoStreamMode.Read)
'Создаём
StreamReader для чтения данных из CryptoStream
Dim SReader As
New IO.StreamReader(CryptStream)
'Читаем
расшифрованную информацию из CryptoStream и пишем её в консоль
Console.WriteLine(SReader.ReadToEnd())
'Закрываем все объекты
SReader.Close()
fs.Close()
CryptStream.Close()
End Sub
Как создавать ключи? Случайные ключ и вектор инициализации
создаются автоматически при создании экземпляра класса, реализующего
симметричный алгоритм шифрования (например, RijndaelManaged).
Они расположены в свойствах Key и
IV соответственно. Если вы хотите сгенерировать новый
ключ, то нужно вызвать метод GenerateKey. Для создания
нового вектора инициализации необходимо вызвать метод GenerateIV.
Асимметричное шифрование
Асимметричное шифрование применяется для шифрования небольших
объёмов данных. Поэтому CryptoStream при асимметричном
шифровании не используется.
.NET Framework содержит классы RSACryptoServiceProvider
и DSACryptoServiceProvider, реализующие асимметричные
алгоритмы шифрования RSA и DSA.
Для хранения ключей используются классы RSAParameters и DSAParameters. При создании
экземпляра класса, реализующего алгоритм, пара ключей создаётся автоматически.
Вы можете экспортировать ключи из объекта RSACryptoServiceProvider
(или DSACryptoServiceProvider) с помощью метода ExportParameters. Метод возвращает экземпляр класса RSAParameters (или DSAParametrs для
алгоритма DSA). Также вы можете экспортировать
параметры в строку XML. Это делается с помощью метода ToXMLString. Оба метода содержат параметр типа Boolean. Если вы установить его равным True,
то помимо публичных параметров будет импортирован также личный ключ. Методы ImportParameters и FromXMLString позволят вам импортировать параметры из объекта RSAParameters (или DSAParameters) и
из строки XML соответственно.
Для шифрования данных используется метод Encrypt.
Он имеет 2 параметра. Первый параметр – шифруемые данные, байтовый массив. Второй
параметр имеет тип Boolean. Он задаёт тип отступа. Если
установить его равным True, то будет использован OAEP padding
(PKCS#1 v2), в противном случае используется Direct Encryption (PKCS#1 v1.5).
На мой взгляд, лучше использовать Direct Encryption, так как OAEP padding поддерживается
только на Windows XP и выше. Метод Encrypt возвращает
зашифрованные данные в байтовом массиве. Расшифровать данные можно с помощью
метода Decrypt. Он также принимает байтовый массив и
тип отступа и возвращает расшифрованные данные.
Ниже приведён небольшой пример асимметричного шифрования строки.
Dim CryptedData() As Byte 'Массив для хранения зашифрованных данных
Dim Params As Security.Cryptography.RSAParameters
'Параметры шифрования
Private Sub Encrypt()
'Созадём экземпляр класса
RSACryptoServiceProvider
Dim RSA As New Security.Cryptography.RSACryptoServiceProvider
Dim Data() As Byte 'Здесь будут данные
для шифрования
'Преобразуем строку в байтовый массив
Data = System.Text.Encoding.Default.GetBytes("Шифруемая строка")
'Шифруем данные
CryptedData = RSA.Encrypt(Data, False)
'Экспортируем параметры для того, чтобы в дальнейшем
расшифровать
Params = RSA.ExportParameters(True)
End Sub
Private Sub Decrypt()
'Созадём экземпляр класса
RSACryptoServiceProvider
Dim RSA As New Security.Cryptography.RSACryptoServiceProvider
'Импортируем ключи
RSA.ImportParameters(Params)
Dim Data() As Byte 'Здесь будут
расшифрованные данные
'Расшифровываем данные
Data = RSA.Decrypt(CryptedData, False)
'Преобразуем байтовый массив в строку и покажем юзеру
MsgBox(System.Text.Encoding.Default.GetString(Data))
End Sub
Заключение
.NET Framework предоставляет нам богатые
возможности для защиты данных. В этой статье были рассмотрены классы для
шифрования данных. В ближайшее время я постараюсь написать также о хешировании
и цифровой подписи данных.