aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2024-07-28 15:08:48 +0000
committersaturneric <[email protected]>2024-07-28 15:08:56 +0000
commit4e0db9ef4bf329d5698b31bd93601004305f71dc (patch)
tree94a22cfab394456ff89392831d3e146a76413118
parentfix: remove invalid parameters from the SDK (diff)
downloadGpgFrontend-4e0db9ef4bf329d5698b31bd93601004305f71dc.tar.gz
GpgFrontend-4e0db9ef4bf329d5698b31bd93601004305f71dc.zip
feat: add paper key module support
-rw-r--r--src/core/GpgConstants.h9
-rw-r--r--src/ui/dialog/controller/ModuleControllerDialog.cpp8
-rw-r--r--src/ui/dialog/keypair_details/KeyPairOperaTab.cpp166
-rw-r--r--src/ui/dialog/keypair_details/KeyPairOperaTab.h12
-rw-r--r--ui/ModuleControllerDialog.ui2
5 files changed, 189 insertions, 8 deletions
diff --git a/src/core/GpgConstants.h b/src/core/GpgConstants.h
index 1c514703..1165db78 100644
--- a/src/core/GpgConstants.h
+++ b/src/core/GpgConstants.h
@@ -53,10 +53,13 @@ constexpr const char* PGP_PRIVATE_KEY_BEGIN =
"-----BEGIN PGP PRIVATE KEY BLOCK-----"; ///<
// MODULE ID
-const QString kGnuPGInfoGatheringModuleID =
+constexpr const char* kGnuPGInfoGatheringModuleID =
"com.bktus.gpgfrontend.module.gnupg_info_gathering";
-const QString kVersionCheckingModuleID =
+constexpr const char* kVersionCheckingModuleID =
"com.bktus.gpgfrontend.module.version_checking";
-const QString kPinentryModuleID = "com.bktus.gpgfrontend.module.pinentry";
+constexpr const char* kPinentryModuleID =
+ "com.bktus.gpgfrontend.module.pinentry";
+constexpr const char* kPaperKeyModuleID =
+ "com.bktus.gpgfrontend.module.paper_key";
} // namespace GpgFrontend
diff --git a/src/ui/dialog/controller/ModuleControllerDialog.cpp b/src/ui/dialog/controller/ModuleControllerDialog.cpp
index 8f1df81c..aa69eb5a 100644
--- a/src/ui/dialog/controller/ModuleControllerDialog.cpp
+++ b/src/ui/dialog/controller/ModuleControllerDialog.cpp
@@ -62,14 +62,14 @@ ModuleControllerDialog::ModuleControllerDialog(QWidget* parent)
connect(ui_->moduleListView, &ModuleListView::SignalSelectModule, this,
&ModuleControllerDialog::slot_load_module_details);
- connect(ui_->activateOrDeactiveButton, &QPushButton::clicked, this, [=]() {
+ connect(ui_->activateOrDeactivateButton, &QPushButton::clicked, this, [=]() {
auto module_id = ui_->moduleListView->GetCurrentModuleID();
if (module_id.isEmpty()) return;
if (!module_manager_->IsModuleActivated(module_id)) {
module_manager_->ActiveModule(module_id);
} else {
- module_manager_->DeactiveModule(module_id);
+ module_manager_->DeactivateModule(module_id);
}
QTimer::singleShot(1000, [=]() { slot_load_module_details(module_id); });
@@ -178,8 +178,8 @@ void ModuleControllerDialog::slot_load_module_details(
}
ui_->moduleInfoTextBrowser->setText(buffer);
- ui_->activateOrDeactiveButton->setText(if_activated ? tr("Deactivate")
- : tr("Activate"));
+ ui_->activateOrDeactivateButton->setText(if_activated ? tr("Deactivate")
+ : tr("Activate"));
ui_->autoActivateButton->setText(module_so.auto_activate
? tr("Disable Auto Activate")
: tr("Enable Auto Activate"));
diff --git a/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp b/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp
index 10a1ac00..34b03cd9 100644
--- a/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp
+++ b/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp
@@ -34,6 +34,7 @@
#include "core/function/gpg/GpgKeyImportExporter.h"
#include "core/function/gpg/GpgKeyOpera.h"
#include "core/model/GpgKey.h"
+#include "core/module/ModuleManager.h"
#include "core/typedef/GpgTypedef.h"
#include "core/utils/GpgUtils.h"
#include "core/utils/IOUtils.h"
@@ -96,6 +97,16 @@ KeyPairOperaTab::KeyPairOperaTab(const QString& key_id, QWidget* parent)
key_server_opera_button->setDisabled(forbid_all_gnupg_connection);
advance_h_box_layout->addWidget(key_server_opera_button);
+ if (!Module::IsModuleActivate(kPaperKeyModuleID)) {
+ if (!m_key_.IsPrivateKey() || !m_key_.IsHasMasterKey()) {
+ auto* import_paper_key_button = new QPushButton(tr("Import A Paper Key"));
+ import_paper_key_button->setStyleSheet("text-align:center;");
+ connect(import_paper_key_button, &QPushButton::clicked, this,
+ &KeyPairOperaTab::slot_import_paper_key);
+ vbox_p_k->addWidget(import_paper_key_button);
+ }
+ }
+
if (m_key_.IsPrivateKey() && m_key_.IsHasMasterKey()) {
auto* revoke_cert_opera_button =
new QPushButton(tr("Revoke Certificate Operation"));
@@ -168,6 +179,17 @@ void KeyPairOperaTab::CreateOperaMenu() {
connect(export_shortest_secret_key, &QAction::triggered, this,
&KeyPairOperaTab::slot_export_short_private_key);
+ if (!Module::IsModuleActivate(kPaperKeyModuleID)) {
+ auto* export_secret_key_as_paper_key =
+ new QAction(tr("Export Secret Key As A Paper Key"), this);
+ connect(export_secret_key_as_paper_key, &QAction::triggered, this,
+ &KeyPairOperaTab::slot_export_paper_key);
+ if (!m_key_.IsPrivateKey()) {
+ export_secret_key_as_paper_key->setDisabled(true);
+ }
+ secret_key_export_opera_menu_->addAction(export_secret_key_as_paper_key);
+ }
+
secret_key_export_opera_menu_->addAction(export_full_secret_key);
secret_key_export_opera_menu_->addAction(export_shortest_secret_key);
@@ -447,4 +469,148 @@ void KeyPairOperaTab::slot_import_revoke_cert() {
emit UISignalStation::GetInstance() -> SignalKeyRevoked(m_key_.GetId());
CommonUtils::GetInstance()->SlotImportKeys(nullptr, rev_file.readAll());
}
+
+void KeyPairOperaTab::slot_export_paper_key() {
+ if (!Module::IsModuleActivate(kPaperKeyModuleID)) return;
+
+ int ret = QMessageBox::information(
+ this, tr("Exporting private key as a Paper key"),
+ "<h3>" + tr("You are about to export your") + "<font color=\"red\">" +
+ tr(" PRIVATE KEY ") + "</font>!</h3>\n" +
+ tr("This is NOT your Public Key, so DON'T give it away.") + "<br />" +
+ tr("A PaperKey is a human-readable printout of your private key, "
+ "which can be used to recover your key if you lose access to "
+ "your "
+ "digital copy. ") +
+ "<br />" + tr("Keep it in a safe place.") + "<br />" +
+ tr("Do you REALLY want to export your PRIVATE KEY?"),
+ QMessageBox::Cancel | QMessageBox::Ok);
+
+ // export key, if ok was clicked
+ if (ret == QMessageBox::Ok) {
+ auto [err, gf_buffer] = GpgKeyImportExporter::GetInstance().ExportKey(
+ m_key_, true, false, true);
+ if (CheckGpgError(err) != GPG_ERR_NO_ERROR) {
+ CommonUtils::RaiseMessageBox(this, err);
+ return;
+ }
+
+ // generate a file name
+#ifndef WINDOWS
+ auto file_string = m_key_.GetName() + "<" + m_key_.GetEmail() + ">(" +
+ m_key_.GetId() + ")_paper_key.txt";
+#else
+ auto file_string = m_key_.GetName() + "[" + m_key_.GetEmail() + "](" +
+ m_key_.GetId() + ")_paper_key.txt";
+#endif
+ std::replace(file_string.begin(), file_string.end(), ' ', '_');
+
+ auto file_name = QFileDialog::getSaveFileName(
+ this, tr("Export Key To File"), file_string,
+ tr("Key Files") + " (*.txt);;All Files (*)");
+
+ if (file_name.isEmpty()) return;
+
+ Module::TriggerEvent(
+ "REQUEST_TRANS_KEY_2_PAPER_KEY",
+ {
+ {"secret_key", QString(gf_buffer.ConvertToQByteArray().toBase64())},
+ },
+ [this, file_name](Module::EventIdentifier i,
+ Module::Event::ListenerIdentifier ei,
+ Module::Event::Params p) {
+ qCDebug(ui) << "REQUEST_TRANS_KEY_2_PAPER_KEY callback: " << i << ei;
+
+ if (p["ret"] != "0" || p["paper_key"].isEmpty()) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("An error occurred trying to recover the "
+ "Paper Key back to the private key."));
+ return;
+ }
+
+ if (!WriteFile(file_name, p["paper_key"].toLatin1())) {
+ QMessageBox::critical(
+ this, tr("Export Error"),
+ tr("Couldn't open %1 for writing").arg(file_name));
+ return;
+ }
+ });
+ }
+}
+
+void KeyPairOperaTab::slot_import_paper_key() {
+ if (!Module::IsModuleActivate(kPaperKeyModuleID)) return;
+
+ auto [err, gf_buffer] =
+ GpgKeyImportExporter::GetInstance().ExportKey(m_key_, false, false, true);
+ if (CheckGpgError(err) != GPG_ERR_NO_ERROR) {
+ CommonUtils::RaiseMessageBox(this, err);
+ return;
+ }
+
+ // generate a file name
+#ifndef WINDOWS
+ auto file_string = m_key_.GetName() + "<" + m_key_.GetEmail() + ">(" +
+ m_key_.GetId() + ")_paper_key.txt";
+#else
+ auto file_string = m_key_.GetName() + "[" + m_key_.GetEmail() + "](" +
+ m_key_.GetId() + ")_paper_key.txt";
+#endif
+ std::replace(file_string.begin(), file_string.end(), ' ', '_');
+
+ auto file_name = QFileDialog::getOpenFileName(
+ this, tr("Import A Paper Key"), file_string,
+ tr("Paper Key File") + " (*.txt);;All Files (*)");
+
+ if (file_name.isEmpty()) return;
+
+ QFileInfo file_info(file_name);
+
+ if (!file_info.isFile() || !file_info.isReadable()) {
+ QMessageBox::critical(
+ this, tr("Error"),
+ tr("Cannot open this file. Please make sure that this "
+ "is a regular file and it's readable."));
+ return;
+ }
+
+ if (file_info.size() > static_cast<qint64>(1024 * 1024)) {
+ QMessageBox::critical(
+ this, tr("Error"),
+ tr("The target file is too large for a paper key keyring."));
+ return;
+ }
+
+ auto [succ, gf_in_buff] = ReadFileGFBuffer(file_name);
+ if (!succ) {
+ QMessageBox::critical(
+ this, tr("Error"),
+ tr("Cannot open this file. Please make sure that this "
+ "is a regular file and it's readable."));
+ return;
+ }
+
+ Module::TriggerEvent(
+ "REQUEST_TRANS_PAPER_KEY_2_KEY",
+ {
+ {"public_key", QString(gf_buffer.ConvertToQByteArray().toBase64())},
+ {"paper_key_secrets",
+ QString(gf_in_buff.ConvertToQByteArray().toBase64())},
+ },
+ [this](Module::EventIdentifier i, Module::Event::ListenerIdentifier ei,
+ Module::Event::Params p) {
+ qCDebug(ui) << "REQUEST_TRANS_PAPER_KEY_2_KEY callback: " << i << ei;
+
+ if (p["ret"] != "0" || p["secret_key"].isEmpty()) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("An error occurred trying to recover the "
+ "Paper Key back to the private key."));
+ return;
+ }
+
+ CommonUtils::GetInstance()->SlotImportKeys(
+ this, QByteArray::fromBase64(p["secret_key"].toLatin1()));
+ });
+}
+
} // namespace GpgFrontend::UI
diff --git a/src/ui/dialog/keypair_details/KeyPairOperaTab.h b/src/ui/dialog/keypair_details/KeyPairOperaTab.h
index 22c94957..27bc7400 100644
--- a/src/ui/dialog/keypair_details/KeyPairOperaTab.h
+++ b/src/ui/dialog/keypair_details/KeyPairOperaTab.h
@@ -126,6 +126,18 @@ class KeyPairOperaTab : public QWidget {
*/
void slot_import_revoke_cert();
+ /**
+ * @brief
+ *
+ */
+ void slot_export_paper_key();
+
+ /**
+ * @brief
+ *
+ */
+ void slot_import_paper_key();
+
private:
GpgKey m_key_; ///<
QMenu* key_server_opera_menu_{}; ///<
diff --git a/ui/ModuleControllerDialog.ui b/ui/ModuleControllerDialog.ui
index 97dd1397..910a3de8 100644
--- a/ui/ModuleControllerDialog.ui
+++ b/ui/ModuleControllerDialog.ui
@@ -111,7 +111,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
- <widget class="QPushButton" name="activateOrDeactiveButton">
+ <widget class="QPushButton" name="activateOrDeactivateButton">
<property name="enabled">
<bool>true</bool>
</property>