Опубликован: 05.08.2010 | Доступ: свободный | Студентов: 2009 / 47 | Оценка: 4.50 / 4.40 | Длительность: 60:26:00
Лекция 6:

Работа с потоками данных

< Лекция 5 || Лекция 6: 12345678910111213

Пример 3. Поток CryptoStream и электронные подписи документов

Чтобы уж совсем завершить тему потока CryptoStream, рассмотрим еще одну сферу его применения - электронные подписи документов. Иногда получатель документа должен быть уверен, что этот документ не был искажен. В этом случае отправитель и получатель договариваются об одном и том же секретном ключе и применяют специальные алгоритмы хеширования, использующие ключ.

Напомним, что любые хеш-алгоритмы всегда генерируют значение постоянной длины (каждый своей) независимо от длины хешируемого текста. Но алгоритмы хеширования с ключами HMAC ( Hash Message Authentication ) отличаются от обычных алгоритмов хеширования тем, что они генерируют хеш на основании ключа. Отправитель документа вычисляет его хеш на основании секретного ключа и отправляет вместе с ключем получателю. Получатель извлекает хеш из присланного документа и повторно хеширует сам оставшийся документ с применением своего дубликата ключа. Если вычисленный хеш совпадает с полученным, то подлинность документа считается установленной.

Библиотека .NET Framework поддерживает задачи электронных подписей несколькими классами-алгоритмами пространства имен System.Security.Cryptography. Они принимают ключи разного размера и производят хеш-значение разной длины. Если длина применяемых ключей отличается от разрешенной, то любой из алгоритмов генерирует исключение.

Построим работоспособное приложение, выполняющее электронную подпись документа и устанавливающее его подлинность. Код приведем по сокращенной программе - без объяснений (достаточно комментариев, разберетесь, кто захочет!).

  • Добавьте к решению CryptoStream новый проект с именем Demo3 и назначьте его стартовым

  • Откройте интерфейсный файл Form1.Designer.cs и заполните его следующим кодом (приводится полностью)
namespace Demo3
{
    partial class Form1
    {
        private System.ComponentModel.IContainer components = null;
    
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
    
        #region Windows Form Designer generated code
    
