/// <summary> /// Асинхронный поток для дешифрования /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void backgroundDecrypter_DoWork(object sender, DoWorkEventArgs e) { // Принимаем bgWorker BackgroundWorker worker = sender as BackgroundWorker; // Принимаем пути всех файлов CrypterPack decryptPack = (CrypterPack)e.Argument; // Дешифруем файлы e.Result = DecryptFilesAES(decryptPack, worker, e); }
/// <summary> /// Дешифрование файлов /// </summary> /// <param name="decryptPack"></param> /// <param name="worker"></param> /// <param name="e"></param> /// <returns></returns> private object DecryptFilesAES(CrypterPack decryptPack, BackgroundWorker worker, DoWorkEventArgs e) { // Количество готовых файлов int countDoneDecrypt = 0; using (Aes aes = Aes.Create()) { aes.Key = FromHex(decryptPack.key); aes.IV = FromHex(decryptPack.iv); foreach (string filePath in decryptPack.paths) { // Проверяем не отменил ли пользователь операцию if (worker.CancellationPending) { e.Cancel = true; } else { try { // Дешифруем с помощью AES и ключей DecryptFileFromAES(filePath, aes.Key, aes.IV); } catch (Exception ex) { ex.HelpLink = filePath; worker.ReportProgress(highestPercentageReached, ex); continue; } countDoneDecrypt++; // Report progress as a percentage of the total task. int percentComplete = countDoneDecrypt * 100 / decryptPack.paths.Length; highestPercentageReached = percentComplete; worker.ReportProgress(percentComplete, filePath); } } } return(0); }
/// <summary> /// Кнопка расшифровать /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void buttonDecrypt_Click(object sender, EventArgs e) { // Если установлен флажок "Доп. защиты", то расшифроваем зашифрованный AES ключ с помощью доп. ключа RSA try { if (checkBoxTwoKeys.Checked) { using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048)) { rsa.FromXmlString(textBoxRsaKey.Text); textBoxKey.Text = BitConverter.ToString(rsa.Decrypt(FromHex(textBoxKey.Text), false)); } } } catch (Exception) { MessageBox.Show("Невозможно расшифровать основной ключ с помощью дополнительного.", "Неверные ключи.", MessageBoxButtons.OK); return; } // Считывание ключа string key = string.Empty; string iv = string.Empty; try { key = textBoxKey.Text.Substring(0, 95); iv = textBoxKey.Text.Substring(96, 47); } catch (Exception) { MessageBox.Show("Неверный ключ!", "Ошибка!", MessageBoxButtons.OK); return; } // Переносим все выбранные папки treeView в список var selectedFolders = GetAllFilesPathFrom(Descendants(treeView.Nodes) .Where(n => n.Checked && n.Tag != null) .Select(n => n.Tag.ToString()) .ToArray()).ToArray(); var listPaths = GetAllFilesPathFrom(GetAllItemsFrom(listViewFiles.Items) .Select(n => n.Text) .ToArray()).ToArray(); string[] allPaths = selectedFolders.Union(listPaths).ToArray(); listViewFiles.Clear(); // добавляем файлы в listView foreach (var path in allPaths) { listViewFiles.Items.Add(path.ToString()); } // Проверка элементов if (listViewFiles.Items.Count <= 0) { MessageBox.Show("Пожалуйста, выберите файлы для дешифрования", "Не выбраны файлы", MessageBoxButtons.OK); return; } // Убираем все подсветы UncolorItems(); // Начальные логи logBar.Text = "Logs: Decrypt started..."; progressBar.Value = 0; highestPercentageReached = 0; if (backgroundCrypter.IsBusy == false && backgroundDecrypter.IsBusy == false) { CrypterPack decryptPack = new CrypterPack(); decryptPack.key = key; decryptPack.iv = iv; decryptPack.paths = allPaths; backgroundDecrypter.RunWorkerAsync(decryptPack); CrypterStarted(true); } else { MessageBox.Show("Процесс уже запущен.", "Невозможно запустить второй раз", MessageBoxButtons.OK); } }
/// <summary> /// Обработчик для ReportProgress /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { logBar.Text = $"Crypt {e.ProgressPercentage.ToString()}%"; progressBar.Value = e.ProgressPercentage; if (e.UserState != null) { switch (e.UserState.GetType().Name) { case "CrypterPack": CrypterPack crypterPack = (CrypterPack)e.UserState; string tmp = crypterPack.key + "-" + crypterPack.iv; // Если установлен флажок доп защиты, шифруем ключ. if (checkBoxTwoKeys.Checked) { using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048)) { try { // Если ключ уже установлен, используем его if (textBoxRsaKey.Text.Length > 0) { rsa.FromXmlString(textBoxRsaKey.Text); textBoxKey.Text = BitConverter.ToString(rsa.Encrypt(FromHex(tmp), false)); } else { // Иначе генерируем и устанавливаем новый textBoxRsaKey.Text = rsa.ToXmlString(true); textBoxKey.Text = BitConverter.ToString(rsa.Encrypt(FromHex(tmp), false)); } } catch (Exception) { MessageBox.Show("Ошибка при попытке зашифровать основной ключ. Оставлен оригинал основного ключа", "Ошибка формирования дополнительного уровня защиты", MessageBoxButtons.OK); textBoxKey.Text = tmp; } } } else { textBoxKey.Text = tmp; } break; case "String": string cryptFilePath = (string)e.UserState; if (listViewFiles.Items.Contains(listViewFiles.FindItemWithText(cryptFilePath))) { int index = listViewFiles.FindItemWithText(cryptFilePath).Index; listViewFiles.Items[index].Text = cryptFilePath + ".crypto"; listViewFiles.Items[index].BackColor = Color.GreenYellow; listViewFiles.Items[index].EnsureVisible(); } break; case "CryptographicException": Exception ex = (Exception)e.UserState; string filePath = ex.HelpLink; if (listViewFiles.Items.Contains(listViewFiles.FindItemWithText(filePath))) { int index = listViewFiles.FindItemWithText(filePath).Index; listViewFiles.Items[index].BackColor = Color.Red; listViewFiles.Items[index].EnsureVisible(); } break; } } }
/// <summary> /// Функция шифрования файлов AES /// </summary> /// <param name="files"></param> /// <param name="worker"></param> /// <param name="e"></param> /// <returns></returns> private object EncryptFilesAES(CrypterPack cryptPack, BackgroundWorker worker, DoWorkEventArgs e) { // Количество готовых файлов int countDoneCrypt = 0; // Создаём объект aes using (Aes aes = Aes.Create()) { CrypterPack packForKeys = new CrypterPack(); if (cryptPack.iv != null && cryptPack.key != null) { // Ставим другие ключи aes.IV = FromHex(cryptPack.iv); aes.Key = FromHex(cryptPack.key); packForKeys.iv = cryptPack.iv; packForKeys.key = cryptPack.key; } else { // Считываем новые packForKeys.iv = BitConverter.ToString(aes.IV); packForKeys.key = BitConverter.ToString(aes.Key); } // Если объект AES успешно создан, записываем ключи в Бокс worker.ReportProgress(highestPercentageReached, packForKeys); // Для каждого файла из файлов foreach (string filePath in cryptPack.paths) { // Проверяем не отменил ли пользователь операцию if (worker.CancellationPending) { e.Cancel = true; } else { try { if (filePath.Contains(".crypto")) { throw new CryptographicException("Шифрование уже зашифрованного файла."); } EncryptFileFromAES(filePath, aes.Key, aes.IV); } catch (Exception ex) { ex.HelpLink = filePath; worker.ReportProgress(highestPercentageReached, ex); continue; } countDoneCrypt++; // Report progress as a percentage of the total task. int percentComplete = countDoneCrypt * 100 / cryptPack.paths.Length; highestPercentageReached = percentComplete; worker.ReportProgress(percentComplete, filePath); } } } return(0); }
/// <summary> /// Кнопка Зашифровать /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void buttonCryptro_Click(object sender, EventArgs e) { // Пытаемся считать установленный ключ string key = string.Empty; string iv = string.Empty; try { // Если ключ длиннее 48 байт (143 - потому что байты представлены в hex виде) if (textBoxKey.Text.Length > 143) { throw new Exception(); } key = textBoxKey.Text.Substring(0, 95); iv = textBoxKey.Text.Substring(96, 47); } catch (Exception) { var result = MessageBox.Show("Файлы зашифруются новым ключом, который в дальнейшем можно будет использовать", "Ключ отсутствует или задан неверно", MessageBoxButtons.OKCancel); if (result == DialogResult.OK) { key = string.Empty; iv = string.Empty; } else if (result == DialogResult.Cancel) { return; } } // Переносим все выбранные папки treeView в список var selectedFolders = GetAllFilesPathFrom(Descendants(treeView.Nodes) .Where(n => n.Checked && n.Tag != null) .Select(n => n.Tag.ToString()) .ToArray()).ToArray(); var listPaths = GetAllFilesPathFrom(GetAllItemsFrom(listViewFiles.Items) .Select(n => n.Text) .ToArray()).ToArray(); string[] allPaths = selectedFolders.Union(listPaths).ToArray(); listViewFiles.Clear(); // добавляем файлы в listView foreach (var path in allPaths) { listViewFiles.Items.Add(path.ToString()); } // Проверяем наличие файлов if (listViewFiles.Items.Count <= 0) { MessageBox.Show("Пожалуйста, выберите файлы для шифрования", "Не выбраны файлы", MessageBoxButtons.OK); return; } // Удаляем все подсветы UncolorItems(); // Начальные логи logBar.Text = "Logs: Crypt started..."; progressBar.Value = 0; highestPercentageReached = 0; // Если процесс уже не запущен, запускаем if (backgroundCrypter.IsBusy == false && backgroundDecrypter.IsBusy == false) { CrypterPack cryptPack = new CrypterPack(); // Если есть ключи запускаем с ключом if (key != String.Empty && iv != String.Empty) { // Заносим информацию о ключах cryptPack.iv = iv; cryptPack.key = key; cryptPack.paths = allPaths; backgroundCrypter.RunWorkerAsync(cryptPack); } // Если ключа нет, запускаем только по путям else { cryptPack.paths = allPaths; // В отдельном потоке backgroundCrypter.RunWorkerAsync(cryptPack); } CrypterStarted(true); } else { MessageBox.Show("Процесс уже запущен.", "Невозможно запустить второй раз", MessageBoxButtons.OK); } }