Методические указания по дисциплине Информационная безопасность
.pdfDim transform As ICryptoTransform = DES.CreateEncryptor()
Dim cs As New CryptoStream(fs, transform, CryptoStreamMode.Write) Dim w As New StreamWriter(cs)
w.Write(text)
w.Flush()
' Очистка буфера памяти и закрытие файла cs.FlushFinalBlock()
w.Close()
fs.Close()
Visual C#:
string text; text=textBox1.Text;
// Открытие зашифрованного файла для записи
FileStream fs = new FileStream("C:\\Шифр примера 2.txt", FileMode.Create);
//Создание нового симметричного ключа для шифрования по алгоритму DES
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
//Шифрование симметричного ключа и вектора инициализации
//с помощью открытого ключа RSA
byte[] EncrypKey=RSA.Encrypt(DES.Key,false); byte[] EncrypIV=RSA.Encrypt(DES.IV,false);
// Запись асимметрично зашифрованных ключа и вектора инициализации // в файл
fs.Write(EncrypKey, 0, EncrypKey.Length); fs.Write(EncrypIV, 0, EncrypIV.Length);
// Шифрование информации с помощью алгоритма DES и запись ее в файл
ICryptoTransform transform = DES.CreateEncryptor(); CryptoStream cs = new CryptoStream(fs, transform,
CryptoStreamMode.Write);
StreamWriter w = new StreamWriter(cs); w.Write(text);
w.Flush();
// Очистка буфера памяти и закрытие файла cs.FlushFinalBlock();
w.Close();
fs.Close();
Пример 4. Прочитать и отобразить в элементе управления RichTextBox зашифрованную информацию из примера 3:
Visual Basic .Net:
' Открытие зашифрованного файла для чтения
Dim fs As New FileStream("C:\Шифр примера 2.txt", FileMode.Open)
'Можно прочитать весь файл сразу, все равно все будет зашифровано
'для этого нужно пропустить все строки отсюда до указанного места
'вычисление числа байт в зашифрованном блоке,
'которое равно размеру ключа
Dim KeyBlockSize As Integer = CType(RSA.KeySize / 8, Integer)
'Получение зашифрованного симметричного ключа и
'вектора инициализации
Dim DES As New DESCryptoServiceProvider
Dim EncrypKey(KeyBlockSize - 1) As Byte
11
Dim EncrypIV(KeyBlockSize - 1) As Byte fs.Read(EncrypKey, 0, EncrypKey.Length) fs.Read(EncrypIV, 0, EncrypIV.Length)
' Для чтения всего файла сразу пропустить строки досюда
Dim r As New StreamReader(fs) RichTextBox1.Text = r.ReadToEnd r.Close()
fs.Close()
Visual C#:
// Открытие зашифрованного файла для чтения
FileStream fs = new FileStream("C:\\Шифр примера 2.txt", FileMode.Open);
//Можно прочитать весь файл сразу, все равно всё будет зашифровано
//для этого нужно пропустить все строки отсюда до указанного места
//вычисление числа байт в зашифрованном блоке,
//которое равно размеру ключа
Int32 KeyBlockSize = System.Convert.ToInt32(RSA.KeySize / 8);
//Получение зашифрованнного симметричного ключа и
//вектора инициализации
DESCryptoServiceProvider DES = new DESCryptoServiceProvider(); Byte[] EncrypKey = new Byte[KeyBlockSize];
Byte[] EncrypIV = new Byte[KeyBlockSize]; fs.Read(EncrypKey, 0, EncrypKey.Length); fs.Read(EncrypIV, 0, EncrypIV.Length);2
// Для чтения всего файла сразу необходимо пропустить строки досюда
StreamReader r = new StreamReader(fs); richTextBox1.Text = r.ReadToEnd(); r.Close();
fs.Close();
Пример 5. Прочесть и расшифровать информацию из файла, в котором содержится зашифрованный ключ симметричного шифрования по алгоритму DES и зашифрованная этим ключом информация:
Visual Basic .Net:
' Открытие зашифрованного файла для чтения
Dim fs As New FileStream("C:\Шифр примера 2.txt", FileMode.Open)
'Вычисление числа байт в зашифровнном блоке,
'которое равно размеру ключа
Dim KeyBlockSize As Integer = CType(RSA.KeySize / 8, Integer)
'Получение зашифрованного симметричного ключа и
'вектора инициализации
Dim DES As New DESCryptoServiceProvider Dim EncrypKey(KeyBlockSize - 1) As Byte Dim EncrypIV(KeyBlockSize - 1) As Byte fs.Read(EncrypKey, 0, EncrypKey.Length) fs.Read(EncrypIV, 0, EncrypIV.Length)
2 Массивы EncryptKey и EncyptIV определены на VB. Net с размерностью KeyBlockSize-1, а на
C# .Net – с размерностью KeyBlockSize, т.к. на VB. Net индексы массивов изменяются от 0 до n, т.е. массив A(n) содержит n+1 элемент, а в C# .Net индексы массивов изменяются от 0 до n-1, т.е. массив A(n) содержит n элементов.
12
DES.KeySize = KeyBlockSize
DES.Key = RSA.Decrypt(EncrypKey, False)
DES.IV = RSA.Decrypt(EncrypIV, False)
' Чтение оставшейся части файла с помощью симметричного ключа
Dim transform As ICryptoTransform = DES.CreateDecryptor()
Dim cs As New CryptoStream(fs, transform, CryptoStreamMode.Read) Dim r As New StreamReader(cs)
RichTextBox2.Text = r.ReadToEnd() r.Close()
fs.Close()
Visual C#:
// Открытие зашифрованного файла для чтения
FileStream fs = new FileStream("C:\\Шифр примера 2.txt", FileMode.Open);
//Вычисление числа байт в зашифрованном блоке,
//которое равно размеру ключа
Int32 KeyBlockSize = System.Convert.ToInt32(RSA.KeySize / 8);
//Получение зашифрованного симметричного ключа и
//вектора инициализации
DESCryptoServiceProvider DES = new DESCryptoServiceProvider(); Byte[] EncrypKey = new Byte[KeyBlockSize];
Byte[] EncrypIV = new Byte[KeyBlockSize]; fs.Read(EncrypKey, 0, EncrypKey.Length); fs.Read(EncrypIV, 0, EncrypIV.Length); DES.KeySize = KeyBlockSize;
DES.Key = RSA.Decrypt(EncrypKey, false); DES.IV = RSA.Decrypt(EncrypIV, false);
// Чтение оставшейся части файла с помощью симметричного ключа
ICryptoTransform transform = DES.CreateDecryptor(); CryptoStream cs = new CryptoStream(fs, transform,
CryptoStreamMode.Read);
StreamReader r = new StreamReader(cs); richTextBox2.Text = r.ReadToEnd(); r.Close();
fs.Close();
13
Хеширование и генерация цифровых подписей средствами
Visual Studio .Net
Для генерации хэш-кодов сообщений в Visual Studio .Net также используются классы из пространства имѐн System.Security.Cryptography. Реализованы следующие алгоримты хеширования:
MD5 – реализован классом MD5CryptoServiceProvider (длина хэш-кода
–128 бит);
SHA-1 – реализован классом SHA1CryptoServiceProvider (длина хэшкода – 160 бит);
SHA-256 – реализован классом SHA256Managed (длина хэш-кода – 256 бит);
SHA-384 – реализован классом SHA384Managed (длина хэш-кода – 384 бит);
SHA-512 – реализован классом SHA512Managed (длина хэш-кода – 512 бит).
Все эти классы имеют метод ComputeHash, который принимает массив байт и возвращает другой массив байт, содержащий хэш-код необходимой длины.
Пример 1. Пусть некоторый текст записан в файле с именем «Пример 3.txt». Необходимо сгенерировать хэш-код для данного текста по алгоритму MD5:
Visual Basic .Net:
' Чтение и отображение информации из файла
Dim fs As New FileStream("C:\Пример 3.txt", FileMode.OpenOrCreate) Dim r As New StreamReader(fs)
RichTextBox1.Text = r.ReadToEnd
Dim MD5 As New MD5CryptoServiceProvider
'Возвращение к началу потока fs.Position = 0
'Вычисление 128-битного MD5 хэш-кода для файла
Dim hash1() As Byte = MD5.ComputeHash(fs) r.Close()
fs.Close()
Visual C#:
// Чтение и отображение информации из файла
FileStream fs = new FileStream("C:\\Пример 3.txt", FileMode.OpenOrCreate);
StreamReader r = new StreamReader(fs); richTextBox1.Text = r.ReadToEnd();
MD5CryptoServiceProvider MD5=new MD5CryptoServiceProvider();
//Возвращение к началу потока fs.Position=0;
//Вычисление 128-битного MD5 хэш-кода для файла
Byte[] hash1=MD5.ComputeHash(fs); r.Close();
fs.Close();
Методов сравнения хеш-кодов у данных классов нет. Поэтому для сравнения необходимо при получении сообщения создать новый хэш-код и сравнить его с полученным. Сравнение должно осуществляться побайтно, т.к. методов сравнения массивов в Visual Studio .Net также нет: необходимо писать специальную
14
программу. При этом сам хэш-код ничем не защищен, поэтому хеширование используется довольно редко.
Для решения этой проблемы используется шифрование хэш-кода, но непосредственное шифрование также не дает возможности сравнения хэш-кодов. Однако в Visual Studio .Net имеются специальные средства создания зашифрованных хэш-кодов с помощью алгоритма асимметричного шифрования RSA, т.е. средства создания цифровых подписей.
Для создания цифровой подписи RSA используется метод SignData класса
RSACryptoServiceProvider. Он имеет синтаксис:
Имя экземпляра класса.SignData(массив данных, алгоритм хеширования)
Массив данных имеет тип Byte, для преобразования текста в массив байт необходимо использовать специальные классы, например, класс GetBytes из пространства имен System.Text (данный класс реализован отдельно для каждой из кодировок текста). В качестве алгоритмов хеширования можно использовать только MD5 и SHA-1, необходимо создать экземпляр соответствующего класса.
Пример 2. Пусть некоторый текст записан в файле «Пример 3.txt», а информация о секретном ключе RSA содержится в файле «Key1.bin». Необходимо создать цифровую подпись RSA для данного текста и поместить еѐ в файл «Подпись.bin». В качестве алгоритма хеширования использовать SHA-1:
Visual Basic .Net:
Dim text As String
Dim signature() As Byte
'Открытие исходного файла и чтение из него информации в переменную text
Dim fs As New FileStream("C:\Пример3.txt", FileMode.Open) Dim r As New StreamReader(fs)
text = r.ReadToEnd() r.Close() fs.Close()
'Прочитать информацию о секретном ключе
Dim RSA As New RSACryptoServiceProvider()
fs = New FileStream("C:\key1.bin", FileMode.Open) r = New StreamReader(fs) RSA.FromXmlString(r.ReadToEnd())
fs.Close()
' Преобразование данных в поток бит
Dim databytes() As Byte = System.Text.Encoding.UTF8.GetBytes(text) ' Подписывание данных
signature = RSA.SignData(databytes, New SHA1CryptoServiceProvider) ' Запись подписи в файл
fs = New FileStream("C:\Подпись.bin", FileMode.OpenOrCreate) fs.Write(signature, 0, signature.Length)
fs.Close()
Visual C#:
String text; Byte[] signature;
// Открытие исходного файла и чтение из него информации в переменную text
FileStream fs = new FileStream("C:\\Пример 3.txt", FileMode.Open); StreamReader r = new StreamReader(fs);
15
text = r.ReadToEnd(); r.Close(); fs.Close();
// Прочитать информацию о секретном ключе
RSACryptoServiceProvider rsa=new RSACryptoServiceProvider(); fs = new FileStream("C:\\key1.bin", FileMode.Open);
r = new StreamReader(fs); rsa.FromXmlString(r.ReadToEnd()); fs.Close();
// Преобразование данных в поток бит
byte[] databytes = System.Text.Encoding.UTF8.GetBytes(text); // Подписывание данных
signature=rsa.SignData(databytes, new SHA1CryptoServiceProvider()); // Запись подписи в файл
fs=new FileStream("C:\\Подпись.bin",FileMode.OpenOrCreate); fs.Write(signature,0,signature.Length);
fs.Close();
Для верификации подписи используется метод VerifyData класса
RSACryptoServiceProvider. Он имеет синтаксис:
Имя экземпляра класса.VerifyData(массив данных,алгоритм хеширования,подпись).
В качестве массива данных передаѐтся тот же массив, который подписывался методом SignData, также задаѐтся и алгоритм шифрования. В качестве подписи передаѐтся массив байт, полученный на выходе метода
SignData.
Пример 3. Пусть некоторый текст записан в файле «Пример 3.txt», информация об открытом ключе RSA содержится в файле «Key2.bin», а подпись, созданная с помощью секретного ключа – в файле «Подпись.bin». Необходимо прочитать все эти данные и проверить истинность цифровой подписи:
Visual Basic .Net:
Dim text As String
Dim signature() As Byte
'открытие исходного файла и чтение из него информации в переменную text
Dim fs As New FileStream("C:\Пример3.txt", FileMode.Open) Dim r As New StreamReader(fs)
text = r.ReadToEnd() r.Close() fs.Close()
'прочитать информацию об открытом ключе
Dim rsa As New RSACryptoServiceProvider()
fs = New FileStream("C:\key2.bin", FileMode.Open) r = New StreamReader(fs) rsa.FromXmlString(r.ReadToEnd())
fs.Close()
' преобразование данных в поток бит
Dim databytes() As Byte = System.Text.Encoding.UTF8.GetBytes(text)
' прочитать информацию о подписи
fs = New FileStream("C:\Подпись.bin", FileMode.Open) fs.Read(signature, 0, signature.Length)
fs.Close()
' верификация подписи
16
If rsa.VerifyData(databytes, New SHA1CryptoServiceProvider, signature)
Then
Label2.Text = "Подпись верна"
Else
Label2.Text = "Подпись не верна"
End If
Visual C#:
String text;
Byte[] signature=new Byte[64];3
//Открытие исходного файла и чтение из него информации в переменную text
FileStream fs = new FileStream("C:\\Пример 3.txt", FileMode.Open); StreamReader r = new StreamReader(fs);
text = r.ReadToEnd(); r.Close(); fs.Close();
//Прочитать информацию об открытом ключе
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); fs = new FileStream("C:\\key2.bin", FileMode.Open);
r = new StreamReader(fs); rsa.FromXmlString(r.ReadToEnd()); fs.Close();
// Преобразование данных в поток бит
byte[] databytes = System.Text.Encoding.UTF8.GetBytes(text);
// Прочитать информацию о подписи
fs = new FileStream("C:\\Подпись.bin", FileMode.Open); fs.Read(signature, 0, signature.Length);
fs.Close();
// Верификация подписи
if (rsa.VerifyData(databytes, new SHA1CryptoServiceProvider(), signature))
{
label1.Text = "Подпись верна";
}
else
{
label1.Text ="Подпись не верна";
}
3 Поскольку на C# невозможно использовать переменные, которым не присвоено значение, то массив signature необходимо объявлять явно. Для метода хеширования SHA-1 длина массива подписи равна 64.
17
Асимметричное шифрование в SQL Server
SQL server поддерживает следующие алгоритмы асимметричного шифрования: DES, TripleDES, RC2, AES. Базовым алгоритмом шифрования является 3DES.
Различают шифрование при передаче данных и при хранении. Шифрование при передаче осуществляется автоматически. Для этого необходимо запустить SQL Server Configuration Manager, в контекстном меню пункта Protocols for SQLServer
выбрать пункт Properties и в диалоговом окне Protocol Properties во вкладке Flags установить значение Yes у пункта ForceEncryption.
Шифрование при хранении определяется пользователем. При установке SQL Server автоматически создаётся специальный симметричный ключ Service Master Key (SMK). Этот ключ представляет собой 128-битный ключ алгоритма TripleDES и предназначен для шифрования всех других ключей и секретов сервера. Для резервного копирования SMK необходимо выполнить запрос, например:
BACKUP SERVICE MASTER KEY TO FILE = 'key1' ENCRYPTION BY PASSWORD = '123';
Для восстановления SMK необходимо выполнить запрос, например:
RESTORE SERVICE MASTER KEY FROM FILE = 'key1' DECRYPTION BY PASSWORD = '123';
В случае компрометации SMK его можно сгенерировать заново с помощью запроса:
ALTER SERVICE MASTER KEY REGENERATE.
При генерации нового SMK автоматически заново зашифровываются все остальные созданные ключи и секреты сервера, такие, как пароли входа.
Для каждой базы можно создать главный ключ базы данных (Database Main Key –DMK), с помощью следующего запроса:
USE SALE1
CREATE MASTER KEY ENCRYPTION BY PASSWORD='1234'
Для удаления DMK базы необходимо выполнить запрос:
USE SALE
DROP MASTER KEY
Для DMK также можно выполнить резервное копирование в файл и восстановление из файла, например, с помощью запросов (предварительно его нужно открыть):
USE SALE1
OPEN MASTER KEY DECRYPTION BY PASSWORD='1234'
BACKUP MASTER KEY TO FILE = 'KEY3' ENCRYPTION BY PASSWORD = '567'
(пароль на запись ключа в файл может отличаться от пароля открытия ключа)
USE SALE1
RESTORE MASTER KEY
FROM FILE = 'key3'
DECRYPTION BY PASSWORD = '567'
ENCRYPTION BY PASSWORD = '1234';
18
(первый пароль – это пароль, с помощью которого создаѐтся и открывается DMK, второй пароль – это пароль, с помощью которого DMK был записан в файл).
При резервировании ключей перезапись файлов не производится, поэтому при попытке записать новый ключ (SMK или DMK) в уже существующий файл, выдаѐтся сообщение об ошибке. Поэтому необходимо физически удалять старые ключи из папок компьютера.
Создание DMK не обязательно. После создания DMK он шифруется с помощью SMK и с помощью пароля.
Для шифрования собственно данных используются симметричные ключи пользователей. Необходимо создать пользователя базы данных, схему, в которой он будет работать и дать ему соответствующие права. После этого администратор базы может создать симметричный ключ пользователя с помощью запроса, в котором определяется имя ключа, имя пользователя, которому принадлежит ключ, алгоритм шифрования и пароль, по которому пользователь может обращаться к этому ключу.
Пример 1. Пусть в базе Sale имеется пользователь Ерохин, работающий в схеме с именем Ерохин. Создать для этого пользователя симметричный ключ, осуществляющий шифрование по алгоритму DES. Присвоить ключу имя client_key1:
USE SALE
CREATE SYMMETRIC KEY CLIENT_KEY1
AUTHORIZATION Ерохин WITH ALGORITHM=DES
ENCRYPTION BY PASSWORD='123'
(в предложении Authorization указывается имя пользователя, а не имя схемы). Созданные ключи отображаются в папке \Security\Symmetric keys соответствующей базы, их можно удалить с помощью Management Studio.
Повторное создание ключа с одним и тем же именем без удаления невозможно, сначала требуется удалить старый ключ. Резервирование и восстановление симметричных ключей осуществляется с помощью программы
Reporting Services Configuration Manager.
Собственно шифрование и расшифровка данных могут быть осуществлены администратором или пользователем-владельцем ключа. Шифрованию подлежат только строковые данные, зашифрованные данные представляют собой набор бит, поэтому для хранения зашифрованных данных необходимо использовать тип
VarBinary.
Если в таблице имеется столбец, который нужно зашифровать (полностью или частично), то для этого необходимо создать дополнительный столбец соответствующего типа. Шифрование осуществляется после открытия ключа с использованием запроса типа Update. При этом будут видны и зашифрованные и открытые данные.
Пример 2. Пусть в базе Sale имеются сведения о номерах телефонов клиентов (поле Phone типа NVarChar(24)). Зашифровать эти данные с использованием созданного выше ключа. Для этого необходимо создать новый столбец, например, с именем CryptPhone и типом данных VarBinary(max). После этого необходимо выполнить запрос:
USE SALE1
OPEN SYMMETRIC KEY CLIENT_KEY DECRYPTION BY PASSWORD='123'
19
UPDATE CLIENT SET CRYPT_PHONE=ENCRYPTBYKEY(KEY_GUID('CLIENT_KEY'),PHONE) CLOSE ALL SYMMETRIC KEYS
(По окончании работы следует закрыть симметричный ключ, можно закрыть сразу все ключи).
Расшифровка данных осуществляется только для просмотра с помощью запроса типа Select.
Пример 3. Расшифровать информацию о телефонах клиентов с помощью созданного выше ключа и отобразить имена клиентов и их телефоны:
USE SALE1
OPEN SYMMETRIC KEY CLIENT_KEY DECRYPTION BY PASSWORD='123'
SELECT NAME_FIRM,CONVERT(NVARCHAR(24), DECRYPTBYKEY(CRYPT_PHONE)) AS PRONE FROM CLIENT
CLOSE SYMMETRIC KEY CLIENT_KEY
При простом просмотре таблицы будут видны оба столбца – Phone и Crypt_Phone. Для того чтобы были видны только зашифрованные данные, необходимо создать соответствующее представление или ограничить число столбцов в запросе. Однако в любом случае в базе хранятся и открытые и зашифрованные данные, поэтому при взломе базы открытые данные всѐ равно будут видны.
Для решения этой проблемы следует сразу помещать в базу зашифрованные данные. Для этого нужно создать соответствующие столбцы и помещать в них данные с помощью запроса Insert. В нашем случае, например, необходимо убрать столбец Phone, добавить столбец Crypt_phone типа Varbinary, а заполнение таблицы производить с помощью следующих операторов (пусть таблица содержит также столбец Name_Firm, являющийся открытым):
USE SALE1_NEW
OPEN SYMMETRIC KEY CLIENT_KEY DECRYPTION BY PASSWORD='123'
INSERT INTO CLIENT VALUES ('МТУСИ',
ENCRYPTBYKEY(KEY_GUID('CLIENT_KEY1'),'1927847')) CLOSE SYMMETRIC KEY CLIENT_KEY
Таким образом необходимо заполнять каждую запись таблицы. Это не самый удобный способ, однако он гарантирует, что даже при взломе базы данных секретные данные видны не будут.
Для просмотра информации о всех открытых ключах используется запрос:
SELECT * FROM SYS.OPENKEYS
При шифровании данных возникают вопросы, связанные с индексированием и поиском. Поскольку зашифрованные столбцы представляют собой поток битов, то эффективные способы индексирования отсутствуют. Единственным выходом является создание дополнительных незашифрованных столбцов, которые используются для индексирования.
Подписано в печать 24.06.2013г. Формат 60х90 1/16. Объем 1,3 усл.п.л. Тираж 75 экз. Изд. № 44. Заказ 118.
ООО «ТиРу». Москва, ул. Правды, д. 24, стр. 5.
20