        private void InitializeComponent()
        {
            this.cmbHMAC = new System.Windows.Forms.ComboBox();
            this.label1 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.txtSourceFile = new System.Windows.Forms.TextBox();
            this.btnSelectFile = new System.Windows.Forms.Button();
            this.txtDestinationDir = new System.Windows.Forms.TextBox();
            this.btnDestinationDir = new System.Windows.Forms.Button();
            this.label4 = new System.Windows.Forms.Label();
            this.txtKey = new System.Windows.Forms.TextBox();
            this.btnClose = new System.Windows.Forms.Button();
            this.lblInfo = new System.Windows.Forms.Label();
            this.label3 = new System.Windows.Forms.Label();
            this.btnSigned = new System.Windows.Forms.Button();
            this.btnChecked = new System.Windows.Forms.Button();
            this.btnShowFile = new System.Windows.Forms.Button();
            this.btnNewFile = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // cmbHMAC
            // 
            this.cmbHMAC.FormattingEnabled = true;
            this.cmbHMAC.Location = new System.Drawing.Point(94, 21);
            this.cmbHMAC.Name = "cmbHMAC";
            this.cmbHMAC.Size = new System.Drawing.Size(280, 24);
            this.cmbHMAC.TabIndex = 0;
            this.cmbHMAC.SelectedIndexChanged += new System.EventHandler(this.cmbHMAC_SelectedIndexChanged);
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(36, 24);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(51, 17);
            this.label1.TabIndex = 1;
            this.label1.Text = "HMAC:";
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(5, 156);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(83, 17);
            this.label2.TabIndex = 2;
            this.label2.Text = "Source File:";
            // 
            // txtSourceFile
            // 
            this.txtSourceFile.Location = new System.Drawing.Point(94, 155);
            this.txtSourceFile.Name = "txtSourceFile";
            this.txtSourceFile.Size = new System.Drawing.Size(280, 22);
            this.txtSourceFile.TabIndex = 3;
            this.txtSourceFile.KeyDown += new System.Windows.Forms.KeyEventHandler(this.EditKeyDown);
            this.txtSourceFile.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.EditKeyPress);
            // 
            // btnSelectFile
            // 
            this.btnSelectFile.Font = new System.Drawing.Font("Agency FB", 7.2F, System.Drawing.FontStyle.Bold, 
            	System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.btnSelectFile.Location = new System.Drawing.Point(380, 155);
            this.btnSelectFile.Name = "btnSelectFile";
            this.btnSelectFile.Size = new System.Drawing.Size(25, 23);
            this.btnSelectFile.TabIndex = 4;
            this.btnSelectFile.Text = "...";
            this.btnSelectFile.UseVisualStyleBackColor = true;
            this.btnSelectFile.Click += new System.EventHandler(this.btnSelectFile_Click);
            // 
            // txtDestinationDir
            // 
            this.txtDestinationDir.Location = new System.Drawing.Point(94, 198);
            this.txtDestinationDir.Name = "txtDestinationDir";
            this.txtDestinationDir.Size = new System.Drawing.Size(280, 22);
            this.txtDestinationDir.TabIndex = 6;
            // 
            // btnDestinationDir
            // 
            this.btnDestinationDir.Font = new System.Drawing.Font("Agency FB", 7.2F, System.Drawing.FontStyle.Bold, 
            	System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.btnDestinationDir.Location = new System.Drawing.Point(380, 198);
            this.btnDestinationDir.Name = "btnDestinationDir";
            this.btnDestinationDir.Size = new System.Drawing.Size(25, 23);
            this.btnDestinationDir.TabIndex = 7;
            this.btnDestinationDir.Text = "...";
            this.btnDestinationDir.UseVisualStyleBackColor = true;
            this.btnDestinationDir.Click += new System.EventHandler(this.btnDestinationDir_Click);
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(52, 67);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(36, 17);
            this.label4.TabIndex = 8;
            this.label4.Text = "Key:";
            // 
            // txtKey
            // 
            this.txtKey.Location = new System.Drawing.Point(94, 66);
            this.txtKey.Name = "txtKey";
            this.txtKey.Size = new System.Drawing.Size(280, 22);
            this.txtKey.TabIndex = 9;
            // 
            // btnClose
            // 
            this.btnClose.AutoSize = true;
            this.btnClose.Location = new System.Drawing.Point(353, 256);
            this.btnClose.Name = "btnClose";
            this.btnClose.Size = new System.Drawing.Size(75, 27);
            this.btnClose.TabIndex = 12;
            this.btnClose.Text = "Close";
            this.btnClose.UseVisualStyleBackColor = true;
            this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
            // 
            // lblInfo
            // 
            this.lblInfo.AutoSize = true;
            this.lblInfo.Location = new System.Drawing.Point(104, 110);
            this.lblInfo.Name = "lblInfo";
            this.lblInfo.Size = new System.Drawing.Size(45, 17);
            this.lblInfo.TabIndex = 15;
            this.lblInfo.Text = "lblInfo";
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(8, 186);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(79, 34);
            this.label3.TabIndex = 5;
            this.label3.Text = "Destination\r\ndirectory:";
            this.label3.TextAlign = System.Drawing.ContentAlignment.TopRight;
            // 
            // btnSigned
            // 
            this.btnSigned.AutoSize = true;
            this.btnSigned.Location = new System.Drawing.Point(98, 256);
            this.btnSigned.Name = "btnSigned";
            this.btnSigned.Size = new System.Drawing.Size(75, 27);
            this.btnSigned.TabIndex = 19;
            this.btnSigned.Text = "Signed";
            this.btnSigned.UseVisualStyleBackColor = true;
            this.btnSigned.Click += new System.EventHandler(this.btnSigned_Click);
            // 
            // btnChecked
            // 
            this.btnChecked.AutoSize = true;
            this.btnChecked.Location = new System.Drawing.Point(182, 256);
            this.btnChecked.Name = "btnChecked";
            this.btnChecked.Size = new System.Drawing.Size(75, 27);
            this.btnChecked.TabIndex = 20;
            this.btnChecked.Text = "Checked";
            this.btnChecked.UseVisualStyleBackColor = true;
            this.btnChecked.Click += new System.EventHandler(this.btnChecked_Click);
            // 
            // btnShowFile
            // 
            this.btnShowFile.AutoSize = true;
            this.btnShowFile.Location = new System.Drawing.Point(266, 256);
            this.btnShowFile.Name = "btnShowFile";
            this.btnShowFile.Size = new System.Drawing.Size(78, 27);
            this.btnShowFile.TabIndex = 21;
            this.btnShowFile.Text = "Show File";
            this.btnShowFile.UseVisualStyleBackColor = true;
            this.btnShowFile.Click += new System.EventHandler(this.btnShowFile_Click);
            // 
            // btnNewFile
            // 
            this.btnNewFile.AutoSize = true;
            this.btnNewFile.Location = new System.Drawing.Point(14, 256);
            this.btnNewFile.Name = "btnNewFile";
            this.btnNewFile.Size = new System.Drawing.Size(75, 27);
            this.btnNewFile.TabIndex = 22;
            this.btnNewFile.Text = "New File";
            this.btnNewFile.UseVisualStyleBackColor = true;
            this.btnNewFile.Click += new System.EventHandler(this.btnNewFile_Click);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(442, 296);
            this.Controls.Add(this.btnNewFile);
            this.Controls.Add(this.btnShowFile);
            this.Controls.Add(this.btnChecked);
            this.Controls.Add(this.btnSigned);
            this.Controls.Add(this.lblInfo);
            this.Controls.Add(this.btnClose);
            this.Controls.Add(this.txtKey);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.btnDestinationDir);
            this.Controls.Add(this.txtDestinationDir);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.btnSelectFile);
            this.Controls.Add(this.txtSourceFile);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.cmbHMAC);
            this.MaximizeBox = false;
            this.Name = "Form1";
            this.Text = "HMAC Algorithm with Files";
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
            this.ResumeLayout(false);
            this.PerformLayout();
        }
    
        #endregion
    
        private System.Windows.Forms.ComboBox cmbHMAC;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.TextBox txtSourceFile;
        private System.Windows.Forms.Button btnSelectFile;
        private System.Windows.Forms.TextBox txtDestinationDir;
        private System.Windows.Forms.Button btnDestinationDir;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.TextBox txtKey;
        private System.Windows.Forms.Button btnClose;
        private System.Windows.Forms.Label lblInfo;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.Button btnSigned;
        private System.Windows.Forms.Button btnChecked;
        private System.Windows.Forms.Button btnShowFile;
        private System.Windows.Forms.Button btnNewFile;
    }
}
  • Откройте файл Form1.cs в режиме View Code и заполните его следующим кодом (приводится полностью)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
    
