Элементам управления окна на рис. 2 соответствуют объекты программы с именами (значениями свойства Name), указанными в табл. 2.
Для работы с потоком данных в оперативной памяти в программе используется класс MemoryStream из пространства имен System. IO, имеющий конструктор без параметров и конструктор с параметром типа byte[], который задает массив байт, связываемый с потоком данных в оперативной памяти. Метод
byte[] ToArray()
этого класса позволяет получить данные из потока в оперативной памяти.
Для кодирования шифротекста перед его отображением в окне используется метод класса Encoding
string GetString(byte[] bytes, int index, int count)
позволяющий получить строку символов, соответствующую данным длиной count байт из массива bytes, начиная с элемента index.

Рис. 2. Шифрование и расшифрование введенного сообщения
Таблица 2
Имена объектов программ для элементов управления
Элемент управления окна | Его имя в программе |
Редактор для ввода сообщения | PlainText |
Редактор для отображения шифротекста | CipherText |
Список для выбора длины ключа | KeyLen |
Кнопка «Зашифровать» | Encrypt |
Кнопка «Расшифровать» | Decrypt |
Кнопка «Выход» | Exit |
Ниже приведен текст программы на языке C#:
using System;
using System. Collections. Generic;
using ponentModel;
using System. Data;
using System. Drawing;
using System. Linq;
using System. Text;
using System. Windows. Forms;
// подключение пространства имен классов криптографии
using System. Security. Cryptography;
// подключение пространства имен для классов работы с памятью
using System. IO;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
// объект класса для криптоалгоритма
AesManaged Aes;
// буфер для случайного секретного ключа
byte[] key;
// длина ключа
int KeyLength;
// объект класса для потока данных в оперативной памяти
MemoryStream msEncrypt;
// объект для криптографического потока данных
CryptoStream csEncrypt;
// буфер для массива байт шифруемой строки
byte[] toEncrypt;
// буфер для массива расшифрованных байт
byte[] encrypted;
// массив данных для списка возможных значений длины ключа
int[] ksizes;
// конструктор класса формы главного окна программы
public Form1()
{
InitializeComponent();
//создание объекта для алгоритма шифрования
Aes = new AesManaged();
// получение случайного начального вектора
Aes. GenerateIV();
// установка режима блочного шифрования
Aes. Mode = CipherMode. CBC;
// массив допустимых значений длины ключа
KeySizes[] ks=Aes. LegalKeySizes;
// получение минимально возможной длины ключа
KeyLength = ks[0].MinSize;
// индексы элемента списка и выделенного элемента
int i=0, isel=0;
// максимальная длина ключа и длина ключа по умолчанию
int ksmax= ks[0]. MaxSize, ksdef= Aes. KeySize;
// создание массива данных для списка
ksizes=new int[3];
// заполнение списка возможных значений длины ключа
do
{
ksizes[i] = KeyLength;
// сохранение индекса для длины ключа по умолчанию
if (KeyLength == ksdef)
isel = i;
// увеличение возможной длины ключа
KeyLength += ks[0].SkipSize;
i++;
}
while (KeyLength <= ksmax);
// связывание списка с массивом данных
KeyLen. DataSource = ksizes;
// выделение элемента списка
KeyLen. SelectedIndex = isel;
}
// обработка нажатия кнопки "Выход"
private void Exit_Click(object sender, EventArgs e)
{
// закрытие главного окна
Close();
}
// обработка изменения открытого текста
private void PlainText_TextChanged(object sender, EventArgs e)
{
/* блокирование кнопки "Зашифровать", если открытый текст не введен */
Encrypt. Enabled = PlainText. Text. Length!= 0;
}
// обработка изменения шифротекста
private void CipherText_TextChanged(object sender, EventArgs e)
{
/* блокирование кнопки "Расшифровать", если шифротекст не получен */
Decrypt. Enabled = CipherText. Text. Length!= 0;
}
// обработка нажатия кнопки "Зашифровать"
private void Encrypt_Click(object sender, EventArgs e)
{
// очистка редактора с шифротекстом
CipherText. Clear();
// создание объекта для потока данных в оперативной памяти
msEncrypt = new MemoryStream();
// декодирование введенной строки открытого текста
toEncrypt = Encoding. Unicode. GetBytes(PlainText. Text);
// полученние выбранной длины ключа
KeyLength = ksizes[KeyLen. SelectedIndex];
// задание длины секретного ключа
Aes. KeySize = KeyLength;
// создание объекта для генерации случайного ключа
RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
// выделение памяти под случайный ключ
key = new byte[KeyLength/8];
// получение случайного ключа
rand. GetBytes(key);
// задание секретного ключа для шифрования
Aes. Key = key;
// создание объекта для выполнения шифрования потока
ICryptoTransform encryptor = Aes. CreateEncryptor(Aes. Key, Aes. IV);
// создание объекта для криптографического потока
csEncrypt = new CryptoStream(msEncrypt, encryptor,
CryptoStreamMode. Write);
// шифрование открытого текста
csEncrypt. Write(toEncrypt, 0, toEncrypt. Length);
// закрытие криптографического потока
csEncrypt. Close();
// получение шифротекста
encrypted = msEncrypt. ToArray();
// отображение шифротекста
CipherText. Text = Encoding. Unicode. GetString(encrypted, 0,
encrypted. Length);
// блокирование кнопки "Зашифровать"
Encrypt. Enabled = false;
// блокирование списка для выбора длины ключа
KeyLen. Enabled = false;
// закрытие потока в памяти
msEncrypt. Close();
}
// обработка нажатия кнопки "Расшифровать"
private void Decrypt_Click(object sender, EventArgs e)
{
// очистка строки с открытым текстом
PlainText. Clear();
// создание объекта для выполнения расшифрования потока
ICryptoTransform decryptor = Aes. CreateDecryptor(Aes. Key, Aes. IV);
// получение шифротекста
encrypted = Encoding. Unicode. GetBytes(CipherText. Text);
// создание объекта для данных в оперативной памяти
msEncrypt = new MemoryStream(encrypted);
// создание объекта для криптографического потока
csEncrypt = new CryptoStream(msEncrypt, decryptor,
CryptoStreamMode. Read);
// выделение памяти для расшифрованногог текста
toEncrypt = new byte[encrypted. Length];
// расшифрование данных
csEncrypt. Read(toEncrypt, 0, encrypted. Length);
// отображение расшифрованного открытого текста
PlainText. Text = Encoding. Unicode. GetString(toEncrypt, 0,
toEncrypt. Length);
// закрытие криптографического потока
csEncrypt. Close();
// блокирование кнопки "Расшифровать"
Decrypt. Enabled = false;
// закрытие потока в памяти
msEncrypt. Close();
}
}
}
1.3. Непосредственное обращение к криптопровайдерам в приложениях для Microsoft. Net
Как уже отмечалось во введении, среди криптографических классов библиотеки FCL отсутствуют классы, реализующие некоторые широко распространенные криптографические алгоритмы, например, алгоритм потокового симметричного шифрования RC4.
Для создания класса с реализацией алгоритма RC4 потребуется создать новый класс-наследник абстрактного класса SymmetricAlgorithm. В создаваемом классе потребуется переопределить следующие абстрактные методы базового класса SymmetricAlgorithm:
· void GenerateKey() − генерация случайного ключа симметричного шифрования;
· void GenerateIV() − генерация случайного вектора инициализации, необходимого при использовании только блочных алгоритмов симметричного шифрования, к которым RC4 не относится;
· ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV) – создание объекта для шифрования данных с заданным значением ключа и неиспользуемым значением начального вектора;
· ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV) – создание объекта для расшифрования данных с заданным значением ключа и неиспользуемым значением начального вектора.
Интерфейс ICryptoTransform (базовый набор криптографических преобразований) включает свойства:
· bool CanReuseTransform – признак возможности повторного использования криптографического преобразования;
· bool CanTransformMultipleBlocks – признак возможности преобразования нескольких блоков данных;
· int InputBlockSize – размер входного блока данных в байтах;
· int OutputBlockSize – размер выходного блока данных в байтах.
Методы интерфейса ICryptoTransform:
· void Dispose() – освобождение ресурсов преобразования;
· int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) – преобразование inputCount байт из буфера inputBuffer со смещением inputOffset и запись результата в буфер outputBuffer со смещением outputOffset (метод возвращает количество записанных байт);
· byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) – преобразование inputCount байт последнего блока входных данных inputBuffer со смещением inputOffset (метод возвращает указатель на массив преобразованных данных).
Напомним, что интерфейсы в языке программирования C# являются альтернативным по отношению к абстрактным классам способом определения базовых методов для множества объектов. Создаваемый класс для реализации дополнительного алгоритма симметричного шифрования должен быть наследником класса SymmetricAlgorithm и наследником интерфейса ICryptoTransform. В нем должны быть определены абстрактные методы класса SymmetricAlgorithm и все методы интерфейса ICryptoTransform.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |


