Пошаговое руководство. Создание криптографического приложения
Обновлен: Ноябрь 2007
В этом пошаговом руководстве демонстрируются процедуры шифрования и расшифровки содержимого. Примеры кода предназначены для приложений Windows Forms. vboriCodeExamplesForWindowsFormsApplications На примере данного приложения не демонстрируются реальные сценарии, такие как использование смарт-карт. Здесь демонстрируются основные принципы шифрования и расшифровки данных.
В этом пошаговом руководстве выполняются следующие рекомендации по шифрованию.
Используется класс RijndaelManaged, симметричный алгоритм, для шифрования и расшифровки данных с использованием автоматически генерируемых объектов Key и IV.
Используется класс RSACryptoServiceProvider, асимметричный алгоритм, для шифрования и расшифровки ключа в данные, зашифрованные с помощью RijndaelManaged. Использование асимметричных алгоритмов наиболее целесообразно при небольших объемах данных, например при работе с ключами.
Примечание. Если необходимо защищать данные на компьютере, а не обмениваться зашифрованным содержимым с другими пользователями, следует использовать классы ProtectedData или ProtectedMemory.
В следующей таблице перечислены задачи шифрования, рассматриваемые в данном разделе.
Задача |
Описание |
---|---|
Создание приложения Windows Forms |
Перечисляются элементы управления, необходимые для запуска приложения. |
Объявление глобальных объектов |
Объявление строковых переменных пути, CspParameters и RSACryptoServiceProvider, получающих глобальный контекст класса Form. |
Создание асимметричного ключа |
Создается пара ключей, состоящая из асимметричного открытого и закрытого ключа, которой присваивается имя контейнера ключа. |
Шифрование файла |
Вывод диалогового окна для выбора файла, подлежащего шифрованию, и шифрование файла. |
Расшифровка файла |
Вывод диалогового окна для выбора зашифрованного файла, подлежащего расшифровке, и расшифровка файла. |
Получение закрытого ключа |
Получение полной пары ключей с помощью имени контейнера ключа. |
Экспорт открытого ключа |
Сохранение ключа в XML-файл только с открытыми параметрами. |
Импорт открытого ключа |
Загрузка ключа из XML-файла в контейнер ключа. |
Тестирование приложения |
Перечень процедур для тестирования приложения. |
Обязательные компоненты
Для выполнения данного руководства необходимы следующие компоненты.
- Ссылки на пространства имен System.IO и System.Security.Cryptography.
Создание приложения Windows Forms
Большинство примеров кода в этом пошаговом руководстве представляют собой обработчики событий для кнопочных элементов управления. В следующей таблице приводится список элементов управления, необходимых для работы примера приложения, а также их имена, соответствующие примерам кода.
Элемент управления |
Имя |
Свойство Text (при необходимости) |
---|---|---|
buttonEncryptFile |
Encrypt File |
|
buttonDecryptFile |
Decrypt File |
|
buttonCreateAsmKeys |
Create Keys |
|
buttonExportPublicKey |
Export Public Key |
|
buttonImportPublicKey |
Import Public Key |
|
buttonGetPrivateKey |
Get Private Key |
|
label1 |
||
openFileDialog1 |
||
openFileDialog2 |
Чтобы создать обработчики событий для кнопок, дважды щелкните по ним в конструкторе Visual Studio.
Объявление глобальных объектов
Добавьте следующий код в конструктор формы. Отредактируйте строковые переменные среды и настроек.
' Declare CspParmeters and RsaCryptoServiceProvider
' objects with global scope of your Form class.
Dim cspp As CspParameters = New System.Security.Cryptography.CspParameters
Dim rsa As RSACryptoServiceProvider
' Path variables for source, encryption, and
' decryption folders. Must end with a backslash.
Dim EncrFolder As String = "c:\Encrypt\"
Dim DecrFolder As String = "c:\Decrypt\"
Dim SrcFolder As String = "c:\docs\"
' Public key file
Dim PubKeyFile As String = "c:\encrypt\rsaPublicKey.txt"
' Key container name for
' private/public key value pair.
Dim keyName As String = "Key01"
// Declare CspParmeters and RsaCryptoServiceProvider
// objects with global scope of your Form class.
CspParameters cspp = new CspParameters();
RSACryptoServiceProvider rsa;
// Path variables for source, encryption, and
// decryption folders. Must end with a backslash.
const string EncrFolder = @"c:\Encrypt\";
const string DecrFolder = @"c:\Decrypt\";
const string SrcFolder = @"c:\docs\";
// Public key file
const string PubKeyFile = @"c:\encrypt\rsaPublicKey.txt";
// Key container name for
// private/public key value pair.
const string keyName = "Key01";
Создание асимметричного ключа
При выполнении данной задачи создается асимметричный ключ, с помощью которого производится шифрование и расшифровка ключа RijndaelManaged. Этот ключ использовался для шифрования содержимого, и с его помощью на элементе управления типа "метка" отображается имя контейнера ключа.
Добавьте следующий код в качестве обработчика события Click кнопки Create Keys (buttonCreateAsmKeys_Click).
Private Sub buttonCreateAsmKeys_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonCreateAsmKeys.Click
' Stores a key pair in the key container.
cspp.KeyContainerName = keyName
rsa = New RSACryptoServiceProvider(cspp)
rsa.PersistKeyInCsp = True
If rsa.PublicOnly = True Then
Label1.Text = "Key: " + cspp.KeyContainerName + " - Public Only"
Else
Label1.Text = "Key: " + cspp.KeyContainerName + " - Full Key Pair"
End If
End Sub
private void buttonCreateAsmKeys_Click(object sender, System.EventArgs e)
{
// Stores a key pair in the key container.
cspp.KeyContainerName = keyName;
rsa = new RSACryptoServiceProvider(cspp);
rsa.PersistKeyInCsp = true;
if (rsa.PublicOnly == true)
label1.Text = "Key: " + cspp.KeyContainerName + " - Public Only";
else
label1.Text = "Key: " + cspp.KeyContainerName + " - Full Key Pair";
}
Шифрование файла
Для выполнения этой задачи используются два метода: обработчик события для кнопки Encrypt File (buttonEncryptFile_Click) и метод EncryptFile. Первый метод используется для вывода диалогового окна выбора файла и передачи имени файла второму методу, который выполняет шифрование.
Зашифрованное содержимое, ключ и вектор инициализации сохраняются в объект FileStream, называемый пакетом шифрования.
Метод EncryptFile выполняет следующие действия.
Создает симметричный алгоритм RijndaelManaged для шифрования содержимого.
Создает объект RSACryptoServiceProvider и устанавливает для шифрования ключа RijndaelManaged.
Использует объект CryptoStream для чтения и шифрования объекта FileStream исходного файла в виде байтовых блоков в объект назначения FileStream для зашифрованного файла.
Определяет длину зашифрованного ключа и вектора инициализации и создает байтовые массивы соответствующей длины.
Записывает ключ, вектор инициализации и значения их длин в пакет шифрования.
Пакетом шифрования используется следующий формат.
длина ключа, байты 0-3
длина вектора инициализации, байты 4-7
зашифрованный ключ
вектор инициализации
зашифрованный текст
Значения длины ключа и вектора инициализации могут использоваться для определения начальных точек и длин всех частей пакета шифрования, которые затем могут использоваться при расшифровке файла.
Добавьте следующий код в качестве обработчика события Click кнопки Encrypt File (buttonEncryptFile_Click).
Private Sub buttonEncryptFile_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonEncryptFile.Click
If rsa Is Nothing Then
MsgBox("Key not set.")
Else
' Display a dialog box to select a file to encrypt.
OpenFileDialog1.InitialDirectory = SrcFolder
If OpenFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
Try
Dim fName As String = OpenFileDialog1.FileName
If (Not (fName) Is Nothing) Then
Dim fInfo As FileInfo = New FileInfo(fName)
' Use just the file name without path.
Dim name As String = fInfo.Name
EncryptFile(name)
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End If
End If
End Sub
private void buttonEncryptFile_Click(object sender, System.EventArgs e)
{
if (rsa == null)
MessageBox.Show("Key not set.");
else
{
// Display a dialog box to select a file to encrypt.
openFileDialog1.InitialDirectory = SrcFolder;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
string fName = openFileDialog1.FileName;
if (fName != null)
{
FileInfo fInfo = new FileInfo(fName);
// Pass the file name without the path.
string name = fInfo.Name;
EncryptFile(name);
}
}
}
}
Добавьте следующий метод EncryptFile в форму.
Private Sub EncryptFile(ByVal inFile As String)
' Create instance of Rijndael for
' symetric encryption of the data.
Dim rjndl As RijndaelManaged = New RijndaelManaged
rjndl.KeySize = 256
rjndl.BlockSize = 256
rjndl.Mode = CipherMode.CBC
Dim transform As ICryptoTransform = rjndl.CreateEncryptor
' Use RSACryptoServiceProvider to
' enrypt the Rijndael key.
Dim keyEncrypted() As Byte = rsa.Encrypt(rjndl.Key, False)
' Create byte arrays to contain
' the length values of the key and IV.
Dim LenK() As Byte = New Byte((4) - 1) {}
Dim LenIV() As Byte = New Byte((4) - 1) {}
Dim lKey As Integer = keyEncrypted.Length
LenK = BitConverter.GetBytes(lKey)
Dim lIV As Integer = rjndl.IV.Length
LenIV = BitConverter.GetBytes(lIV)
' Write the following to the FileStream
' for the encrypted file (outFs):
' - length of the key
' - length of the IV
' - ecrypted key
' - the IV
' - the encrypted cipher content
' Change the file's extension to ".enc"
Dim outFile As String = (EncrFolder _
+ (inFile.Substring(0, inFile.LastIndexOf(".")) + ".enc"))
Using outFs As FileStream = New FileStream(outFile, FileMode.Create)
outFs.Write(LenK, 0, 4)
outFs.Write(LenIV, 0, 4)
outFs.Write(keyEncrypted, 0, lKey)
outFs.Write(rjndl.IV, 0, lIV)
' Now write the cipher text using
' a CryptoStream for encrypting.
Using outStreamEncrypted As CryptoStream = New CryptoStream(outFs, transform, CryptoStreamMode.Write)
' By encrypting a chunk at
' a time, you can save memory
' and accommodate large files.
Dim count As Integer = 0
Dim offset As Integer = 0
' blockSizeBytes can be any arbitrary size.
Dim blockSizeBytes As Integer = (rjndl.BlockSize / 8)
Dim data() As Byte = New Byte((blockSizeBytes) - 1) {}
Dim bytesRead As Integer = 0
Using inFs As FileStream = New FileStream(inFile, FileMode.Open)
Do
count = inFs.Read(data, 0, blockSizeBytes)
offset = (offset + count)
outStreamEncrypted.Write(data, 0, count)
bytesRead = (bytesRead + blockSizeBytes)
Loop Until (count = 0)
outStreamEncrypted.FlushFinalBlock()
inFs.Close()
End Using
outStreamEncrypted.Close()
End Using
outFs.Close()
End Using
End Sub
private void EncryptFile(string inFile)
{
// Create instance of Rijndael for
// symetric encryption of the data.
RijndaelManaged rjndl = new RijndaelManaged();
rjndl.KeySize = 256;
rjndl.BlockSize = 256;
rjndl.Mode = CipherMode.CBC;
ICryptoTransform transform = rjndl.CreateEncryptor();
// Use RSACryptoServiceProvider to
// enrypt the Rijndael key.
byte[] keyEncrypted = rsa.Encrypt(rjndl.Key, false);
// Create byte arrays to contain
// the length values of the key and IV.
byte[] LenK = new byte[4];
byte[] LenIV = new byte[4];
int lKey = keyEncrypted.Length;
LenK = BitConverter.GetBytes(lKey);
int lIV = rjndl.IV.Length;
LenIV = BitConverter.GetBytes(lIV);
// Write the following to the FileStream
// for the encrypted file (outFs):
// - length of the key
// - length of the IV
// - ecrypted key
// - the IV
// - the encrypted cipher content
// Change the file's extension to ".enc"
string outFile = EncrFolder + inFile.Substring(0, inFile.LastIndexOf(".")) + ".enc";
using (FileStream outFs = new FileStream(outFile, FileMode.Create))
{
outFs.Write(LenK, 0, 4);
outFs.Write(LenIV, 0, 4);
outFs.Write(keyEncrypted, 0, lKey);
outFs.Write(rjndl.IV, 0, lIV);
// Now write the cipher text using
// a CryptoStream for encrypting.
using (CryptoStream outStreamEncrypted = new CryptoStream(outFs, transform, CryptoStreamMode.Write))
{
// By encrypting a chunk at
// a time, you can save memory
// and accommodate large files.
int count = 0;
int offset = 0;
// blockSizeBytes can be any arbitrary size.
int blockSizeBytes = rjndl.BlockSize / 8;
byte[] data = new byte[blockSizeBytes];
int bytesRead = 0;
using (FileStream inFs = new FileStream(inFile, FileMode.Open))
{
do
{
count = inFs.Read(data, 0, blockSizeBytes);
offset += count;
outStreamEncrypted.Write(data, 0, count);
bytesRead += blockSizeBytes;
}
while (count > 0);
inFs.Close();
}
outStreamEncrypted.FlushFinalBlock();
outStreamEncrypted.Close();
}
outFs.Close();
}
}
Расшифровка файла
Для выполнения этой задачи используются два метода: обработчик события для кнопки Decrypt File (buttonEncryptFile_Click) и метод DecryptFile. Первый метод используется для вывода диалогового окна выбора файла и передачи имени файла второму методу, который выполняет расшифровку.
Метод Decrypt выполняет следующие действия.
Создает симметричный алгоритм RijndaelManaged для расшифровки содержимого.
Считывает первые восемь байтов объекта FileStream зашифрованного пакета в байтовые массивы для получения значений длин зашифрованного ключа и вектора инициализации.
Извлекает ключ и вектор инициализации из пакета шифрования в байтовые массивы.
Создает объект RSACryptoServiceProvider и устанавливает для расшифровки ключа RijndaelManaged.
Использует объект CryptoStream для чтения и расшифровки зашифрованного текста пакета шифрования FileStream в виде байтовых блоков и загрузки их в объект FileStream для расшифрованного файла. По завершении этой операции расшифровка считается выполненной.
Добавьте следующий код в качестве обработчика события Click кнопки Decrypt File.
Private Sub buttonDecryptFile_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonDecryptFile.Click
If rsa Is Nothing Then
MsgBox("Key not set.")
Else
' Display a dialog box to select the encrypted file.
OpenFileDialog2.InitialDirectory = EncrFolder
If (OpenFileDialog2.ShowDialog = Windows.Forms.DialogResult.OK) Then
Try
Dim fName As String = OpenFileDialog2.FileName
If (Not (fName) Is Nothing) Then
Dim fi As FileInfo = New FileInfo(fName)
Dim name As String = fi.Name
DecryptFile(name)
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End If
End If
End Sub
private void buttonDecryptFile_Click(object sender, EventArgs e)
{
if (rsa == null)
MessageBox.Show("Key not set.");
else
{
// Display a dialog box to select the encrypted file.
openFileDialog2.InitialDirectory = EncrFolder;
if (openFileDialog2.ShowDialog() == DialogResult.OK)
{
string fName = openFileDialog2.FileName;
if (fName != null)
{
FileInfo fi = new FileInfo(fName);
string name = fi.Name;
DecryptFile(name);
}
}
}
}
Добавьте следующий метод DecryptFile в форму.
Private Sub DecryptFile(ByVal inFile As String)
' Create instance of Rijndael for
' symetric decryption of the data.
Dim rjndl As RijndaelManaged = New RijndaelManaged
rjndl.KeySize = 256
rjndl.BlockSize = 256
rjndl.Mode = CipherMode.CBC
' Create byte arrays to get the length of
' the encrypted key and IV.
' These values were stored as 4 bytes each
' at the beginning of the encrypted package.
Dim LenK() As Byte = New Byte(4 - 1) {}
Dim LenIV() As Byte = New Byte(4 - 1) {}
' Construct the file name for the decrypted file.
Dim outFile As String = (DecrFolder _
+ (inFile.Substring(0, inFile.LastIndexOf(".")) + ".txt"))
' Use FileStream objects to read the encrypted
' file (inFs) and save the decrypted file (outFs).
Using inFs As FileStream = New FileStream((EncrFolder + inFile), FileMode.Open)
inFs.Seek(0, SeekOrigin.Begin)
inFs.Read(LenK, 0, 3)
inFs.Seek(4, SeekOrigin.Begin)
inFs.Read(LenIV, 0, 3)
Dim lengthK As Integer = BitConverter.ToInt32(LenK, 0)
Dim lengthIV As Integer = BitConverter.ToInt32(LenIV, 0)
Dim startC As Integer = (lengthK + lengthIV + 8)
Dim lenC As Integer = (CType(inFs.Length, Integer) - startC)
Dim KeyEncrypted() As Byte = New Byte(lengthK - 1) {}
Dim IV() As Byte = New Byte(lengthIV - 1) {}
' Extract the key and IV
' starting from index 8
' after the length values.
inFs.Seek(8, SeekOrigin.Begin)
inFs.Read(KeyEncrypted, 0, lengthK)
inFs.Seek(8 + lengthK, SeekOrigin.Begin)
inFs.Read(IV, 0, lengthIV)
Dim KeyDecrypted() As Byte = rsa.Decrypt(KeyEncrypted, False)
' Decrypt the key.
Dim transform As ICryptoTransform = rjndl.CreateDecryptor(KeyDecrypted, IV)
' Decrypt the cipher text from
' from the FileSteam of the encrypted
' file (inFs) into the FileStream
' for the decrypted file (outFs).
Using outFs As FileStream = New FileStream(outFile, FileMode.Create)
Dim count As Integer = 0
Dim offset As Integer = 0
' blockSizeBytes can be any arbitrary size.
Dim blockSizeBytes As Integer = (rjndl.BlockSize / 8)
Dim data() As Byte = New Byte(blockSizeBytes - 1) {}
' By decrypting a chunk a time,
' you can save memory and
' accommodate large files.
' Start at the beginning
' of the cipher text.
inFs.Seek(startC, SeekOrigin.Begin)
Using outStreamDecrypted As CryptoStream = New CryptoStream(outFs, transform, CryptoStreamMode.Write)
Do
count = inFs.Read(data, 0, blockSizeBytes)
offset = (offset + count)
outStreamDecrypted.Write(data, 0, count)
Loop Until (count = 0)
outStreamDecrypted.FlushFinalBlock()
outStreamDecrypted.Close()
End Using
outFs.Close()
End Using
inFs.Close()
End Using
End Sub
private void DecryptFile(string inFile)
{
// Create instance of Rijndael for
// symetric decryption of the data.
RijndaelManaged rjndl = new RijndaelManaged();
rjndl.KeySize = 256;
rjndl.BlockSize = 256;
rjndl.Mode = CipherMode.CBC;
rjndl.Padding = PaddingMode.None;
// Create byte arrays to get the length of
// the encrypted key and IV.
// These values were stored as 4 bytes each
// at the beginning of the encrypted package.
byte[] LenK = new byte[4];
byte[] LenIV = new byte[4];
// Consruct the file name for the decrypted file.
string outFile = DecrFolder + inFile.Substring(0, inFile.LastIndexOf(".")) + ".txt";
// Use FileStream objects to read the encrypted
// file (inFs) and save the decrypted file (outFs).
using (FileStream inFs = new FileStream(EncrFolder + inFile, FileMode.Open))
{
inFs.Seek(0, SeekOrigin.Begin);
inFs.Seek(0, SeekOrigin.Begin);
inFs.Read(LenK, 0, 3);
inFs.Seek(4, SeekOrigin.Begin);
inFs.Read(LenIV, 0, 3);
// Convert the lengths to integer values.
int lenK = BitConverter.ToInt32(LenK, 0);
int lenIV = BitConverter.ToInt32(LenIV, 0);
// Determine the start postition of
// the ciphter text (startC)
// and its length(lenC).
int startC = lenK + lenIV + 8;
int lenC = (int)inFs.Length - startC;
// Create the byte arrays for
// the encrypted Rijndael key,
// the IV, and the cipher text.
byte[] KeyEncrypted = new byte[lenK];
byte[] IV = new byte[lenIV];
// Extract the key and IV
// starting from index 8
// after the length values.
inFs.Seek(8, SeekOrigin.Begin);
inFs.Read(KeyEncrypted, 0, lenK);
inFs.Seek(8 + lenK, SeekOrigin.Begin);
inFs.Read(IV, 0, lenIV);
// Use RSACryptoServiceProvider
// to decrypt the Rijndael key.
byte[] KeyDecrypted = rsa.Decrypt(KeyEncrypted, false);
// Decrypt the key.
ICryptoTransform transform = rjndl.CreateDecryptor(KeyDecrypted, IV);
// Decrypt the cipher text from
// from the FileSteam of the encrypted
// file (inFs) into the FileStream
// for the decrypted file (outFs).
using (FileStream outFs = new FileStream(outFile, FileMode.Create))
{
int count = 0;
int offset = 0;
// blockSizeBytes can be any arbitrary size.
int blockSizeBytes = rjndl.BlockSize / 8;
byte[] data = new byte[blockSizeBytes];
// By decrypting a chunk a time,
// you can save memory and
// accommodate large files.
// Start at the beginning
// of the cipher text.
inFs.Seek(startC, SeekOrigin.Begin);
using (CryptoStream outStreamDecrypted = new CryptoStream(outFs, transform, CryptoStreamMode.Write))
{
do
{
count = inFs.Read(data, 0, blockSizeBytes);
offset += count;
outStreamDecrypted.Write(data, 0, count);
}
while (count > 0);
outStreamDecrypted.FlushFinalBlock();
outStreamDecrypted.Close();
}
outFs.Close();
}
inFs.Close();
}
}
Экспорт открытого ключа
В рамках этой задачи ключ, созданный при нажатии кнопки Create Keys, сохраняется в файл. Экспортируются только открытые параметры.
Данная задача воссоздает ситуацию, в которой Алиса предоставляет Бобу открытый ключ, чтобы он мог зашифровывать для нее файлы. Боб и другие лица, имеющие открытый ключ, не смогут расшифровывать их, поскольку они не имеют полной пары ключей с закрытыми параметрами.
Добавьте следующий код в качестве обработчика события Click кнопки Export Public Key (buttonExportPublicKey_Click).
Private Sub buttonExportPublicKey_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonExportPublicKey.Click
' Save the public key created by the RSA
' to a file. Caution, persisting the
' key to a file is a security risk.
Dim sw As StreamWriter = New StreamWriter(PubKeyFile)
sw.Write(rsa.ToXmlString(False))
sw.Close()
End Sub
void buttonExportPublicKey_Click(object sender, System.EventArgs e)
{
// Save the public key created by the RSA
// to a file. Caution, persisting the
// key to a file is a security risk.
StreamWriter sw = new StreamWriter(PubKeyFile);
sw.Write(rsa.ToXmlString(false));
sw.Close();
}
Импорт открытого ключа
В рамках данной задачи производится загрузка ключа, имеющего только открытые параметры, который затем устанавливается в качестве имени контейнера ключа. Этот ключ создается при нажатии кнопки Export Public Key.
Данная задача воссоздает ситуацию, в которой Боб загружает ключ Алисы, имеющий только открытые параметры, чтобы зашифровывать для нее файлы.
Добавьте следующий код в качестве обработчика события Click кнопки Import Public Key (buttonImportPublicKey_Click).
Private Sub buttonImportPublicKey_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonImportPublicKey.Click
Dim sr As StreamReader = New StreamReader(PubKeyFile)
cspp.KeyContainerName = keyName
rsa = New RSACryptoServiceProvider(cspp)
Dim keytxt As String = sr.ReadToEnd
rsa.FromXmlString(keytxt)
rsa.PersistKeyInCsp = True
If rsa.PublicOnly = True Then
Label1.Text = "Key: " + cspp.KeyContainerName + " - Public Only"
Else
Label1.Text = "Key: " + cspp.KeyContainerName + " - Full Key Pair"
End If
sr.Close()
End Sub
void buttonImportPublicKey_Click(object sender, System.EventArgs e)
{
StreamReader sr = new StreamReader(PubKeyFile);
cspp.KeyContainerName = keyName;
rsa = new RSACryptoServiceProvider(cspp);
string keytxt = sr.ReadToEnd();
rsa.FromXmlString(keytxt);
rsa.PersistKeyInCsp = true;
if (rsa.PublicOnly == true)
label1.Text = "Key: " + cspp.KeyContainerName + " - Public Only";
else
label1.Text = "Key: " + cspp.KeyContainerName + " - Full Key Pair";
sr.Close();
}
Получение закрытого ключа
В рамках этой задачи контейнеру ключа присваивается имя, соответствующее имени ключа, созданного при нажатии кнопки Create Keys. Контейнер ключа будет содержать полную пару ключей с закрытыми параметрами.
Данная задача воссоздает ситуацию, в которой Алиса использует свой закрытый ключ для расшифровки файлов, зашифрованных Бобом.
Добавьте следующий код в качестве обработчика события Click кнопки Get Private Key (buttonGetPrivateKey_Click).
Private Sub buttonGetPrivateKey_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles buttonGetPrivateKey.Click
cspp.KeyContainerName = keyName
rsa = New RSACryptoServiceProvider(cspp)
rsa.PersistKeyInCsp = True
If rsa.PublicOnly = True Then
Label1.Text = "Key: " + cspp.KeyContainerName + " - Public Only"
Else
Label1.Text = "Key: " + cspp.KeyContainerName + " - Full Key Pair"
End If
End Sub
private void buttonGetPrivateKey_Click(object sender, EventArgs e)
{
cspp.KeyContainerName = keyName;
rsa = new RSACryptoServiceProvider(cspp);
rsa.PersistKeyInCsp = true;
if (rsa.PublicOnly == true)
label1.Text = "Key: " + cspp.KeyContainerName + " - Public Only";
else
label1.Text = "Key: " + cspp.KeyContainerName + " - Full Key Pair";
}
Тестирование приложения
После сборки приложения проведите следующие сценарии тестирования.
Создание ключей, шифрование и расшифровка
Нажмите кнопку Create Keys. В метке отобразится имя ключа и будет указано, является ли он полной парой ключей.
Нажмите кнопку Export Public Key. Обратите внимание, что при экспорте параметров открытого ключа текущий ключ не меняется.
Нажмите кнопку Encrypt File и выберите файл.
Нажмите кнопку Decrypt Fileи выберите последний зашифрованный файл.
Проверьте содержимое расшифрованного файла.
Закройте и перезапустите приложение, чтобы протестировать извлечение сохраненных контейнеров ключей в следующем сценарии.
Шифрование с открытым ключом
Нажмите кнопку Import Public Key. В метке отобразится имя ключа и будет указано, является ли он исключительно открытым.
Нажмите кнопку Encrypt File и выберите файл.
Нажмите кнопку Decrypt Fileи выберите последний зашифрованный файл. Эта операция должна завершиться ошибкой, так как необходим закрытый ключ для расшифровки.
В этом сценарии демонстрируется ситуация, когда для шифрования файла, передаваемого другому лицу, имеется только открытый ключ. Обычно для шифрования предоставляется только открытый ключ, а закрытый ключ используется для расшифровки.
Расшифровка при помощи закрытого ключа
Нажмите кнопку Get Private Key. В метке отобразится имя ключа и будет указано, является ли он полной парой ключей.
Нажмите кнопку Decrypt File и выберите последний зашифрованный файл. Эта операция должна завершиться успешно, так как имеется полная пара ключей для расшифровки.