// Дополнительные пространства имен
using System.Security.Cryptography;
using System.IO;
    
namespace Demo3
{
    public partial class Form1 : Form
    {
        // Объявляем ссылку на объект для хеширования документов
        KeyedHashAlgorithm hmac = null;// Тип общего предка 
        // Создаем объект сохранения параметров
        MySettings settings = new MySettings();// Это наш класс в файле MySettings.cs
    
        public Form1()
        {
            InitializeComponent();
    
            // Привязка именованных параметров к 
            // сохраняемым свойствам элементов управления
            txtDestinationDir.DataBindings.Add(new Binding("Text", settings, "DestinationDir"));
            txtSourceFile.DataBindings.Add(new Binding("Text", settings, "SourceFile"));
    
            // Настраиваем ComboBox динамически
            cmbHMAC.Items.AddRange(
                new string[]
                {
                    "HMACSHA1",
                    "MACTripleDES",
                    "HMACMD5",
                    "HMACRIPEMD160",
                    "HMACSHA256",
                    "HMACSHA384",
                    "HMACSHA512"
                });
    
            cmbHMAC.SelectedIndex = 0;// Выделяем первый элемент
        }
    
        // Меняем алгоритм хеширования
        private void cmbHMAC_SelectedIndexChanged(object sender, EventArgs e)
        {
            ComboBox cmb = sender as ComboBox;
            switch (cmb.SelectedIndex)
            {
                case 0:
                    hmac = new HMACSHA1();
                    break;
                case 1:
                    hmac = new MACTripleDES();
                    break;
                case 2:
                    hmac = new HMACMD5();
                    break;
                case 3:
                    hmac = new HMACRIPEMD160();
                    break;
                case 4:
                    hmac = new HMACSHA256();
                    break;
                case 5:
                    hmac = new HMACSHA384();
                    break;
                case 6:
                    hmac = new HMACSHA512();
                    break;
            }
    
            CorrectTextKey();
        }
    
