Опубликован: 11.05.2007 | Доступ: свободный | Студентов: 1706 / 243 | Оценка: 4.36 / 4.25 | Длительность: 16:06:00
Дополнительный материал 3:

Приложение III. Симметричное шифрование

< Дополнительный материал 2 || Дополнительный материал 3

Приложение III. Симметричное шифрование

В теме, посвященной среде .NET Remoting, для шифрования передаваемых по каналу данных используется приведенный ниже класс симметричного шифрования. Он предоставляет интерфейс к стандартному классу FCL RijndaelManaged, реализующему алгоритм шифрования Рижндала. Используется версия алгоритма с генерацией случайного вектора инициализации, который передается вместе с зашифрованными данными. Основные методы класса - Encrypt и Decrypt реализуют соответственно шифровку и дешифровку содержимого входного потока и запись результата в выходной поток.

// Файл SevaSecurityCipher.cs
using System;
using System.IO;
using System.Security.Cryptography;

namespace Seva.Security.Encryption
{
    public class SymmetricEncryptor
    {
        public const int KeySize = 32;
        public const int BlockSize = 32;
        
        RijndaelManaged cipher = null;
        
        public byte[] Key
        {
            get { return cipher.Key;  }
            set { cipher.Key = value; }
        }

        public SymmetricEncryptor()
        {
            cipher = CreateCipher();
            
            cipher.GenerateKey();
        }

        public SymmetricEncryptor(byte[] key)
        {
            cipher = CreateCipher();

            cipher.Key = key;
        }
                
        public void SaveKey(string fileName)
        {
            using (FileStream file = new FileStream(fileName, 
                FileMode.Create, FileAccess.Write))
            {
                file.Write(Key, 0, Key.Length);
            }
        }    
    
        public void LoadKey(string fileName)
        {
            byte[] buffer = new byte[KeySize];
            using (FileStream file = new FileStream(fileName, 
                FileMode.Open, FileAccess.Read))
            {
                file.Read(buffer, 0, KeySize);
            }
            Key = buffer;
        }       

        public byte[] CreateEmptyIv()
        {
            return new byte[SymmetricEncryptor.BlockSize];                
        }
        
        public byte[] EncryptMessage(byte[] plainText, out byte[] iv)
        {
            cipher.GenerateIV();

            iv = cipher.IV;

            ICryptoTransform transform = cipher.CreateEncryptor();

            byte[] cipherText = transform.TransformFinalBlock(plainText, 
                0, plainText.Length);

            return cipherText;
        }

        public byte[] DecryptMessage(byte[] cipherText, byte[] iv)
        {
            cipher.IV = iv;

            ICryptoTransform transform = cipher.CreateDecryptor();

            byte[] plainText = transform.TransformFinalBlock(cipherText, 
                0, cipherText.Length);

            return plainText;
        }

        public void Encrypt(Stream input, Stream output)
        {
            byte[] iv = null;
            byte[] buffer = new byte[input.Length];                       
            
            input.Read(buffer, 0, buffer.Length);
                       
            buffer = EncryptMessage(buffer, out iv);
            //
            output.Write(iv, 0, iv.Length);
            output.Write(buffer, 0, buffer.Length);
        }
            
        public void Decrypt(Stream input, Stream output)
        {    
            byte[] iv = CreateEmptyIv();
            byte[] buffer = new byte[input.Length-iv.Length];
            
            input.Read(iv, 0, iv.Length);
            input.Read(buffer, 0, buffer.Length);
            //
            buffer = DecryptMessage(buffer, iv);
            output.Write(buffer, 0, buffer.Length);
        }    

        private RijndaelManaged CreateCipher()
        {
            RijndaelManaged cipher = new RijndaelManaged();

            cipher.KeySize   = KeySize * 8;
            cipher.BlockSize = BlockSize * 8;
            cipher.Mode      = CipherMode.CBC;
            cipher.Padding   = PaddingMode.PKCS7;

            return cipher;
        }
    }
}    
// SevaSecurityCipher.cs
Листинг III.1.

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

// Файл makekey.cs
using System;
using System.IO;
using Seva.Security.Encryption;

class MainApp
{
    public static void Main(string[] Args)
    {
        if (Args.Length != 1)
        {
            Console.WriteLine("usage: makekey <key_file>");
            return;
        }
        
        SymmetricEncryptor encryptor = new SymmetricEncryptor();
        encryptor.SaveKey(Args[0]);
    }
}        
// Файл makekey.cs

Ниже приведена строка компиляции для программы создания ключей.

csc MakeKey.cs SevaSecurityCipher.cs
< Дополнительный материал 2 || Дополнительный материал 3