diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/core/GpgConstants.cpp | 2 | ||||
-rw-r--r-- | src/core/key_package/KeyPackageOperator.cpp | 108 | ||||
-rw-r--r-- | src/core/key_package/KeyPackageOperator.h | 130 | ||||
-rwxr-xr-x | src/ui/KeyMgmt.cpp | 60 | ||||
-rw-r--r-- | src/ui/import_export/ExportKeyPackageDialog.cpp | 106 | ||||
-rw-r--r-- | src/ui/import_export/ExportKeyPackageDialog.h | 16 |
7 files changed, 296 insertions, 127 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 27a4f81c..5fd37a18 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -27,6 +27,7 @@ aux_source_directory(./result_analyse GPG_SOURCE) aux_source_directory(./function GPG_SOURCE) aux_source_directory(./model GPG_SOURCE) +aux_source_directory(./key_package GPG_SOURCE) aux_source_directory(./aes GPG_SOURCE) aux_source_directory(./file GPG_SOURCE) aux_source_directory(. GPG_SOURCE) diff --git a/src/core/GpgConstants.cpp b/src/core/GpgConstants.cpp index 838164d1..8617e2b9 100644 --- a/src/core/GpgConstants.cpp +++ b/src/core/GpgConstants.cpp @@ -47,7 +47,7 @@ const char* GpgFrontend::GpgConstants::PGP_SIGNATURE_BEGIN = const char* GpgFrontend::GpgConstants::PGP_SIGNATURE_END = "-----END PGP SIGNATURE-----"; ///< const char* GpgFrontend::GpgConstants::PGP_PUBLIC_KEY_BEGIN = - "------BEGIN PGP PUBLIC KEY BLOCK-----"; ///< + "-----BEGIN PGP PUBLIC KEY BLOCK-----"; ///< const char* GpgFrontend::GpgConstants::PGP_PRIVATE_KEY_BEGIN = "-----BEGIN PGP PRIVATE KEY BLOCK-----"; ///< const char* GpgFrontend::GpgConstants::GPG_FRONTEND_SHORT_CRYPTO_HEAD = diff --git a/src/core/key_package/KeyPackageOperator.cpp b/src/core/key_package/KeyPackageOperator.cpp new file mode 100644 index 00000000..b0e21f9f --- /dev/null +++ b/src/core/key_package/KeyPackageOperator.cpp @@ -0,0 +1,108 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric<[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "KeyPackageOperator.h" + +#include <qt-aes/qaesencryption.h> + +#include "core/file/FileOperator.h" +#include "core/function/GpgKeyGetter.h" +#include "core/function/GpgKeyImportExporter.h" + +namespace GpgFrontend { + +bool KeyPackageOperator::GeneratePassphrase( + const std::filesystem::path& phrase_path, std::string& phrase) { + phrase = generate_passphrase(256); + return FileOperator::WriteFileStd(phrase_path, phrase); +} + +bool KeyPackageOperator::GenerateKeyPackage( + const std::filesystem::path& key_package_path, + const std::string& key_package_name, KeyIdArgsListPtr& key_ids, + std::string& phrase, bool secret) { + ByteArrayPtr key_export_data = nullptr; + if (!GpgKeyImportExporter::GetInstance().ExportKeys(key_ids, key_export_data, + secret)) { + return false; + } + + auto key = QByteArray::fromStdString(phrase); + auto data = QString::fromStdString(*key_export_data).toLocal8Bit().toBase64(); + + auto hash_key = QCryptographicHash::hash(key, QCryptographicHash::Sha256); + QAESEncryption encryption(QAESEncryption::AES_256, QAESEncryption::ECB, + QAESEncryption::Padding::ISO); + auto encoded = encryption.encode(data, hash_key); + + return FileOperator::WriteFileStd(key_package_path, encoded.toStdString()); +} + +bool KeyPackageOperator::ImportKeyPackage( + const std::filesystem::path& key_package_path, + const std::filesystem::path& phrase_path, GpgFrontend::GpgImportInformation &import_info) { + + std::string encrypted_data; + FileOperator::ReadFileStd(key_package_path, encrypted_data); + + if (encrypted_data.empty()) { + return false; + }; + + std::string passphrase; + FileOperator::ReadFileStd(phrase_path, passphrase); + if (passphrase.size() != 256) { + return false; + } + + auto hash_key = QCryptographicHash::hash( + QByteArray::fromStdString(passphrase), QCryptographicHash::Sha256); + auto encoded = QByteArray::fromStdString(encrypted_data); + + QAESEncryption encryption(QAESEncryption::AES_256, QAESEncryption::ECB, + QAESEncryption::Padding::ISO); + + auto decoded = encryption.removePadding(encryption.decode(encoded, hash_key)); + auto key_data = QByteArray::fromBase64(decoded); + + if (!key_data.startsWith(GpgConstants::PGP_PUBLIC_KEY_BEGIN) && + !key_data.startsWith(GpgConstants::PGP_PRIVATE_KEY_BEGIN)) { + return false; + } + + auto key_data_ptr = std::make_unique<ByteArray>(key_data.toStdString()); + import_info = + GpgKeyImportExporter::GetInstance().ImportKey(std::move(key_data_ptr)); + return true; +} + +std::string KeyPackageOperator::GenerateKeyPackageName() { + return generate_key_package_name(); +} + +} // namespace GpgFrontend diff --git a/src/core/key_package/KeyPackageOperator.h b/src/core/key_package/KeyPackageOperator.h new file mode 100644 index 00000000..d4185ac8 --- /dev/null +++ b/src/core/key_package/KeyPackageOperator.h @@ -0,0 +1,130 @@ +/** + * Copyright (C) 2021 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric<[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#ifndef GPGFRONTEND_KEYPACKAGEOPERATOR_H +#define GPGFRONTEND_KEYPACKAGEOPERATOR_H + +#include "core/GpgFrontendCore.h" +#include "core/function/GpgKeyImportExporter.h" + +namespace GpgFrontend { + +/** + * @brief give the possibility to import or export a key package + * + */ +class KeyPackageOperator { +public: + /** + * @brief generate passphrase for key package and save it to file + * + * @param phrase_path path to passphrase file + * @param phrase passphrase generated + * @return true if passphrase was generated and saved + * @return false if passphrase was not generated and saved + */ + static bool GeneratePassphrase(const std::filesystem::path &phrase_path, + std::string &phrase); + + /** + * @brief generate the name of the key package + * + * @return std::string name of the key package + */ + static std::string GenerateKeyPackageName(); + + /** + * @brief generate key package + * + * @param key_package_path path to key package + * @param key_package_name name of the key package + * @param key_ids key ids to export + * @param phrase passphrase to encrypt key package + * @param secret true if secret key should be exported + * @return true if key package was generated + * @return false if key package was not generated + */ + static bool GenerateKeyPackage(const std::filesystem::path &key_package_path, + const std::string &key_package_name, + KeyIdArgsListPtr &key_ids, std::string &phrase, + bool secret); + + /** + * @brief import key package + * + * @param key_package_path path to key package + * @param phrase_path path to passphrase file + * @param import_info import info + * @return true if key package was imported + * @return false if key package was not imported + */ + static bool ImportKeyPackage(const std::filesystem::path &key_package_path, + const std::filesystem::path &phrase_path, + GpgFrontend::GpgImportInformation &import_info); + +private: + /** + * @brief genearte passphrase + * + * @param len length of the passphrase + * @return std::string passphrase + */ + static std::string generate_passphrase(const int len) { + std::random_device rd_; ///< Random device + auto mt_ = std::mt19937(rd_()); ///< Mersenne twister + + std::uniform_int_distribution<int> dist(999, 99999); + static const char alphanum[] = "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + std::string tmp_str; + tmp_str.reserve(len); + + for (int i = 0; i < len; ++i) { + tmp_str += alphanum[dist(mt_) % (sizeof(alphanum) - 1)]; + } + return tmp_str; + } + + /** + * @brief generate key package name + * + * @return std::string key package name + */ + static std::string generate_key_package_name() { + std::random_device rd_; ///< Random device + auto mt_ = std::mt19937(rd_()); ///< Mersenne twister + + std::uniform_int_distribution<int> dist(999, 99999); + auto file_string = boost::format("KeyPackage_%1%") % dist(mt_); + return file_string.str(); + } +}; +} // namespace GpgFrontend + +#endif // GPGFRONTEND_KEYPACKAGEOPERATOR_H diff --git a/src/ui/KeyMgmt.cpp b/src/ui/KeyMgmt.cpp index 016ae5c6..58b716ab 100755 --- a/src/ui/KeyMgmt.cpp +++ b/src/ui/KeyMgmt.cpp @@ -33,12 +33,13 @@ #include "core/function/GpgKeyGetter.h" #include "core/function/GpgKeyImportExporter.h" #include "core/function/GpgKeyOpera.h" -#include "ui/import_export/ExportKeyPackageDialog.h" +#include "core/key_package/KeyPackageOperator.h" #include "ui/SignalStation.h" #include "ui/UserInterfaceUtils.h" +#include "ui/import_export/ExportKeyPackageDialog.h" #include "ui/key_generate/SubkeyGenerateDialog.h" -#include "ui/settings/GlobalSettingStation.h" #include "ui/main_window/MainWindow.h" +#include "ui/settings/GlobalSettingStation.h" namespace GpgFrontend::UI { KeyMgmt::KeyMgmt(QWidget* parent) : QMainWindow(parent) { @@ -97,7 +98,8 @@ KeyMgmt::KeyMgmt(QWidget* parent) : QMainWindow(parent) { create_menus(); create_tool_bars(); - connect(this, &KeyMgmt::SignalStatusBarChanged, qobject_cast<MainWindow*>(this->parent()) , + connect(this, &KeyMgmt::SignalStatusBarChanged, + qobject_cast<MainWindow*>(this->parent()), &MainWindow::SlotSetStatusBarText); auto& settings = GlobalSettingStation::GetInstance().GetUISettings(); @@ -156,7 +158,7 @@ KeyMgmt::KeyMgmt(QWidget* parent) : QMainWindow(parent) { key_list_->AddMenuAction(show_key_details_act_); connect(this, &KeyMgmt::SignalKeyStatusUpdated, SignalStation::GetInstance(), - &SignalStation::SignalKeyDatabaseRefresh); + &SignalStation::SignalKeyDatabaseRefresh); connect(SignalStation::GetInstance(), &SignalStation::SignalRefreshStatusBar, this, [=](const QString& message, int timeout) { statusBar()->showMessage(message, timeout); @@ -528,54 +530,26 @@ void KeyMgmt::SlotImportKeyPackage() { this, _("Import Key Package"), {}, QString(_("Key Package")) + " (*.gfepack);;All Files (*)"); - if (key_package_file_name.isEmpty()) return; - - auto encrypted_data = - read_all_data_in_file(key_package_file_name.toStdString()); - - if (encrypted_data.empty()) { - QMessageBox::critical(this, _("Error"), - _("No data was read from the key package.")); - return; - }; - auto key_file_name = QFileDialog::getOpenFileName( this, _("Import Key Package Passphrase File"), {}, QString(_("Key Package Passphrase File")) + " (*.key);;All Files (*)"); - auto passphrase = read_all_data_in_file(key_file_name.toStdString()); - - LOG(INFO) << "passphrase size" << passphrase.size(); - if (passphrase.size() != 256) { - QMessageBox::critical( - this, _("Wrong Passphrase"), - _("Please double check the passphrase you entered is correct.")); + if(key_package_file_name.isEmpty() || key_file_name.isEmpty()) return; - } - auto hash_key = QCryptographicHash::hash( - QByteArray::fromStdString(passphrase), QCryptographicHash::Sha256); - auto encoded = QByteArray::fromStdString(encrypted_data); - QAESEncryption encryption(QAESEncryption::AES_256, QAESEncryption::ECB, - QAESEncryption::Padding::ISO); + GpgImportInformation info; - auto decoded = encryption.removePadding(encryption.decode(encoded, hash_key)); - auto key_data = QByteArray::fromBase64(decoded); + if (KeyPackageOperator::ImportKeyPackage(key_package_file_name.toStdString(), + key_file_name.toStdString(), info)) { + emit SignalStatusBarChanged(QString(_("key(s) imported"))); + emit SignalKeyStatusUpdated(); - if (!key_data.startsWith(GpgConstants::PGP_PUBLIC_KEY_BEGIN) && - !key_data.startsWith(GpgConstants::PGP_PRIVATE_KEY_BEGIN)) { - QMessageBox::critical( - this, _("Wrong Passphrase"), - _("Please double check the passphrase you entered is correct.")); - return; + auto dialog = new KeyImportDetailDialog(info, false, this); + dialog->exec(); + } else { + QMessageBox::critical(this, _("Error"), + _("An error occur in importing key package.")); } - - auto key_data_ptr = std::make_unique<ByteArray>(key_data.toStdString()); - auto info = - GpgKeyImportExporter::GetInstance().ImportKey(std::move(key_data_ptr)); - - auto dialog = new KeyImportDetailDialog(info, false, this); - dialog->exec(); } } // namespace GpgFrontend::UI diff --git a/src/ui/import_export/ExportKeyPackageDialog.cpp b/src/ui/import_export/ExportKeyPackageDialog.cpp index 2b275fd3..d813d12c 100644 --- a/src/ui/import_export/ExportKeyPackageDialog.cpp +++ b/src/ui/import_export/ExportKeyPackageDialog.cpp @@ -31,21 +31,23 @@ #include <boost/format.hpp> #include "core/function/GpgKeyGetter.h" -#include "core/function/GpgKeyImportExporter.h" +#include "core/key_package/KeyPackageOperator.h" #include "ui_ExportKeyPackageDialog.h" GpgFrontend::UI::ExportKeyPackageDialog::ExportKeyPackageDialog( KeyIdArgsListPtr key_ids, QWidget* parent) : QDialog(parent), ui_(std::make_shared<Ui_exportKeyPackageDialog>()), - key_ids_(std::move(key_ids)), - mt_(rd_()) { + key_ids_(std::move(key_ids)) { ui_->setupUi(this); - generate_key_package_name(); + ui_->nameValueLabel->setText( + KeyPackageOperator::GenerateKeyPackageName().c_str()); - connect(ui_->gnerateNameButton, &QPushButton::clicked, this, - [=]() { generate_key_package_name(); }); + connect(ui_->gnerateNameButton, &QPushButton::clicked, this, [=]() { + ui_->nameValueLabel->setText( + KeyPackageOperator::GenerateKeyPackageName().c_str()); + }); connect(ui_->setOutputPathButton, &QPushButton::clicked, this, [=]() { auto file_name = QFileDialog::getSaveFileName( @@ -55,13 +57,19 @@ GpgFrontend::UI::ExportKeyPackageDialog::ExportKeyPackageDialog( }); connect(ui_->generatePassphraseButton, &QPushButton::clicked, this, [=]() { - passphrase_ = generate_passphrase(256); auto file_name = QFileDialog::getSaveFileName( this, _("Export Key Package Passphrase"), ui_->nameValueLabel->text() + ".key", QString(_("Key File")) + " (*.key);;All Files (*)"); + + if (!KeyPackageOperator::GeneratePassphrase(file_name.toStdString(), + passphrase_)) { + QMessageBox::critical( + this, _("Error"), + _("An error occurred while generating the passphrase file.")); + return; + } ui_->passphraseValueLabel->setText(file_name); - write_buffer_to_file(file_name.toStdString(), passphrase_); }); connect(ui_->button_box_, &QDialogButtonBox::accepted, this, [=]() { @@ -81,48 +89,37 @@ GpgFrontend::UI::ExportKeyPackageDialog::ExportKeyPackageDialog( return; } + // get suitable key ids auto key_id_exported = std::make_unique<KeyIdArgsList>(); auto keys = GpgKeyGetter::GetInstance().GetKeys(key_ids_); for (const auto& key : *keys) { - if (ui_->noPublicKeyCheckBox->isChecked() && !key.IsPrivateKey()) { + if (ui_->noPublicKeyCheckBox->isChecked() && !key.IsPrivateKey()) continue; - } key_id_exported->push_back(key.GetId()); } - ByteArrayPtr key_export_data = nullptr; - if (!GpgKeyImportExporter::GetInstance().ExportKeys( - key_ids_, key_export_data, - ui_->includeSecretKeyCheckBox->isChecked())) { - QMessageBox::critical(this, _("Error"), _("Export Key(s) Failed.")); - this->close(); - return; + if (KeyPackageOperator::GenerateKeyPackage( + ui_->outputPathLabel->text().toStdString(), + ui_->nameValueLabel->text().toStdString(), key_id_exported, + passphrase_, ui_->includeSecretKeyCheckBox->isChecked())) { + QMessageBox::information( + this, _("Success"), + QString( + _("The Key Package has been successfully generated and has been " + "protected by encryption algorithms(AES-256-ECB). You can " + "safely transfer your Key Package.")) + + "<br /><br />" + "<b>" + + _("But the key file cannot be leaked under any " + "circumstances. Please delete the Key Package and key file as " + "soon " + "as possible after completing the transfer operation.") + + "</b>"); + accept(); + } else { + QMessageBox::critical( + this, _("Error"), + _("An error occurred while exporting the key package.")); } - - auto key = QByteArray::fromStdString(passphrase_), - data = - QString::fromStdString(*key_export_data).toLocal8Bit().toBase64(); - - auto hash_key = QCryptographicHash::hash(key, QCryptographicHash::Sha256); - QAESEncryption encryption(QAESEncryption::AES_256, QAESEncryption::ECB, - QAESEncryption::Padding::ISO); - auto encoded = encryption.encode(data, hash_key); - - write_buffer_to_file(ui_->outputPathLabel->text().toStdString(), - encoded.toStdString()); - - QMessageBox::information( - this, _("Success"), - QString(_( - "The Key Package has been successfully generated and has been " - "protected by encryption algorithms. You can safely transfer your " - "Key Package.")) + - "<br />" + "<b>" + - _("But the key file cannot be leaked under any " - "circumstances. Please delete the Key Package and key file as " - "soon " - "as possible after completing the transfer operation.") + - "</b>"); }); connect(ui_->button_box_, &QDialogButtonBox::rejected, this, @@ -146,28 +143,3 @@ GpgFrontend::UI::ExportKeyPackageDialog::ExportKeyPackageDialog( setAttribute(Qt::WA_DeleteOnClose); setWindowTitle(_("exportKeyPackageDialog")); } - -std::string GpgFrontend::UI::ExportKeyPackageDialog::generate_passphrase( - const int len) { - std::uniform_int_distribution<int> dist(999, 99999); - static const char alphanum[] = - "0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz"; - std::string tmp_str; - tmp_str.reserve(len); - - for (int i = 0; i < len; ++i) { - tmp_str += alphanum[dist(mt_) % (sizeof(alphanum) - 1)]; - } - - return tmp_str; -} - -void GpgFrontend::UI::ExportKeyPackageDialog::generate_key_package_name() { - std::uniform_int_distribution<int> dist(999, 99999); - auto file_string = boost::format("KeyPackage_%1%") % dist(mt_); - ui_->nameValueLabel->setText(file_string.str().c_str()); - ui_->outputPathLabel->clear(); - ui_->passphraseValueLabel->clear(); -} diff --git a/src/ui/import_export/ExportKeyPackageDialog.h b/src/ui/import_export/ExportKeyPackageDialog.h index 68f9b433..ecf13b1d 100644 --- a/src/ui/import_export/ExportKeyPackageDialog.h +++ b/src/ui/import_export/ExportKeyPackageDialog.h @@ -54,23 +54,7 @@ class ExportKeyPackageDialog : public QDialog { private: std::shared_ptr<Ui_exportKeyPackageDialog> ui_; ///< KeyIdArgsListPtr key_ids_; ///< - std::random_device rd_; ///< - std::mt19937 mt_; ///< std::string passphrase_; ///< - - /** - * @brief - * - * @param len - * @return std::string - */ - std::string generate_passphrase(int len); - - /** - * @brief - * - */ - void generate_key_package_name(); }; } // namespace GpgFrontend::UI |