        // Устанавливаем допустимую длину ввода
        void CorrectTextKey()
        {
            // Корректируем длину поля ввода ключа
            int lenKey = hmac.Key.Length;
            int lenTextBox = ASCIIEncoding.ASCII.GetByteCount(txtKey.Text);
            if (lenTextBox > lenKey)// Убираем лишнее
                txtKey.Text = txtKey.Text.Substring(0, lenKey);
            txtKey.MaxLength = lenKey;// Ограничение в поле ввода
            // Отображаем в текстовой метке
            lblInfo.Text = String.Format("Key Size: {0} bytes   Hash Size: {1} bytes",
                hmac.Key.Length, hmac.HashSize / 8);
        }
    
        // Создать новый текстовый файл через блокнот
        private void btnNewFile_Click(object sender, EventArgs e)
        {
            // Создаем новый текстовый файл через блокнот
            System.Diagnostics.Process exe = new System.Diagnostics.Process();
            exe.StartInfo.FileName = "Notepad.exe"; //Имя программы для запуска
            //exe.StartInfo.Arguments = path;         //Аргументы
            exe.Start();        // Запускаем внешний процесс
            //exe.WaitForExit();// Останавливаем наш процесс до закрытия блокнота
            exe.Close();        // Освобождаем связанные с процессом ресурсы
        }
    
        // Посмотреть через блокнот результаты 
        private void btnShowFile_Click(object sender, EventArgs e)
        {
            // Покажем выбранный файл через блокнот
            System.Diagnostics.Process exe = new System.Diagnostics.Process();
            exe.StartInfo.FileName = "Notepad.exe"; //Имя программы для запуска
            exe.StartInfo.Arguments = SelectFile(); //Выбрать файл через диалог
            exe.Start();        // Запускаем внешний процесс
            //exe.WaitForExit();// Останавливаем наш процесс до закрытия блокнота
            exe.Close();        // Освобождаем связанные с процессом ресурсы
        }
    
