Visual Basic, .NET, ASP, VBScript
 

   
 

.NET разработчик, автор множества статей. В ранние годы (2001 - 2003) занимался разработкой на Visual Basic 6 и Active Server Pages, с 2003 года в основном занят разработкой корпоративного программного обеспечения на платформе Microsoft .NET (C#, VB.NET; ASP.NET, Silverlight). Личный блог: http://pavel.surmenok.com/

 
     
   
 

Введение

Криптография используется для защиты данных от просмотра и модификации. Основными задачами криптографии являются:

 

·         Конфиденциальность данных: защита данных от просмотра

·         Целостность данных: защита данных от изменения в процессе передачи или хранения

·         Аутентификация: гарантия, что данные были отправлены тем, кто их должен был отправить

 

Наиболее актуальными вопросы защиты данных являются для разработчиков Интернет-приложений, особенно, оперирующих коммерческими данными. Для решения этих задач в 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 предоставляет нам богатые возможности для защиты данных. В этой статье были рассмотрены классы для шифрования данных. В ближайшее время я постараюсь написать также о хешировании и цифровой подписи данных.

 

Павел Сурменок
pavel@vbnet.ru
http://vbnet.ru
 
     

   
   
     
  VBNet рекомендует