Разработка распределенных приложений в Microsoft.NET Framework

         

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


cs using System; using


// Файл 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.
Закрыть окно




// Файл 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