        // Подписать документ
        private void btnSigned_Click(object sender, EventArgs e)
        {
            if (txtKey.Text == "")
            {
                MessageBox.Show(this, "Введите ключ для хеширования", "Ошибка",
                    MessageBoxButtons.OK, MessageBoxIcon.Stop);
                return;
            }
    
            string destinationFile = "";
            if (Path.GetExtension(txtSourceFile.Text) != ".txt")
            {
                MessageBox.Show(this, "Выберите файл '*.txt' для хеширования", "Ошибка",
                    MessageBoxButtons.OK, MessageBoxIcon.Stop);
                return;
            }
            else
            {
                destinationFile = txtSourceFile.Text.Replace(".txt", String.Empty) + ".sign";
                destinationFile = Path.GetFileName(destinationFile);// Укороченное имя
                destinationFile = Path.Combine(txtDestinationDir.Text, destinationFile);
            }
    
            if (signedData(txtSourceFile.Text, destinationFile, txtKey.Text))
                MessageBox.Show(this, "Выполнено!", "Подписание файла",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            else
                MessageBox.Show(this, "Процесс подписания закончился неудачей!", "Ошибка",
                    MessageBoxButtons.OK, MessageBoxIcon.Stop);
        }
    
        // Выполнить аутентификацию документа
        private void btnChecked_Click(object sender, EventArgs e)
        {
            if (txtKey.Text == "")
            {
                MessageBox.Show(this, "Введите ключ для аутентификации", "Ошибка",
                    MessageBoxButtons.OK, MessageBoxIcon.Stop);
                return;
            }
    
            string destinationFile = "";
            if (Path.GetExtension(txtSourceFile.Text) != ".sign")
            {
                MessageBox.Show(this, "Выберите файл '*.sign' для аутентификации", "Ошибка",
                    MessageBoxButtons.OK, MessageBoxIcon.Stop);
                return;
            }
            else
            {
                destinationFile = txtSourceFile.Text + ".txt";
                destinationFile = Path.GetFileName(destinationFile);// Укороченное имя
                destinationFile = Path.Combine(txtDestinationDir.Text, destinationFile);
            }
    
            if (checkedData(txtSourceFile.Text, destinationFile, txtKey.Text))
                MessageBox.Show(this, "Выполнено!", "Аутентификация файла",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            else
                MessageBox.Show(this, "Процесс аутентификации закончился неудачей!", "Ошибка",
                    MessageBoxButtons.OK, MessageBoxIcon.Stop);
        }
    
        // Подписываем заданный файл
        private bool signedData(
            string sourceFile, string destinationFile, string cryptoKey)
        {
            FileStream inFileStream = null, outFileStream = null;
    
            // Создаем заново, иначе барахлит
            switch (cmbHMAC.SelectedIndex)
            {
                case 0:
                    hmac = new HMACSHA1();
                    break;
                case 1:
                    hmac = new MACTripleDES();
                    break;
                case 2:
                    hmac = new HMACMD5();
                    break;
                case 3:
                    hmac = new HMACRIPEMD160();
                    break;
                case 4:
                    hmac = new HMACSHA256();
                    break;
                case 5:
                    hmac = new HMACSHA384();
                    break;
                case 6:
                    hmac = new HMACSHA512();
                    break;
            }
    
            try
            {
                // Настраиваем алгоритм хеширования
                byte[] key = new byte[hmac.Key.Length];// Заготавливаем требуемый размер ключа
                ASCIIEncoding.ASCII.GetBytes(cryptoKey.Trim()).CopyTo(key, 0);// Заполняем ключ
                hmac.Key = key;
    
                // Создаем оболочку CryptoStream для хеширования 'в никуда'
                CryptoStream cryptoStream = new CryptoStream(Stream.Null, hmac, CryptoStreamMode.Write);
    
                // Открываем исходный файл, используя файловый поток
                inFileStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read);
                // Объявляем массив байтов с длиной входного файла 
                byte[] bytes = new byte[inFileStream.Length];
    
                // Считываем входной файловый поток в массив байтов и записываем 
                // байты в CryptoStream, чтобы получить хеш исходного документа
                inFileStream.Read(bytes, 0, bytes.Length);
                cryptoStream.Write(bytes, 0, bytes.Length);
                cryptoStream.Close();
    
                // Извлекаем хеш и записываем все в выходной документ
                outFileStream = new FileStream(destinationFile, FileMode.Create, FileAccess.Write);
                BinaryWriter bw = new BinaryWriter(outFileStream);
                bw.Write(hmac.Hash.Length);// Пишем длину хеша
                outFileStream.Write(hmac.Hash, 0, hmac.Hash.Length);// Пишем сам хеш
                inFileStream.Position = 0;// Указатель в начало
                inFileStream.Read(bytes, 0, bytes.Length); // Читаем исходный файл
                outFileStream.Write(bytes, 0, bytes.Length); // Пишем сам документ
    
                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(this, e.ToString(), "Hashed Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Stop);
    
                return false;
            }
            finally
            {
                // Освобождаем файловые ресурсы в любом случае
                if (inFileStream != null) inFileStream.Close();
                if (outFileStream != null) outFileStream.Close();
            }
        }
    
        // Хешируем указанный файл с тем же ключем и алгоритмом
        private bool checkedData(
            string sourceFile, string destinationFile, string cryptoKey)
        {
            FileStream inFileStream = null, outFileStream = null;
    
            // Создаем заново, иначе барахлит
            switch (cmbHMAC.SelectedIndex)
            {
                case 0:
                    hmac = new HMACSHA1();
                    break;
                case 1:
                    hmac = new MACTripleDES();
                    break;
                case 2:
                    hmac = new HMACMD5();
                    break;
                case 3:
                    hmac = new HMACRIPEMD160();
                    break;
                case 4:
                    hmac = new HMACSHA256();
                    break;
                case 5:
                    hmac = new HMACSHA384();
                    break;
                case 6:
                    hmac = new HMACSHA512();
                    break;
            }
    
            try
            {
                // Настраиваем алгоритм хеширования
                byte[] key = new byte[hmac.Key.Length];// Заготавливаем требуемый размер ключа
                ASCIIEncoding.ASCII.GetBytes(cryptoKey.Trim()).CopyTo(key, 0);// Заполняем ключ
                hmac.Key = key;
    
                // Создаем оболочку CryptoStream для хеширования 'в никуда'
                CryptoStream cryptoStream = new CryptoStream(Stream.Null, hmac, CryptoStreamMode.Write);
    
                // Открываем исходный файл и извлекаем хеш
                inFileStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read);
                BinaryReader br = new BinaryReader(inFileStream);// Вспомогательная оболочка
                int hashLength = br.ReadInt32();// Читаем длину хеша
                byte[] receivedHash = new byte[hashLength];// Место под хеш
                inFileStream.Read(receivedHash, 0, receivedHash.Length);// Извлекаем хеш
                long posBeginDoc = inFileStream.Position;// Начало документа
    
                // Объявляем массив байтов тела документа
                byte[] bytes = new byte[inFileStream.Length - posBeginDoc];
    
                // Дочитываем документ в массив байтов и записываем байты 
                // в CryptoStream, чтобы получить хеш исходного документа
                inFileStream.Read(bytes, 0, bytes.Length);
                cryptoStream.Write(bytes, 0, bytes.Length);
                cryptoStream.Close();
    
                // Извлекаем хеш и сравниваем с присланным
                // Преобразование ASCIIEncoding.ASCII.GetString() сбоит!
                String strCurrentHash = Encoding.Unicode.GetString(hmac.Hash);// byte[] -> string
                String strReceivedHash = Encoding.Unicode.GetString(receivedHash);// Присланный хеш
                if (strCurrentHash.CompareTo(strReceivedHash) != 0)
                    MessageBox.Show("Документ фальсифицирован!");
                else
                {
                    inFileStream.Position = posBeginDoc;
                    inFileStream.Read(bytes, 0, bytes.Length);
                    outFileStream = new FileStream(destinationFile, FileMode.Create, FileAccess.Write);
                    outFileStream.Write(bytes, 0, bytes.Length);
                    outFileStream.Flush();
                    MessageBox.Show("Документ подлинный и очищен от хеша!");
                }
    
                return true;
            }
            catch (Exception e)
            {
                MessageBox.Show(this, e.ToString(), "Checked Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Stop);
    
                return false;
            }
            finally
            {
                // Освобождаем файловые ресурсы в любом случае
                if (inFileStream != null) inFileStream.Close();
                if (outFileStream != null) outFileStream.Close();
            }
        }
    
        // Диалог выбора файла для обработки
        OpenFileDialog openFileDialog = new OpenFileDialog();
        String SelectFile()
        {
            // Настраиваем диалог выбора файла
            if (txtSourceFile.Text == String.Empty)
                openFileDialog.InitialDirectory = txtDestinationDir.Text;
            else
                openFileDialog.InitialDirectory = Path.GetDirectoryName(txtSourceFile.Text);
    
            openFileDialog.FileName = "";
            openFileDialog.Filter = "Source Files(*.txt;*.sign)|*.txt;*.sign";
            DialogResult result = openFileDialog.ShowDialog();
            if (result != DialogResult.Cancel)
                return openFileDialog.FileName; // Полное имя
            else
                return txtSourceFile.Text;
        }
    
        // Запуск диалога выбора файла
        private void btnSelectFile_Click(object sender, EventArgs e)
        {
            txtSourceFile.Text = SelectFile();
            txtSourceFile.Focus();// Без этого не сохранится в установках приложения
        }
    
        // Запуск диалога выбора папки назначения
        FolderBrowserDialog dialogFolder = new FolderBrowserDialog();
        private void btnDestinationDir_Click(object sender, EventArgs e)
        {
            if (txtDestinationDir.Text == String.Empty ||
                Directory.Exists(txtDestinationDir.Text) == false)
            {
                dialogFolder.RootFolder =
                    System.Environment.SpecialFolder.MyComputer;
                dialogFolder.SelectedPath = "";
                txtDestinationDir.Text = String.Empty;
            }
            else
            {
                dialogFolder.SelectedPath = txtDestinationDir.Text;
            }
    
            dialogFolder.Description =
                "Выберите место размещения целевого файла";
    
            dialogFolder.ShowDialog();
            txtDestinationDir.Text = dialogFolder.SelectedPath;
            txtDestinationDir.Focus();
        }
    
        // Блокировка редактирования TextBox вручную
        private void EditKeyDown(object sender, KeyEventArgs e)
        {
            e.Handled = true;
        }
        private void EditKeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled = true;
        }
    
        // При закрытии формы сохраняем параметры
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            settings.Save();
        }
    
        // Закрываем форму
        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}

Здесь мы применили двоичные потоки BinaryReader и BinaryWriter вместо текстовых StreamReader и StreamWriter, поскольку последние оставляют в документе невидимые метки и меняют хеш (пачкают). Кодировщики Unicode тоже точнее преобразуют хеш, который может содержать отличные от ASCII символы.

  • Добавьте к текущему проекту командой Project/Add Class новый файл с именем MySettings.cs и заполните его следующим кодом (приводится полностью)
using System;
using System.Configuration;
    
namespace Demo3
{
    // Класс для сохранения параметров приложения
    class MySettings : ApplicationSettingsBase
    {
        [UserScopedSettingAttribute()]       // Область действия - 'Пользователь' 
        [DefaultSettingValueAttribute("C:\\")]   // Значение параметра по умолчанию
        public String DestinationDir
        {
            get
            {
                return ((String)this["DestinationDir"]);
            }
            set
            {
                this["DestinationDir"] = (String)value;
            }
        }
    
        [UserScopedSettingAttribute()]       // Область действия - 'Пользователь' 
        [DefaultSettingValueAttribute("")]   // Значение параметра по умолчанию
        public String SourceFile
        {
            get
            {
                return ((String)this["SourceFile"]);
            }
            set
            {
                this["SourceFile"] = (String)value;
            }
        }
    }
}
  • Запустите приложение Demo3 - оно вполне работоспособно, подписывает документы и проводит их аутентификацию
  • Разберитесь с кодом ( кому надо!), да пусть еще больше простят меня классики

Внешний вид окна будет таким


Естественно, что при прямой и обратной обработке одного и того же документа алгоритм и ключ должны быть одинаковыми.

Дальше пока сами... (опять по шпалам!)


< Лекция 5 || Лекция 6: 12345678910111213
Алексей Бабушкин
Алексей Бабушкин

При выполнении в лабораторной работе упражнения №1 , а именно при выполнении нижеследующего кода:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using Microsoft.Xna.Framework.Graphics;

   

namespace Application1

{

    public partial class MainForm : Form

    {

        // Объявим поле графического устройства для видимости в методах

        GraphicsDevice device;

   

        public MainForm()

        {

            InitializeComponent();

   

            // Подпишемся на событие Load формы

            this.Load += new EventHandler(MainForm_Load);

   

            // Попишемся на событие FormClosed формы

            this.FormClosed += new FormClosedEventHandler(MainForm_FormClosed);

        }

   

        void MainForm_FormClosed(object sender, FormClosedEventArgs e)

        {

            //  Удаляем (освобождаем) устройство

            device.Dispose();

            // На всякий случай присваиваем ссылке на устройство значение null

            device = null;       

        }

   

        void MainForm_Load(object sender, EventArgs e)

        {

            // Создаем объект представления для настройки графического устройства

            PresentationParameters presentParams = new PresentationParameters();

            // Настраиваем объект представления через его свойства

            presentParams.IsFullScreen = false; // Включаем оконный режим

            presentParams.BackBufferCount = 1;  // Включаем задний буфер

                                                // для двойной буферизации

            // Переключение переднего и заднего буферов

            // должно осуществляться с максимальной эффективностью

            presentParams.SwapEffect = SwapEffect.Discard;

            // Устанавливаем размеры заднего буфера по клиентской области окна формы

            presentParams.BackBufferWidth = this.ClientSize.Width;

            presentParams.BackBufferHeight = this.ClientSize.Height;

   

            // Создадим графическое устройство с заданными настройками

            device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,

                this.Handle, presentParams);

        }

   

        protected override void OnPaint(PaintEventArgs e)

        {

            device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);

   

            base.OnPaint(e);

        }

    }

}

Выбрасывается исключение:

Невозможно загрузить файл или сборку "Microsoft.Xna.Framework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d" или один из зависимых от них компонентов. Не удается найти указанный файл.

Делаю все пунктуально. В чем может быть проблема?