aboutsummaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt101
-rw-r--r--src/core/GpgConstants.cpp224
-rw-r--r--src/core/GpgConstants.h220
-rw-r--r--src/core/GpgContext.cpp224
-rw-r--r--src/core/GpgContext.h164
-rw-r--r--src/core/GpgCoreInit.cpp56
-rw-r--r--src/core/GpgCoreInit.h52
-rw-r--r--src/core/GpgFrontendCore.h61
-rw-r--r--src/core/GpgFunctionObject.h247
-rw-r--r--src/core/GpgGenKeyInfo.cpp225
-rw-r--r--src/core/GpgGenKeyInfo.h435
-rw-r--r--src/core/GpgInfo.cpp29
-rw-r--r--src/core/GpgInfo.h50
-rw-r--r--src/core/GpgModel.h60
-rw-r--r--src/core/function/ArchiveFileOperator.cpp238
-rw-r--r--src/core/function/ArchiveFileOperator.h79
-rw-r--r--src/core/function/DataObjectOperator.cpp169
-rw-r--r--src/core/function/DataObjectOperator.h82
-rw-r--r--src/core/function/FileOperator.cpp119
-rw-r--r--src/core/function/FileOperator.h92
-rw-r--r--src/core/function/GlobalSettingStation.cpp141
-rw-r--r--src/core/function/GlobalSettingStation.h232
-rw-r--r--src/core/function/KeyPackageOperator.cpp120
-rw-r--r--src/core/function/KeyPackageOperator.h107
-rw-r--r--src/core/function/PassphraseGenerator.cpp29
-rw-r--r--src/core/function/PassphraseGenerator.h83
-rw-r--r--src/core/function/aes/aes_ssl.h74
-rw-r--r--src/core/function/aes/aes_ssl_cbc.cpp99
-rw-r--r--src/core/function/gpg/GpgBasicOperator.cpp220
-rw-r--r--src/core/function/gpg/GpgBasicOperator.h179
-rw-r--r--src/core/function/gpg/GpgCommandExecutor.cpp63
-rw-r--r--src/core/function/gpg/GpgCommandExecutor.h77
-rw-r--r--src/core/function/gpg/GpgFileOpera.cpp182
-rw-r--r--src/core/function/gpg/GpgFileOpera.h153
-rw-r--r--src/core/function/gpg/GpgKeyGetter.cpp96
-rw-r--r--src/core/function/gpg/GpgKeyGetter.h110
-rw-r--r--src/core/function/gpg/GpgKeyImportExporter.cpp178
-rw-r--r--src/core/function/gpg/GpgKeyImportExporter.h195
-rw-r--r--src/core/function/gpg/GpgKeyManager.cpp92
-rw-r--r--src/core/function/gpg/GpgKeyManager.h93
-rw-r--r--src/core/function/gpg/GpgKeyOpera.cpp293
-rw-r--r--src/core/function/gpg/GpgKeyOpera.h135
-rw-r--r--src/core/function/gpg/GpgUIDOperator.cpp68
-rw-r--r--src/core/function/gpg/GpgUIDOperator.h88
-rw-r--r--src/core/function/result_analyse/GpgDecryptResultAnalyse.cpp97
-rw-r--r--src/core/function/result_analyse/GpgDecryptResultAnalyse.h73
-rw-r--r--src/core/function/result_analyse/GpgEncryptResultAnalyse.cpp66
-rw-r--r--src/core/function/result_analyse/GpgEncryptResultAnalyse.h63
-rw-r--r--src/core/function/result_analyse/GpgResultAnalyse.cpp46
-rw-r--r--src/core/function/result_analyse/GpgResultAnalyse.h86
-rw-r--r--src/core/function/result_analyse/GpgSignResultAnalyse.cpp115
-rw-r--r--src/core/function/result_analyse/GpgSignResultAnalyse.h65
-rw-r--r--src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp214
-rw-r--r--src/core/function/result_analyse/GpgVerifyResultAnalyse.h88
-rw-r--r--src/core/model/GpgData.cpp76
-rw-r--r--src/core/model/GpgData.h87
-rw-r--r--src/core/model/GpgKey.cpp115
-rw-r--r--src/core/model/GpgKey.h415
-rw-r--r--src/core/model/GpgKeySignature.cpp32
-rw-r--r--src/core/model/GpgKeySignature.h209
-rw-r--r--src/core/model/GpgSignature.cpp32
-rw-r--r--src/core/model/GpgSignature.h171
-rw-r--r--src/core/model/GpgSubKey.cpp31
-rw-r--r--src/core/model/GpgSubKey.h248
-rw-r--r--src/core/model/GpgTOFUInfo.cpp32
-rw-r--r--src/core/model/GpgTOFUInfo.h167
-rw-r--r--src/core/model/GpgUID.cpp32
-rw-r--r--src/core/model/GpgUID.h171
68 files changed, 8765 insertions, 0 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
new file mode 100644
index 00000000..192e1e0c
--- /dev/null
+++ b/src/core/CMakeLists.txt
@@ -0,0 +1,101 @@
+#
+# 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
+
+aux_source_directory(./function/result_analyse GPG_SOURCE)
+aux_source_directory(./function/gpg GPG_SOURCE)
+aux_source_directory(./function/aes GPG_SOURCE)
+aux_source_directory(./function GPG_SOURCE)
+aux_source_directory(./model GPG_SOURCE)
+aux_source_directory(. GPG_SOURCE)
+
+# define libgpgfrontend_core
+add_library(gpgfrontend_core STATIC ${GPG_SOURCE})
+
+set(UTILS_DIR ${CMAKE_SOURCE_DIR}/utils)
+set(GPGME_LIB_DIR ${UTILS_DIR}/gpgme/lib)
+
+# link third-party libraries
+target_link_libraries(gpgfrontend_core easyloggingpp config++)
+# link boost libraries
+target_link_libraries(gpgfrontend_core Boost::date_time Boost::system)
+# link gnupg libraries
+target_link_libraries(gpgfrontend_core gpgme assuan gpg-error)
+# link openssl
+target_link_libraries(gpgfrontend_core OpenSSL::SSL OpenSSL::Crypto)
+# link Qt AES
+target_link_libraries(gpgfrontend_core QtAES)
+# link vmime
+if (NOT LINUX)
+ # macOS
+ target_link_libraries(gpgfrontend_core
+ gpgfrontend_vmime intl iconv)
+ if (MINGW)
+ target_link_libraries(gpgfrontend_core ws2_32)
+ endif ()
+else ()
+ target_link_libraries(gpgfrontend_core
+ gpgfrontend_vmime anl ssl crypto)
+endif ()
+# link libarchive
+if (MINGW)
+ find_library(LIBARCHIVE_LIB libarchive.a)
+ target_link_libraries(gpgfrontend_core ${LIBARCHIVE_LIB} bcrypt lzma bz2 z)
+else ()
+ target_link_libraries(gpgfrontend_core archive_static)
+endif ()
+# link json
+target_link_libraries(gpgfrontend_core
+ nlohmann_json::nlohmann_json)
+# link Qt core
+target_link_libraries(gpgfrontend_core Qt5::Core)
+
+# set up pch
+target_precompile_headers(gpgfrontend_core
+ PUBLIC ${CMAKE_SOURCE_DIR}/src/GpgFrontend.h
+ PUBLIC GpgFrontendCore.h)
+
+# using std c++ 17
+target_compile_features(gpgfrontend_core PUBLIC cxx_std_17)
+
+# link for different platforms
+if (MINGW)
+ message(STATUS "Link GPG Static Library For MINGW")
+ target_link_libraries(gpgfrontend_core wsock32)
+elseif (APPLE)
+ message(STATUS "Link GPG Static Library For macOS")
+ target_link_libraries(gpgfrontend_core dl)
+ if (XCODE_BUILD)
+ set_target_properties(gpgfrontend_core
+ PROPERTIES
+ ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}
+ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}
+ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE})
+ endif ()
+else ()
+ # linux
+ message(STATUS "Link GPG Static Library For Unix")
+ target_link_libraries(gpgfrontend_core pthread dl)
+endif ()
diff --git a/src/core/GpgConstants.cpp b/src/core/GpgConstants.cpp
new file mode 100644
index 00000000..f35c257d
--- /dev/null
+++ b/src/core/GpgConstants.cpp
@@ -0,0 +1,224 @@
+/**
+ * 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 "core/GpgConstants.h"
+
+#include <gpg-error.h>
+
+#include <boost/algorithm/string/predicate.hpp>
+#include <string>
+
+const char* GpgFrontend::GpgConstants::PGP_CRYPT_BEGIN =
+ "-----BEGIN PGP MESSAGE-----"; ///<
+const char* GpgFrontend::GpgConstants::PGP_CRYPT_END =
+ "-----END PGP MESSAGE-----"; ///<
+const char* GpgFrontend::GpgConstants::PGP_SIGNED_BEGIN =
+ "-----BEGIN PGP SIGNED MESSAGE-----"; ///<
+const char* GpgFrontend::GpgConstants::PGP_SIGNED_END =
+ "-----END PGP SIGNATURE-----"; ///<
+const char* GpgFrontend::GpgConstants::PGP_SIGNATURE_BEGIN =
+ "-----BEGIN PGP SIGNATURE-----"; ///<
+const char* GpgFrontend::GpgConstants::PGP_SIGNATURE_END =
+ "-----END PGP SIGNATURE-----"; ///<
+const char* GpgFrontend::GpgConstants::PGP_PUBLIC_KEY_BEGIN =
+ "-----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 =
+ "GpgF_Scpt://"; ///<
+
+gpgme_error_t GpgFrontend::check_gpg_error(gpgme_error_t err) {
+ if (gpg_err_code(err) != GPG_ERR_NO_ERROR) {
+ LOG(ERROR) << "[" << _("Error") << " " << gpg_err_code(err) << "] "
+ << _("Source: ") << gpgme_strsource(err) << " "
+ << _("Description: ") << gpgme_strerror(err);
+ }
+ return err;
+}
+
+gpg_err_code_t GpgFrontend::check_gpg_error_2_err_code(gpgme_error_t err,
+ gpgme_error_t predict) {
+ auto err_code = gpg_err_code(err);
+ if (err_code != predict) {
+ LOG(ERROR) << "[" << _("Error") << " " << gpg_err_code(err) << "] "
+ << _("Source: ") << gpgme_strsource(err) << " "
+ << _("Description: ") << gpgme_strerror(err);
+ }
+ return err_code;
+}
+
+gpgme_error_t GpgFrontend::check_gpg_error(gpgme_error_t err,
+ const std::string& comment) {
+ if (gpg_err_code(err) != GPG_ERR_NO_ERROR) {
+ LOG(ERROR) << "[" << _("Error") << " " << gpg_err_code(err) << "] "
+ << _("Source: ") << gpgme_strsource(err) << " "
+ << _("Description: ") << gpgme_strerror(err);
+ }
+ return err;
+}
+
+std::string GpgFrontend::beautify_fingerprint(
+ GpgFrontend::BypeArrayConstRef fingerprint) {
+ auto len = fingerprint.size();
+ std::stringstream out;
+ decltype(len) count = 0;
+ while (count < len) {
+ if (count && !(count % 5)) out << " ";
+ out << fingerprint[count];
+ count++;
+ }
+ return out.str();
+}
+
+static inline void ltrim(std::string& s) {
+ s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
+ return !std::isspace(ch);
+ }));
+}
+
+static inline void rtrim(std::string& s) {
+ s.erase(std::find_if(s.rbegin(), s.rend(),
+ [](unsigned char ch) { return !std::isspace(ch); })
+ .base(),
+ s.end());
+}
+
+static inline std::string trim(std::string& s) {
+ ltrim(s);
+ rtrim(s);
+ return s;
+}
+
+std::string GpgFrontend::read_all_data_in_file(const std::string& utf8_path) {
+ using namespace std::filesystem;
+ class path file_info(utf8_path.c_str());
+ if (!exists(file_info) || !is_regular_file(file_info)) return {};
+ std::ifstream in_file;
+#ifndef WINDOWS
+ in_file.open(file_info.string(), std::ios::in);
+#else
+ in_file.open(file_info.wstring().c_str(), std::ios::in);
+#endif
+ if (!in_file.good()) return {};
+ std::istreambuf_iterator<char> begin(in_file);
+ std::istreambuf_iterator<char> end;
+ std::string in_buffer(begin, end);
+ in_file.close();
+ return in_buffer;
+}
+
+bool GpgFrontend::write_buffer_to_file(const std::string& utf8_path,
+ const std::string& out_buffer) {
+ using namespace std::filesystem;
+ class path file_info(utf8_path.c_str());
+#ifndef WINDOWS
+ std::ofstream out_file(file_info.string(), std::ios::out | std::ios::trunc);
+#else
+ std::ofstream out_file(file_info.wstring().c_str(),
+ std::ios::out | std::ios::trunc);
+#endif
+ if (!out_file.good()) return false;
+ out_file.write(out_buffer.c_str(), out_buffer.size());
+ out_file.close();
+ return true;
+}
+
+std::string GpgFrontend::get_file_extension(const std::string& path) {
+ // Create a path object from given string
+ std::filesystem::path path_obj(path);
+
+ // Check if file name in the path object has extension
+ if (path_obj.has_extension()) {
+ // Fetch the extension from path object and return
+ return path_obj.extension().string();
+ }
+ // In case of no extension return empty string
+ return {};
+}
+
+std::string GpgFrontend::get_only_file_name_with_path(const std::string& path) {
+ // Create a path object from given string
+ std::filesystem::path path_obj(path);
+ // Check if file name in the path object has extension
+ if (path_obj.has_filename()) {
+ // Fetch the extension from path object and return
+ return (path_obj.parent_path() / path_obj.stem()).string();
+ }
+ // In case of no extension return empty string
+ return {};
+}
+
+int GpgFrontend::text_is_signed(GpgFrontend::BypeArrayRef text) {
+ using boost::algorithm::ends_with;
+ using boost::algorithm::starts_with;
+
+ auto trim_text = trim(text);
+ if (starts_with(trim_text, GpgConstants::PGP_SIGNED_BEGIN) &&
+ ends_with(trim_text, GpgConstants::PGP_SIGNED_END))
+ return 2;
+ else if (text.find(GpgConstants::PGP_SIGNED_BEGIN) != std::string::npos &&
+ text.find(GpgConstants::PGP_SIGNED_END) != std::string::npos)
+ return 1;
+ else
+ return 0;
+}
+
+GpgFrontend::GpgEncrResult GpgFrontend::_new_result(
+ gpgme_encrypt_result_t&& result) {
+ gpgme_result_ref(result);
+ return {result, _result_ref_deletor()};
+}
+
+GpgFrontend::GpgDecrResult GpgFrontend::_new_result(
+ gpgme_decrypt_result_t&& result) {
+ gpgme_result_ref(result);
+ return {result, _result_ref_deletor()};
+}
+
+GpgFrontend::GpgSignResult GpgFrontend::_new_result(
+ gpgme_sign_result_t&& result) {
+ gpgme_result_ref(result);
+ return {result, _result_ref_deletor()};
+}
+
+GpgFrontend::GpgVerifyResult GpgFrontend::_new_result(
+ gpgme_verify_result_t&& result) {
+ gpgme_result_ref(result);
+ return {result, _result_ref_deletor()};
+}
+
+GpgFrontend::GpgGenKeyResult GpgFrontend::_new_result(
+ gpgme_genkey_result_t&& result) {
+ gpgme_result_ref(result);
+ return {result, _result_ref_deletor()};
+}
+
+void GpgFrontend::_result_ref_deletor::operator()(void* _result) {
+ DLOG(INFO) << _("Called") << _result;
+ if (_result != nullptr) gpgme_result_unref(_result);
+}
diff --git a/src/core/GpgConstants.h b/src/core/GpgConstants.h
new file mode 100644
index 00000000..8c6977ac
--- /dev/null
+++ b/src/core/GpgConstants.h
@@ -0,0 +1,220 @@
+/**
+ * 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 GPG_CONSTANTS_H
+#define GPG_CONSTANTS_H
+
+#include <gpgme.h>
+
+#include <cassert>
+#include <functional>
+#include <memory>
+#include <string>
+
+#include "GpgFrontend.h"
+
+const int RESTART_CODE = 1000; ///<
+
+namespace GpgFrontend {
+
+using ByteArray = std::string; ///<
+using ByteArrayPtr = std::unique_ptr<ByteArray>; ///<
+using StdBypeArrayPtr = std::unique_ptr<ByteArray>; ///<
+using BypeArrayRef = ByteArray&; ///<
+using BypeArrayConstRef = const ByteArray&; ///<
+using StringArgsPtr = std::unique_ptr<std::vector<std::string>>; ///<
+using StringArgsRef = std::vector<std::string>&; ///<
+
+using GpgError = gpgme_error_t;
+
+/**
+ * @brief Result Deleter
+ *
+ */
+struct _result_ref_deletor {
+ void operator()(void* _result);
+};
+
+using GpgEncrResult = std::shared_ptr<struct _gpgme_op_encrypt_result>; ///<
+using GpgDecrResult = std::shared_ptr<struct _gpgme_op_decrypt_result>; ///<
+using GpgSignResult = std::shared_ptr<struct _gpgme_op_sign_result>; ///<
+using GpgVerifyResult = std::shared_ptr<struct _gpgme_op_verify_result>; ///<
+using GpgGenKeyResult = std::shared_ptr<struct _gpgme_op_genkey_result>; ///<
+
+// Convert from gpgme_xxx_result to GpgXXXResult
+
+/**
+ * @brief
+ *
+ * @param result
+ * @return GpgEncrResult
+ */
+GpgEncrResult _new_result(gpgme_encrypt_result_t&& result);
+
+/**
+ * @brief
+ *
+ * @param result
+ * @return GpgDecrResult
+ */
+GpgDecrResult _new_result(gpgme_decrypt_result_t&& result);
+
+/**
+ * @brief
+ *
+ * @param result
+ * @return GpgSignResult
+ */
+GpgSignResult _new_result(gpgme_sign_result_t&& result);
+
+/**
+ * @brief
+ *
+ * @param result
+ * @return GpgVerifyResult
+ */
+GpgVerifyResult _new_result(gpgme_verify_result_t&& result);
+
+/**
+ * @brief
+ *
+ * @param result
+ * @return GpgGenKeyResult
+ */
+GpgGenKeyResult _new_result(gpgme_genkey_result_t&& result);
+
+// Error Info Printer
+
+/**
+ * @brief
+ *
+ * @param err
+ * @return GpgError
+ */
+GpgError check_gpg_error(GpgError err);
+
+/**
+ * @brief
+ *
+ * @param gpgmeError
+ * @param comment
+ * @return GpgError
+ */
+GpgError check_gpg_error(GpgError gpgmeError, const std::string& comment);
+
+/**
+ * @brief
+ *
+ * @param err
+ * @param predict
+ * @return gpg_err_code_t
+ */
+gpg_err_code_t check_gpg_error_2_err_code(
+ gpgme_error_t err, gpgme_error_t predict = GPG_ERR_NO_ERROR);
+
+// Fingerprint
+
+/**
+ * @brief
+ *
+ * @param fingerprint
+ * @return std::string
+ */
+std::string beautify_fingerprint(BypeArrayConstRef fingerprint);
+
+// File Operation
+
+/**
+ * @brief
+ *
+ * @param path
+ * @return std::string
+ */
+std::string read_all_data_in_file(const std::string& path);
+
+/**
+ * @brief
+ *
+ * @param path
+ * @param out_buffer
+ * @return true
+ * @return false
+ */
+bool write_buffer_to_file(const std::string& path,
+ const std::string& out_buffer);
+
+/**
+ * @brief Get the file extension object
+ *
+ * @param path
+ * @return std::string
+ */
+std::string get_file_extension(const std::string& path);
+
+/**
+ * @brief Get the only file name with path object
+ *
+ * @param path
+ * @return std::string
+ */
+std::string get_only_file_name_with_path(const std::string& path);
+
+// Check
+
+/**
+ * @brief
+ *
+ * @param text
+ * @return int
+ */
+int text_is_signed(BypeArrayRef text);
+
+// Channels
+const int GPGFRONTEND_DEFAULT_CHANNEL = 0; ///<
+const int GPGFRONTEND_NON_ASCII_CHANNEL = 2; ///<
+
+/**
+ * @brief
+ *
+ */
+class GpgConstants {
+ public:
+ static const char* PGP_CRYPT_BEGIN; ///<
+ static const char* PGP_CRYPT_END; ///<
+ static const char* PGP_SIGNED_BEGIN; ///<
+ static const char* PGP_SIGNED_END; ///<
+ static const char* PGP_SIGNATURE_BEGIN; ///<
+ static const char* PGP_SIGNATURE_END; ///<
+ static const char* PGP_PUBLIC_KEY_BEGIN; ///<
+ static const char* PGP_PRIVATE_KEY_BEGIN; ///<
+ static const char* GPG_FRONTEND_SHORT_CRYPTO_HEAD; ///<
+};
+
+} // namespace GpgFrontend
+
+#endif // GPG_CONSTANTS_H
diff --git a/src/core/GpgContext.cpp b/src/core/GpgContext.cpp
new file mode 100644
index 00000000..1897202f
--- /dev/null
+++ b/src/core/GpgContext.cpp
@@ -0,0 +1,224 @@
+/**
+ * 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 "core/GpgContext.h"
+
+#include <gpg-error.h>
+#include <gpgme.h>
+
+#include <functional>
+#include <string>
+#include <utility>
+
+#include "GpgConstants.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+namespace GpgFrontend {
+
+/**
+ * Constructor
+ * Set up gpgme-context, set paths to app-run path
+ */
+GpgContext::GpgContext(const GpgContextInitArgs &args) : args_(args) {
+ static bool _first = true;
+
+ if (_first) {
+ /* Initialize the locale environment. */
+ LOG(INFO) << "locale" << setlocale(LC_CTYPE, nullptr);
+ info_.GpgMEVersion = gpgme_check_version(nullptr);
+ gpgme_set_locale(nullptr, LC_CTYPE, setlocale(LC_CTYPE, nullptr));
+#ifdef LC_MESSAGES
+ gpgme_set_locale(nullptr, LC_MESSAGES, setlocale(LC_MESSAGES, nullptr));
+#endif
+ _first = false;
+ }
+
+ gpgme_ctx_t _p_ctx;
+ check_gpg_error(gpgme_new(&_p_ctx));
+ _ctx_ref = CtxRefHandler(_p_ctx);
+
+ if (args.gpg_alone) {
+ info_.AppPath = args.gpg_path;
+ auto err = gpgme_ctx_set_engine_info(_ctx_ref.get(), GPGME_PROTOCOL_OpenPGP,
+ info_.AppPath.c_str(),
+ info_.DatabasePath.c_str());
+ assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR);
+ }
+
+ auto engine_info = gpgme_ctx_get_engine_info(*this);
+ // Check ENV before running
+ bool check_passed = false, find_openpgp = false, find_gpgconf = false,
+ find_cms = false;
+
+ while (engine_info != nullptr) {
+ if (!strcmp(engine_info->version, "1.0.0")) {
+ engine_info = engine_info->next;
+ continue;
+ }
+
+ DLOG(INFO) << gpgme_get_protocol_name(engine_info->protocol)
+ << std::string(engine_info->file_name == nullptr
+ ? "null"
+ : engine_info->file_name)
+ << std::string(engine_info->home_dir == nullptr
+ ? "null"
+ : engine_info->home_dir);
+
+ switch (engine_info->protocol) {
+ case GPGME_PROTOCOL_OpenPGP:
+ find_openpgp = true;
+ info_.AppPath = engine_info->file_name;
+ info_.GnupgVersion = engine_info->version;
+ break;
+ case GPGME_PROTOCOL_CMS:
+ find_cms = true;
+ info_.CMSPath = engine_info->file_name;
+ break;
+ case GPGME_PROTOCOL_GPGCONF:
+ find_gpgconf = true;
+ info_.GpgConfPath = engine_info->file_name;
+ break;
+ case GPGME_PROTOCOL_ASSUAN:
+ break;
+ case GPGME_PROTOCOL_G13:
+ break;
+ case GPGME_PROTOCOL_UISERVER:
+ break;
+ case GPGME_PROTOCOL_SPAWN:
+ break;
+ case GPGME_PROTOCOL_DEFAULT:
+ break;
+ case GPGME_PROTOCOL_UNKNOWN:
+ break;
+ }
+ engine_info = engine_info->next;
+ }
+
+ // conditional check
+ if ((info_.GnupgVersion >= "2.0.0" && find_gpgconf && find_openpgp &&
+ find_cms) ||
+ (info_.GnupgVersion > "1.0.0" && find_gpgconf))
+ check_passed = true;
+
+ if (!check_passed) {
+ this->good_ = false;
+ LOG(ERROR) << "Env check failed";
+ return;
+ } else {
+ DLOG(INFO) << "gnupg version" << info_.GnupgVersion;
+ init_ctx();
+ good_ = true;
+ }
+}
+
+void GpgContext::init_ctx() {
+ // Set Independent Database
+ if (info_.GnupgVersion <= "2.0.0" && args_.independent_database) {
+ info_.DatabasePath = args_.db_path;
+ DLOG(INFO) << "custom key db path" << info_.DatabasePath;
+ auto err = gpgme_ctx_set_engine_info(_ctx_ref.get(), GPGME_PROTOCOL_OpenPGP,
+ info_.AppPath.c_str(),
+ info_.DatabasePath.c_str());
+ assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR);
+ } else {
+ info_.DatabasePath = "default";
+ }
+
+ if (args_.ascii) {
+ /** Setting the output type must be done at the beginning */
+ /** think this means ascii-armor --> ? */
+ gpgme_set_armor(*this, 1);
+ } else {
+ /** Setting the output type must be done at the beginning */
+ /** think this means ascii-armor --> ? */
+ gpgme_set_armor(*this, 0);
+ }
+
+ // Speed up loading process
+ gpgme_set_offline(*this, 1);
+
+ if (info_.GnupgVersion >= "2.0.0") {
+ check_gpg_error(gpgme_set_keylist_mode(
+ *this, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_WITH_SECRET |
+ GPGME_KEYLIST_MODE_SIGS | GPGME_KEYLIST_MODE_SIG_NOTATIONS |
+ GPGME_KEYLIST_MODE_WITH_TOFU));
+ } else {
+ check_gpg_error(gpgme_set_keylist_mode(
+ *this, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_SIGS |
+ GPGME_KEYLIST_MODE_SIG_NOTATIONS |
+ GPGME_KEYLIST_MODE_WITH_TOFU));
+ }
+
+ // for unit test
+ if (args_.test_mode) {
+ LOG(INFO) << "test mode";
+ if (info_.GnupgVersion >= "2.1.0") SetPassphraseCb(test_passphrase_cb);
+ gpgme_set_status_cb(*this, test_status_cb, nullptr);
+ }
+}
+
+bool GpgContext::good() const { return good_; }
+
+void GpgContext::SetPassphraseCb(gpgme_passphrase_cb_t cb) const {
+ if (info_.GnupgVersion >= "2.1.0") {
+ if (gpgme_get_pinentry_mode(*this) != GPGME_PINENTRY_MODE_LOOPBACK) {
+ gpgme_set_pinentry_mode(*this, GPGME_PINENTRY_MODE_LOOPBACK);
+ }
+ gpgme_set_passphrase_cb(*this, cb, nullptr);
+ } else {
+ LOG(ERROR) << "Not supported for gnupg version" << info_.GnupgVersion;
+ }
+}
+
+gpgme_error_t GpgContext::test_passphrase_cb(void *opaque, const char *uid_hint,
+ const char *passphrase_info,
+ int last_was_bad, int fd) {
+ size_t res;
+ std::string pass = "abcdefg\n";
+ auto pass_len = pass.size();
+
+ size_t off = 0;
+
+ do {
+ res = gpgme_io_write(fd, &pass[off], pass_len - off);
+ if (res > 0) off += res;
+ } while (res > 0 && off != pass_len);
+
+ return off == pass_len ? 0 : gpgme_error_from_errno(errno);
+}
+
+gpgme_error_t GpgContext::test_status_cb(void *hook, const char *keyword,
+ const char *args) {
+ LOG(INFO) << "keyword" << keyword;
+ return GPG_ERR_NO_ERROR;
+}
+
+} // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/GpgContext.h b/src/core/GpgContext.h
new file mode 100644
index 00000000..7de6bcad
--- /dev/null
+++ b/src/core/GpgContext.h
@@ -0,0 +1,164 @@
+/**
+ * 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 __SGPGMEPP_CONTEXT_H__
+#define __SGPGMEPP_CONTEXT_H__
+
+#include "GpgConstants.h"
+#include "GpgFunctionObject.h"
+#include "GpgInfo.h"
+#include "GpgModel.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief
+ *
+ */
+struct GpgContextInitArgs {
+ // make no sense for gpg2
+ bool independent_database = false; ///<
+ std::string db_path = {};
+ bool gpg_alone = false;
+ std::string gpg_path = {};
+ bool test_mode = false;
+ bool ascii = true;
+
+ GpgContextInitArgs() = default;
+};
+
+/**
+ * @brief
+ *
+ */
+class GpgContext : public SingletonFunctionObject<GpgContext> {
+ public:
+ /**
+ * @brief Construct a new Gpg Context object
+ *
+ * @param args
+ */
+ explicit GpgContext(const GpgContextInitArgs& args = {});
+
+ /**
+ * @brief Construct a new Gpg Context object
+ *
+ * @param channel
+ */
+ explicit GpgContext(int channel)
+ : SingletonFunctionObject<GpgContext>(channel) {}
+
+ /**
+ * @brief Destroy the Gpg Context object
+ *
+ */
+ ~GpgContext() override = default;
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool good() const;
+
+ /**
+ * @brief Get the Info object
+ *
+ * @return const GpgInfo&
+ */
+ [[nodiscard]] const GpgInfo& GetInfo() const { return info_; }
+
+ /**
+ * @brief
+ *
+ * @return gpgme_ctx_t
+ */
+ operator gpgme_ctx_t() const { return _ctx_ref.get(); }
+
+ private:
+ GpgInfo info_; ///<
+ GpgContextInitArgs args_; ///<
+
+ /**
+ * @brief
+ *
+ */
+ void init_ctx();
+
+ /**
+ * @brief
+ *
+ */
+ struct _ctx_ref_deleter {
+ void operator()(gpgme_ctx_t _ctx) {
+ if (_ctx != nullptr) gpgme_release(_ctx);
+ }
+ };
+
+ using CtxRefHandler =
+ std::unique_ptr<struct gpgme_context, _ctx_ref_deleter>; ///<
+ CtxRefHandler _ctx_ref = nullptr; ///<
+ bool good_ = true; ///<
+
+ public:
+ /**
+ * @brief
+ *
+ * @param opaque
+ * @param uid_hint
+ * @param passphrase_info
+ * @param last_was_bad
+ * @param fd
+ * @return gpgme_error_t
+ */
+ static gpgme_error_t test_passphrase_cb(void* opaque, const char* uid_hint,
+ const char* passphrase_info,
+ int last_was_bad, int fd);
+
+ /**
+ * @brief
+ *
+ * @param hook
+ * @param keyword
+ * @param args
+ * @return gpgme_error_t
+ */
+ static gpgme_error_t test_status_cb(void* hook, const char* keyword,
+ const char* args);
+
+ /**
+ * @brief Set the Passphrase Cb object
+ *
+ * @param func
+ */
+ void SetPassphraseCb(gpgme_passphrase_cb_t func) const;
+};
+} // namespace GpgFrontend
+
+#endif // __SGPGMEPP_CONTEXT_H__
diff --git a/src/core/GpgCoreInit.cpp b/src/core/GpgCoreInit.cpp
new file mode 100644
index 00000000..6d9963d6
--- /dev/null
+++ b/src/core/GpgCoreInit.cpp
@@ -0,0 +1,56 @@
+/**
+ * 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 "GpgCoreInit.h"
+
+#include "GpgContext.h"
+
+void GpgFrontend::init_gpgfrontend_core() {
+ GpgFrontend::GpgContext::CreateInstance(
+ GPGFRONTEND_DEFAULT_CHANNEL,
+ [&]() -> std::unique_ptr<GpgFrontend::GpgContext> {
+ GpgFrontend::GpgContextInitArgs args;
+ return std::make_unique<GpgFrontend::GpgContext>(args);
+ });
+
+ GpgFrontend::GpgContext::CreateInstance(
+ GPGFRONTEND_NON_ASCII_CHANNEL,
+ [&]() -> std::unique_ptr<GpgFrontend::GpgContext> {
+ GpgFrontend::GpgContextInitArgs args;
+ args.ascii = false;
+ return std::make_unique<GpgFrontend::GpgContext>(args);
+ });
+}
+
+void GpgFrontend::new_default_settings_channel(int channel) {
+ GpgFrontend::GpgContext::CreateInstance(
+ channel, [&]() -> std::unique_ptr<GpgFrontend::GpgContext> {
+ GpgFrontend::GpgContextInitArgs args;
+ return std::make_unique<GpgFrontend::GpgContext>(args);
+ });
+} \ No newline at end of file
diff --git a/src/core/GpgCoreInit.h b/src/core/GpgCoreInit.h
new file mode 100644
index 00000000..5ac804da
--- /dev/null
+++ b/src/core/GpgCoreInit.h
@@ -0,0 +1,52 @@
+/**
+ * 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_GPGCOREINIT_H
+#define GPGFRONTEND_GPGCOREINIT_H
+
+#include "GpgConstants.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief
+ *
+ */
+void init_gpgfrontend_core();
+
+/**
+ * @brief
+ *
+ * @param channel
+ */
+void new_default_settings_channel(
+ int channel = GpgFrontend::GPGFRONTEND_DEFAULT_CHANNEL);
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_GPGCOREINIT_H
diff --git a/src/core/GpgFrontendCore.h b/src/core/GpgFrontendCore.h
new file mode 100644
index 00000000..5931695d
--- /dev/null
+++ b/src/core/GpgFrontendCore.h
@@ -0,0 +1,61 @@
+/**
+* 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_GPGFRONTENDCORE_H
+#define GPGFRONTEND_GPGFRONTENDCORE_H
+
+#include "GpgFrontend.h"
+
+// std includes
+#include <filesystem>
+
+// boost includes
+#include <boost/format.hpp>
+
+// Qt includes
+#include <QtCore>
+
+// vmime includes
+#define VMIME_STATIC
+#undef VMIME_HAVE_MLANG
+#include <vmime/vmime.hpp>
+
+// libconfig includes
+#undef LIBCONFIGXX_STATIC
+#define LIBCONFIGXX_STATIC
+#include <libconfig.h++>
+
+
+// libarchive includes
+#include <libarchive/libarchive/archive.h>
+#include <libarchive/libarchive/archive_entry.h>
+
+#include "core/GpgModel.h"
+
+
+#endif // GPGFRONTEND_GPGFRONTENDCORE_H
diff --git a/src/core/GpgFunctionObject.h b/src/core/GpgFunctionObject.h
new file mode 100644
index 00000000..391b1585
--- /dev/null
+++ b/src/core/GpgFunctionObject.h
@@ -0,0 +1,247 @@
+/**
+ * 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_ZH_CN_TS_FUNCTIONOBJECT_H
+#define GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H
+
+#include <map>
+#include <memory>
+#include <mutex>
+#include <shared_mutex>
+#include <stdexcept>
+#include <string>
+
+#include "GpgConstants.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief
+ *
+ * @tparam T
+ */
+template <typename T>
+class SingletonFunctionObject {
+ public:
+ /**
+ * @brief Get the Instance object
+ *
+ * @param channel
+ * @return T&
+ */
+ static T& GetInstance(
+ int channel = GpgFrontend::GPGFRONTEND_DEFAULT_CHANNEL) {
+ static_assert(std::is_base_of<SingletonFunctionObject<T>, T>::value,
+ "T not derived from SingletonFunctionObject<T>");
+
+ auto _p_pbj = find_object_in_channel(channel);
+ if (_p_pbj == nullptr)
+ return *set_object_in_channel(channel, std::make_unique<T>(channel));
+ else
+ return *_p_pbj;
+ }
+
+ /**
+ * @brief Create a Instance object
+ *
+ * @param channel
+ * @param factory
+ * @return T&
+ */
+ static T& CreateInstance(int channel,
+ std::function<std::unique_ptr<T>(void)> factory) {
+ static_assert(std::is_base_of<SingletonFunctionObject<T>, T>::value,
+ "T not derived from SingletonFunctionObject<T>");
+
+ auto _p_pbj = find_object_in_channel(channel);
+ if (_p_pbj == nullptr)
+ return *set_object_in_channel(channel, std::move(factory()));
+ else
+ return *_p_pbj;
+ }
+
+ /**
+ * @brief Create a Instance object
+ *
+ * @param channel
+ * @param p_obj
+ * @return T&
+ */
+ static T& CreateInstance(int channel, std::unique_ptr<T> p_obj = nullptr) {
+ static_assert(std::is_base_of<SingletonFunctionObject<T>, T>::value,
+ "T not derived from SingletonFunctionObject<T>");
+
+ auto _p_pbj = find_object_in_channel(channel);
+ if (_p_pbj == nullptr)
+ return *set_object_in_channel(channel, std::move(p_obj));
+ else
+ return *_p_pbj;
+ }
+
+ /**
+ * @brief
+ *
+ * @param channel
+ * @return T&
+ */
+ static T& ReleaseChannel(int channel) {
+ decltype(_instances_map.end()) _it;
+ {
+ std::shared_lock lock(_instances_mutex);
+ _it = _instances_map.find(channel);
+ }
+ if (_it != _instances_map.end()) _instances_map.erase(_it);
+ DLOG(INFO) << "channel" << channel << "released";
+ }
+
+ /**
+ * @brief Get the Default Channel object
+ *
+ * @return int
+ */
+ static int GetDefaultChannel() { return _default_channel; }
+
+ /**
+ * @brief Get the Channel object
+ *
+ * @return int
+ */
+ [[nodiscard]] int GetChannel() const { return channel_; }
+
+ /**
+ * @brief Construct a new Singleton Function Object object
+ *
+ */
+ SingletonFunctionObject(T&&) = delete;
+
+ /**
+ * @brief Construct a new Singleton Function Object object
+ *
+ */
+ SingletonFunctionObject(const T&) = delete;
+
+ /**
+ * @brief
+ *
+ */
+ void operator=(const T&) = delete;
+
+ protected:
+ /**
+ * @brief Construct a new Singleton Function Object object
+ *
+ */
+ SingletonFunctionObject() = default;
+
+ /**
+ * @brief Construct a new Singleton Function Object object
+ *
+ * @param channel
+ */
+ explicit SingletonFunctionObject(int channel) : channel_(channel) {}
+
+ /**
+ * @brief Destroy the Singleton Function Object object
+ *
+ */
+ virtual ~SingletonFunctionObject() = default;
+
+ /**
+ * @brief Set the Channel object
+ *
+ * @param channel
+ */
+ void SetChannel(int channel) { this->channel_ = channel; }
+
+ private:
+ int channel_ = _default_channel; ///<
+ static int _default_channel; ///<
+ static std::mutex _instance_mutex; ///<
+ static std::shared_mutex _instances_mutex; ///<
+ static std::unique_ptr<T> _instance; ///<
+ static std::map<int, std::unique_ptr<T>> _instances_map; ///<
+
+ /**
+ * @brief
+ *
+ * @param channel
+ * @return T*
+ */
+ static T* find_object_in_channel(int channel) {
+ // read _instances_map
+ decltype(_instances_map.end()) _it;
+ {
+ std::shared_lock lock(_instances_mutex);
+ _it = _instances_map.find(channel);
+ if (_it == _instances_map.end())
+ return nullptr;
+ else
+ return _it->second.get();
+ }
+ }
+
+ /**
+ * @brief Set the object in channel object
+ *
+ * @param channel
+ * @param p_obj
+ * @return T*
+ */
+ static T* set_object_in_channel(int channel, std::unique_ptr<T> p_obj) {
+ {
+ if (p_obj == nullptr) p_obj = std::make_unique<T>();
+ T* obj = p_obj.get();
+ obj->SetChannel(channel);
+ {
+ std::unique_lock lock(_instances_mutex);
+ _instances_map.insert({channel, std::move(p_obj)});
+ }
+ return obj;
+ }
+ }
+};
+
+template <typename T>
+int SingletonFunctionObject<T>::_default_channel =
+ GpgFrontend::GPGFRONTEND_DEFAULT_CHANNEL;
+
+template <typename T>
+std::mutex SingletonFunctionObject<T>::_instance_mutex;
+
+template <typename T>
+std::shared_mutex SingletonFunctionObject<T>::_instances_mutex;
+
+template <typename T>
+std::unique_ptr<T> SingletonFunctionObject<T>::_instance = nullptr;
+
+template <typename T>
+std::map<int, std::unique_ptr<T>> SingletonFunctionObject<T>::_instances_map;
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H
diff --git a/src/core/GpgGenKeyInfo.cpp b/src/core/GpgGenKeyInfo.cpp
new file mode 100644
index 00000000..6ca83c96
--- /dev/null
+++ b/src/core/GpgGenKeyInfo.cpp
@@ -0,0 +1,225 @@
+/**
+ * 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 "core/GpgGenKeyInfo.h"
+
+#include <boost/date_time/gregorian/greg_date.hpp>
+#include <boost/date_time/gregorian/greg_duration.hpp>
+#include <boost/date_time/gregorian/gregorian_types.hpp>
+#include <string>
+#include <vector>
+
+void GpgFrontend::GenKeyInfo::SetAlgo(const std::string &m_algo) {
+ LOG(INFO) << "set algo" << m_algo;
+ // Check algo if supported
+ std::string algo_args = std::string(m_algo);
+ boost::algorithm::to_upper(algo_args);
+ if (standalone_) {
+ if (!subkey_) {
+ auto support_algo = GetSupportedKeyAlgoStandalone();
+ auto it = std::find(support_algo.begin(), support_algo.end(), algo_args);
+ // Algo Not Supported
+ if (it == support_algo.end()) return;
+ } else {
+ auto support_algo = GetSupportedSubkeyAlgoStandalone();
+ auto it = std::find(support_algo.begin(), support_algo.end(), algo_args);
+ // Algo Not Supported
+ if (it == support_algo.end()) return;
+ }
+ } else {
+ if (!subkey_) {
+ auto support_algo = GetSupportedKeyAlgo();
+ auto it = std::find(support_algo.begin(), support_algo.end(), algo_args);
+ // Algo Not Supported
+ if (it == support_algo.end()) return;
+ } else {
+ auto support_algo = GetSupportedSubkeyAlgo();
+ auto it = std::find(support_algo.begin(), support_algo.end(), algo_args);
+ // Algo Not Supported
+ if (it == support_algo.end()) return;
+ }
+ }
+
+ // reset all options
+ reset_options();
+
+ if (!this->subkey_) {
+ this->SetAllowCertification(true);
+ } else {
+ this->SetAllowCertification(false);
+ }
+
+ this->allow_change_certification_ = false;
+
+ if (!standalone_) boost::algorithm::to_lower(algo_args);
+
+ if (algo_args == "rsa") {
+ /**
+ * RSA is the world’s premier asymmetric cryptographic algorithm,
+ * and is built on the difficulty of factoring extremely large composites.
+ * GnuPG supports RSA with key sizes of between 1024 and 4096 bits.
+ */
+ suggest_min_key_size_ = 1024;
+ suggest_max_key_size_ = 4096;
+ suggest_size_addition_step_ = 1024;
+ SetKeyLength(2048);
+
+ } else if (algo_args == "dsa") {
+ /**
+ * Algorithm (DSA) as a government standard for digital signatures.
+ * Originally, it supported key lengths between 512 and 1024 bits.
+ * Recently, NIST has declared 512-bit keys obsolete:
+ * now, DSA is available in 1024, 2048 and 3072-bit lengths.
+ */
+ SetAllowEncryption(false);
+ allow_change_encryption_ = false;
+
+ suggest_min_key_size_ = 1024;
+ suggest_max_key_size_ = 3072;
+ suggest_size_addition_step_ = 1024;
+ SetKeyLength(2048);
+
+ } else if (algo_args == "ed25519") {
+ /**
+ * GnuPG supports the Elgamal asymmetric encryption algorithm in key lengths
+ * ranging from 1024 to 4096 bits.
+ */
+ SetAllowEncryption(false);
+ allow_change_encryption_ = false;
+
+ suggest_min_key_size_ = -1;
+ suggest_max_key_size_ = -1;
+ suggest_size_addition_step_ = -1;
+ SetKeyLength(-1);
+ } else if (algo_args == "elg") {
+ /**
+ * GnuPG supports the Elgamal asymmetric encryption algorithm in key lengths
+ * ranging from 1024 to 4096 bits.
+ */
+ SetAllowAuthentication(false);
+ allow_change_authentication_ = false;
+
+ SetAllowSigning(false);
+ allow_change_signing_ = false;
+
+ suggest_min_key_size_ = 1024;
+ suggest_max_key_size_ = 4096;
+ suggest_size_addition_step_ = 1024;
+ SetKeyLength(2048);
+ }
+ this->algo_ = algo_args;
+}
+
+void GpgFrontend::GenKeyInfo::reset_options() {
+ allow_change_encryption_ = true;
+ SetAllowEncryption(true);
+
+ allow_change_certification_ = true;
+ SetAllowCertification(true);
+
+ allow_change_signing_ = true;
+ SetAllowSigning(true);
+
+ allow_change_authentication_ = true;
+ SetAllowAuthentication(true);
+
+ passphrase_.clear();
+}
+
+std::string GpgFrontend::GenKeyInfo::GetKeySizeStr() const {
+ if (key_size_ > 0) {
+ return std::to_string(key_size_);
+ } else {
+ return {};
+ }
+}
+
+void GpgFrontend::GenKeyInfo::SetKeyLength(int m_key_size) {
+ if (m_key_size < suggest_min_key_size_ ||
+ m_key_size > suggest_max_key_size_) {
+ return;
+ }
+ GenKeyInfo::key_size_ = m_key_size;
+}
+
+void GpgFrontend::GenKeyInfo::SetExpireTime(
+ const boost::posix_time::ptime &m_expired) {
+ using namespace boost::gregorian;
+ if (!IsNonExpired()) {
+ GenKeyInfo::expired_ = m_expired;
+ }
+}
+
+void GpgFrontend::GenKeyInfo::SetNonExpired(bool m_non_expired) {
+ using namespace boost::posix_time;
+ if (!m_non_expired) this->expired_ = from_time_t(0);
+ GenKeyInfo::non_expired_ = m_non_expired;
+}
+
+void GpgFrontend::GenKeyInfo::SetAllowEncryption(bool m_allow_encryption) {
+ if (allow_change_encryption_)
+ GenKeyInfo::allow_encryption_ = m_allow_encryption;
+}
+
+void GpgFrontend::GenKeyInfo::SetAllowCertification(
+ bool m_allow_certification) {
+ if (allow_change_certification_)
+ GenKeyInfo::allow_certification_ = m_allow_certification;
+}
+
+GpgFrontend::GenKeyInfo::GenKeyInfo(bool m_is_sub_key, bool m_standalone)
+ : standalone_(m_standalone), subkey_(m_is_sub_key) {
+ SetAlgo("rsa");
+}
+
+const std::vector<std::string> &GpgFrontend::GenKeyInfo::GetSupportedKeyAlgo() {
+ static const std::vector<std::string> support_key_algo = {"RSA", "DSA",
+ "ED25519"};
+ return support_key_algo;
+}
+
+const std::vector<std::string>
+ &GpgFrontend::GenKeyInfo::GetSupportedSubkeyAlgo() {
+ static const std::vector<std::string> support_subkey_algo = {"RSA", "DSA",
+ "ED25519"};
+ return support_subkey_algo;
+}
+
+const std::vector<std::string>
+ &GpgFrontend::GenKeyInfo::GetSupportedKeyAlgoStandalone() {
+ static const std::vector<std::string> support_subkey_algo_standalone = {
+ "RSA", "DSA"};
+ return support_subkey_algo_standalone;
+}
+
+const std::vector<std::string>
+ &GpgFrontend::GenKeyInfo::GetSupportedSubkeyAlgoStandalone() {
+ static const std::vector<std::string> support_subkey_algo_standalone = {
+ "RSA", "DSA", "ELG-E"};
+ return support_subkey_algo_standalone;
+}
diff --git a/src/core/GpgGenKeyInfo.h b/src/core/GpgGenKeyInfo.h
new file mode 100644
index 00000000..59ced710
--- /dev/null
+++ b/src/core/GpgGenKeyInfo.h
@@ -0,0 +1,435 @@
+/**
+ * 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_GPGGENKEYINFO_H
+#define GPGFRONTEND_GPGGENKEYINFO_H
+
+#include <boost/date_time.hpp>
+#include <boost/date_time/gregorian/greg_duration_types.hpp>
+#include <boost/format.hpp>
+#include <string>
+#include <vector>
+
+#include "GpgFrontend.h"
+
+namespace GpgFrontend {
+
+class GenKeyInfo {
+ bool standalone_ = false; ///<
+ bool subkey_ = false; ///<
+ std::string name_; ///<
+ std::string email_; ///<
+ std::string comment_; ///<
+
+ std::string algo_; ///<
+ int key_size_ = 2048;
+ boost::posix_time::ptime expired_ =
+ boost::posix_time::second_clock::local_time() +
+ boost::gregorian::years(2); ///<
+ bool non_expired_ = false; ///<
+
+ bool no_passphrase_ = false; ///<
+ bool allow_no_pass_phrase_ = true; ///<
+
+ int suggest_max_key_size_ = 4096; ///<
+ int suggest_size_addition_step_ = 1024; ///<
+ int suggest_min_key_size_ = 1024; ///<
+
+ std::string passphrase_; ///<
+
+ public:
+ /**
+ * @brief Get the Supported Key Algo object
+ *
+ * @return const std::vector<std::string>&
+ */
+ static const std::vector<std::string> &GetSupportedKeyAlgo();
+
+ /**
+ * @brief Get the Supported Subkey Algo object
+ *
+ * @return const std::vector<std::string>&
+ */
+ static const std::vector<std::string> &GetSupportedSubkeyAlgo();
+
+ /**
+ * @brief Get the Supported Key Algo Standalone object
+ *
+ * @return const std::vector<std::string>&
+ */
+ static const std::vector<std::string> &GetSupportedKeyAlgoStandalone();
+
+ /**
+ * @brief Get the Supported Subkey Algo Standalone object
+ *
+ * @return const std::vector<std::string>&
+ */
+ static const std::vector<std::string> &GetSupportedSubkeyAlgoStandalone();
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsSubKey() const { return subkey_; }
+
+ /**
+ * @brief Set the Is Sub Key object
+ *
+ * @param m_sub_key
+ */
+ void SetIsSubKey(bool m_sub_key) { GenKeyInfo::subkey_ = m_sub_key; }
+
+ /**
+ * @brief Get the Userid object
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetUserid() const {
+ auto uid_format = boost::format("%1%(%2%)<%3%>") % this->name_ %
+ this->comment_ % this->email_;
+ return uid_format.str();
+ }
+
+ /**
+ * @brief Set the Name object
+ *
+ * @param m_name
+ */
+ void SetName(const std::string &m_name) { this->name_ = m_name; }
+
+ /**
+ * @brief Set the Email object
+ *
+ * @param m_email
+ */
+ void SetEmail(const std::string &m_email) { this->email_ = m_email; }
+
+ /**
+ * @brief Set the Comment object
+ *
+ * @param m_comment
+ */
+ void SetComment(const std::string &m_comment) { this->comment_ = m_comment; }
+
+ /**
+ * @brief Get the Name object
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetName() const { return name_; }
+
+ /**
+ * @brief Get the Email object
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetEmail() const { return email_; }
+
+ /**
+ * @brief Get the Comment object
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetComment() const { return comment_; }
+
+ /**
+ * @brief Get the Algo object
+ *
+ * @return const std::string&
+ */
+ [[nodiscard]] const std::string &GetAlgo() const { return algo_; }
+
+ /**
+ * @brief Set the Algo object
+ *
+ * @param m_algo
+ */
+ void SetAlgo(const std::string &m_algo);
+
+ /**
+ * @brief Get the Key Size Str object
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetKeySizeStr() const;
+
+ /**
+ * @brief Get the Key Size object
+ *
+ * @return int
+ */
+ [[nodiscard]] int GetKeyLength() const { return key_size_; }
+
+ /**
+ * @brief Set the Key Size object
+ *
+ * @param m_key_size
+ */
+ void SetKeyLength(int m_key_size);
+
+ /**
+ * @brief Get the Expired object
+ *
+ * @return const boost::posix_time::ptime&
+ */
+ [[nodiscard]] const boost::posix_time::ptime &GetExpireTime() const {
+ return expired_;
+ }
+
+ /**
+ * @brief Set the Expired object
+ *
+ * @param m_expired
+ */
+ void SetExpireTime(const boost::posix_time::ptime &m_expired);
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsNonExpired() const { return non_expired_; }
+
+ /**
+ * @brief Set the Non Expired object
+ *
+ * @param m_non_expired
+ */
+ void SetNonExpired(bool m_non_expired);
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsNoPassPhrase() const { return this->no_passphrase_; }
+
+ /**
+ * @brief Set the Non Pass Phrase object
+ *
+ * @param m_non_pass_phrase
+ */
+ void SetNonPassPhrase(bool m_non_pass_phrase) {
+ GenKeyInfo::no_passphrase_ = m_non_pass_phrase;
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsAllowSigning() const { return allow_signing_; }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsAllowNoPassPhrase() const {
+ return allow_no_pass_phrase_;
+ }
+
+ /**
+ * @brief Set the Allow Signing object
+ *
+ * @param m_allow_signing
+ */
+ void SetAllowSigning(bool m_allow_signing) {
+ if (allow_change_signing_) GenKeyInfo::allow_signing_ = m_allow_signing;
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsAllowEncryption() const { return allow_encryption_; }
+
+ /**
+ * @brief Set the Allow Encryption object
+ *
+ * @param m_allow_encryption
+ */
+ void SetAllowEncryption(bool m_allow_encryption);
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsAllowCertification() const {
+ return allow_certification_;
+ }
+
+ /**
+ * @brief Set the Allow Certification object
+ *
+ * @param m_allow_certification
+ */
+ void SetAllowCertification(bool m_allow_certification);
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsAllowAuthentication() const {
+ return allow_authentication_;
+ }
+
+ /**
+ * @brief Set the Allow Authentication object
+ *
+ * @param m_allow_authentication
+ */
+ void SetAllowAuthentication(bool m_allow_authentication) {
+ if (allow_change_authentication_)
+ GenKeyInfo::allow_authentication_ = m_allow_authentication;
+ }
+
+ /**
+ * @brief Get the Pass Phrase object
+ *
+ * @return const std::string&
+ */
+ [[nodiscard]] const std::string &GetPassPhrase() const { return passphrase_; }
+
+ /**
+ * @brief Set the Pass Phrase object
+ *
+ * @param m_pass_phrase
+ */
+ void SetPassPhrase(const std::string &m_pass_phrase) {
+ GenKeyInfo::passphrase_ = m_pass_phrase;
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsAllowChangeSigning() const {
+ return allow_change_signing_;
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsAllowChangeEncryption() const {
+ return allow_change_encryption_;
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsAllowChangeCertification() const {
+ return allow_change_certification_;
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsAllowChangeAuthentication() const {
+ return allow_change_authentication_;
+ }
+
+ /**
+ * @brief Get the Suggest Max Key Size object
+ *
+ * @return int
+ */
+ [[nodiscard]] int GetSuggestMaxKeySize() const {
+ return suggest_max_key_size_;
+ }
+
+ /**
+ * @brief Get the Suggest Min Key Size object
+ *
+ * @return int
+ */
+ [[nodiscard]] int GetSuggestMinKeySize() const {
+ return suggest_min_key_size_;
+ }
+
+ /**
+ * @brief Get the Size Change Step object
+ *
+ * @return int
+ */
+ [[nodiscard]] int GetSizeChangeStep() const {
+ return suggest_size_addition_step_;
+ }
+
+ private:
+ bool allow_encryption_ = true; ///<
+ bool allow_change_encryption_ = true; ///<
+ bool allow_certification_ = true; ///<
+ bool allow_change_certification_ = true; ///<
+ bool allow_authentication_ = true; ///<
+ bool allow_change_authentication_ = true; ///<
+ bool allow_signing_ = true; ///<
+ bool allow_change_signing_ = true; ///<
+
+ /**
+ * @brief
+ *
+ */
+ void reset_options();
+
+ public:
+ /**
+ * @brief Construct a new Gen Key Info object
+ *
+ * @param m_is_sub_key
+ * @param m_standalone
+ */
+ explicit GenKeyInfo(bool m_is_sub_key = false, bool m_standalone = false);
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_GPGGENKEYINFO_H
diff --git a/src/core/GpgInfo.cpp b/src/core/GpgInfo.cpp
new file mode 100644
index 00000000..a77f0ed4
--- /dev/null
+++ b/src/core/GpgInfo.cpp
@@ -0,0 +1,29 @@
+/**
+ * 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 "core/GpgInfo.h"
diff --git a/src/core/GpgInfo.h b/src/core/GpgInfo.h
new file mode 100644
index 00000000..71c5f9a9
--- /dev/null
+++ b/src/core/GpgInfo.h
@@ -0,0 +1,50 @@
+/**
+ * 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_ZH_CN_TS_GPGINFO_H
+#define GPGFRONTEND_ZH_CN_TS_GPGINFO_H
+
+#include <string>
+
+namespace GpgFrontend {
+/**
+ * @brief Use to record some info about gnupg
+ *
+ */
+class GpgInfo {
+ public:
+ std::string AppPath; ///< executable binary path of gnupg
+ std::string DatabasePath; ///<
+ std::string GnupgVersion; ///<
+ std::string GpgConfPath; ///<
+ std::string CMSPath; ///<
+ std::string GpgMEVersion; ///<
+};
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_ZH_CN_TS_GPGINFO_H
diff --git a/src/core/GpgModel.h b/src/core/GpgModel.h
new file mode 100644
index 00000000..e3d43332
--- /dev/null
+++ b/src/core/GpgModel.h
@@ -0,0 +1,60 @@
+/**
+ * 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_ZH_CN_TS_GPGMODEL_H
+#define GPGFRONTEND_ZH_CN_TS_GPGMODEL_H
+
+#include <list>
+#include <utility>
+
+#include "GpgConstants.h"
+#include "core/model/GpgData.h"
+#include "core/model/GpgKey.h"
+#include "core/model/GpgSignature.h"
+
+namespace GpgFrontend {
+
+using KeyId = std::string; ///<
+using SubkeyId = std::string; ///<
+using KeyIdArgsList = std::vector<KeyId>; ///<
+using KeyIdArgsListPtr = std::unique_ptr<KeyIdArgsList>; ///<
+using UIDArgsList = std::vector<std::string>; ///<
+using UIDArgsListPtr = std::unique_ptr<UIDArgsList>; ///<
+using SignIdArgsList = std::vector<std::pair<std::string, std::string>>; ///<
+using SignIdArgsListPtr = std::unique_ptr<SignIdArgsList>; ///<
+using KeyFprArgsListPtr = std::unique_ptr<std::vector<std::string>>; ///<
+using KeyArgsList = std::vector<GpgKey>; ///<
+using KeyListPtr = std::unique_ptr<KeyArgsList>; ///<
+using GpgKeyLinkList = std::list<GpgFrontend::GpgKey>; ///<
+using KeyLinkListPtr = std::unique_ptr<GpgKeyLinkList>; ///<
+using KeyPtr = std::unique_ptr<GpgKey>; ///<
+using KeyPtrArgsList = const std::initializer_list<KeyPtr>; ///<
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_ZH_CN_TS_GPGMODEL_H
diff --git a/src/core/function/ArchiveFileOperator.cpp b/src/core/function/ArchiveFileOperator.cpp
new file mode 100644
index 00000000..6315dcd5
--- /dev/null
+++ b/src/core/function/ArchiveFileOperator.cpp
@@ -0,0 +1,238 @@
+/**
+ * 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 "ArchiveFileOperator.h"
+
+int copy_data(struct archive *ar, struct archive *aw) {
+ int r;
+ const void *buff;
+ size_t size;
+ int64_t offset;
+
+ for (;;) {
+ r = archive_read_data_block(ar, &buff, &size, &offset);
+ if (r == ARCHIVE_EOF)
+ return (ARCHIVE_OK);
+ if (r != ARCHIVE_OK) {
+ LOG(ERROR) << "archive_read_data_block() failed: " << archive_error_string(ar);
+ return (r);
+ }
+ r = archive_write_data_block(aw, buff, size, offset);
+ if (r != ARCHIVE_OK) {
+ LOG(ERROR) << "archive_write_data_block() failed: " << archive_error_string(aw);
+ return (r);
+ }
+ }
+}
+
+void GpgFrontend::ArchiveFileOperator::CreateArchive(
+ const std::filesystem::path &base_path,
+ const std::filesystem::path &archive_path, int compress,
+ const std::vector<std::filesystem::path> &files) {
+ LOG(INFO) << "CreateArchive: " << archive_path.string();
+
+ auto current_base_path_backup = QDir::currentPath();
+ QDir::setCurrent(base_path.string().c_str());
+
+ auto relative_archive_path = std::filesystem::relative(archive_path, base_path);
+
+ std::vector<std::filesystem::path> relative_files;
+ relative_files.reserve(files.size());
+ for(const auto& file : files) {
+ relative_files.push_back(std::filesystem::relative(file, base_path));
+ }
+
+ struct archive *a;
+ struct archive_entry *entry;
+ ssize_t len;
+ int fd;
+
+ LOG(INFO) << "compress: " << compress;
+
+ a = archive_write_new();
+ switch (compress) {
+#ifndef NO_BZIP2_CREATE
+ case 'j':
+ case 'y':
+ archive_write_add_filter_bzip2(a);
+ break;
+#endif
+#ifndef NO_COMPRESS_CREATE
+ case 'Z':
+ archive_write_add_filter_compress(a);
+ break;
+#endif
+#ifndef NO_GZIP_CREATE
+ case 'z':
+ archive_write_add_filter_gzip(a);
+ break;
+#endif
+ default:
+ archive_write_add_filter_none(a);
+ break;
+ }
+ archive_write_set_format_ustar(a);
+ archive_write_set_format_pax_restricted(a);
+
+ auto filename = relative_archive_path.string();
+ if (!filename.empty() && filename == "-")
+ throw std::runtime_error("cannot write to stdout");
+
+ archive_write_open_filename(a, filename.c_str());
+
+ for (const auto &file : relative_files) {
+ struct archive *disk = archive_read_disk_new();
+#ifndef NO_LOOKUP
+ archive_read_disk_set_standard_lookup(disk);
+#endif
+ int r;
+
+ LOG(INFO) << "ReadFile: " << file.string();
+
+ r = archive_read_disk_open(disk, file.string().c_str());
+ if (r != ARCHIVE_OK) {
+ LOG(ERROR) << "archive_read_disk_open() failed: "
+ << archive_error_string(disk);
+ throw std::runtime_error("archive_read_disk_open() failed");
+ }
+
+ for (;;) {
+ bool needcr = false;
+
+ entry = archive_entry_new();
+ r = archive_read_next_header2(disk, entry);
+ if (r == ARCHIVE_EOF) break;
+ if (r != ARCHIVE_OK) {
+ LOG(ERROR) << "archive_read_next_header2() failed: "
+ << archive_error_string(disk);
+ throw std::runtime_error("archive_read_next_header2() failed");
+ }
+ archive_read_disk_descend(disk);
+ LOG(INFO) << "Adding: " << archive_entry_pathname(entry) << "size"
+ << archive_entry_size(entry) << " bytes"
+ << "file type" << archive_entry_filetype(entry);
+ r = archive_write_header(a, entry);
+ if (r < ARCHIVE_OK) {
+ LOG(ERROR) << "archive_write_header() failed: "
+ << archive_error_string(a);
+ throw std::runtime_error("archive_write_header() failed");
+ }
+ if (r == ARCHIVE_FATAL) throw std::runtime_error("archive fatal");
+ if (r > ARCHIVE_FAILED) {
+ ByteArray buff;
+ FileOperator::ReadFileStd(archive_entry_sourcepath(entry), buff);
+ archive_write_data(a, buff.c_str(), buff.size());
+ }
+ archive_entry_free(entry);
+ }
+ archive_read_close(disk);
+ archive_read_free(disk);
+ }
+ archive_write_close(a);
+ archive_write_free(a);
+
+ QDir::setCurrent(current_base_path_backup);
+}
+
+void GpgFrontend::ArchiveFileOperator::ExtractArchive(
+ const std::filesystem::path &archive_path,
+ const std::filesystem::path &base_path) {
+
+ LOG(INFO) << "ExtractArchive: " << archive_path.string();
+
+ auto current_base_path_backup = QDir::currentPath();
+ QDir::setCurrent(base_path.string().c_str());
+
+ struct archive *a;
+ struct archive *ext;
+ struct archive_entry *entry;
+ int r;
+
+ a = archive_read_new();
+ ext = archive_write_disk_new();
+ archive_write_disk_set_options(ext, 0);
+#ifndef NO_BZIP2_EXTRACT
+ archive_read_support_filter_bzip2(a);
+#endif
+#ifndef NO_GZIP_EXTRACT
+ archive_read_support_filter_gzip(a);
+#endif
+#ifndef NO_COMPRESS_EXTRACT
+ archive_read_support_filter_compress(a);
+#endif
+#ifndef NO_TAR_EXTRACT
+ archive_read_support_format_tar(a);
+#endif
+#ifndef NO_CPIO_EXTRACT
+ archive_read_support_format_cpio(a);
+#endif
+#ifndef NO_LOOKUP
+ archive_write_disk_set_standard_lookup(ext);
+#endif
+
+ auto filename = archive_path.string();
+
+ if (!filename.empty() && filename == "-") {
+ LOG(ERROR) << "cannot read from stdin";
+ }
+ if ((r = archive_read_open_filename(a, filename.c_str(), 10240))) {
+ LOG(ERROR) << "archive_read_open_filename() failed: "
+ << archive_error_string(a);
+ throw std::runtime_error("archive_read_open_filename() failed");
+ }
+ for (;;) {
+ r = archive_read_next_header(a, &entry);
+ if (r == ARCHIVE_EOF)
+ break;
+ if (r != ARCHIVE_OK) {
+ LOG(ERROR) << "archive_read_next_header() failed: "
+ << archive_error_string(a);
+ throw std::runtime_error("archive_read_next_header() failed");
+ }
+ LOG(INFO) << "Extracting: " << archive_entry_pathname(entry)
+ << "size" << archive_entry_size(entry) << " bytes"
+ << "file type" << archive_entry_filetype(entry);
+ r = archive_write_header(ext, entry);
+ if (r != ARCHIVE_OK) {
+ LOG(ERROR) << "archive_write_header() failed: "
+ << archive_error_string(ext);
+ } else {
+ r = copy_data(a, ext);
+ if (r != ARCHIVE_OK) {
+ LOG(ERROR) << "copy_data() failed: " << archive_error_string(ext);
+ }
+ }
+ }
+ archive_read_close(a);
+ archive_read_free(a);
+
+ archive_write_close(ext);
+ archive_write_free(ext);
+
+ QDir::setCurrent(current_base_path_backup);
+}
diff --git a/src/core/function/ArchiveFileOperator.h b/src/core/function/ArchiveFileOperator.h
new file mode 100644
index 00000000..8e1d9c44
--- /dev/null
+++ b/src/core/function/ArchiveFileOperator.h
@@ -0,0 +1,79 @@
+/**
+ * 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_ARCHIVEFILEOPERATOR_H
+#define GPGFRONTEND_ARCHIVEFILEOPERATOR_H
+
+#include "core/GpgFrontendCore.h"
+#include "core/function/FileOperator.h"
+
+namespace GpgFrontend {
+
+struct ArchiveStruct {
+ struct archive *archive;
+ struct archive_entry *entry;
+ int fd;
+ bool is_open;
+ std::string name;
+};
+
+class ArchiveFileOperator {
+ public:
+ static void ListArchive(const std::filesystem::path &archive_path) {
+ struct archive *a;
+ struct archive_entry *entry;
+ int r;
+
+ a = archive_read_new();
+ archive_read_support_filter_all(a);
+ archive_read_support_format_all(a);
+ r = archive_read_open_filename(a, archive_path.string().c_str(),
+ 10240); // Note 1
+ if (r != ARCHIVE_OK) return;
+ while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
+ LOG(INFO) << "File: " << archive_entry_pathname(entry);
+ LOG(INFO) << "File Path: " << archive_entry_pathname(entry);
+ archive_read_data_skip(a); // Note 2
+ }
+ r = archive_read_free(a); // Note 3
+ if (r != ARCHIVE_OK) return;
+ }
+
+ static void CreateArchive(
+ const std::filesystem::path &base_path,
+ const std::filesystem::path &archive_path,
+ int compress,
+ const std::vector<std::filesystem::path> &files);
+
+ static void ExtractArchive(
+ const std::filesystem::path &archive_path,
+ const std::filesystem::path &base_path);
+};
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_ARCHIVEFILEOPERATOR_H
diff --git a/src/core/function/DataObjectOperator.cpp b/src/core/function/DataObjectOperator.cpp
new file mode 100644
index 00000000..a3f7fc70
--- /dev/null
+++ b/src/core/function/DataObjectOperator.cpp
@@ -0,0 +1,169 @@
+/**
+ * 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 "DataObjectOperator.h"
+
+#include <qt-aes/qaesencryption.h>
+
+#include "core/function/FileOperator.h"
+#include "core/function/PassphraseGenerator.h"
+
+void GpgFrontend::DataObjectOperator::init_app_secure_key() {
+ LOG(INFO) << "Initializing application secure key";
+ FileOperator::WriteFileStd(app_secure_key_path_,
+ PassphraseGenerator::GetInstance().Generate(256));
+ std::filesystem::permissions(
+ app_secure_key_path_,
+ std::filesystem::perms::owner_read | std::filesystem::perms::owner_write);
+}
+
+GpgFrontend::DataObjectOperator::DataObjectOperator(int channel)
+ : SingletonFunctionObject<DataObjectOperator>(channel) {
+ if (!is_directory(app_secure_path_)) create_directory(app_secure_path_);
+
+ if (!exists(app_secure_key_path_)) {
+ init_app_secure_key();
+ }
+
+ std::string key;
+ if (!FileOperator::ReadFileStd(app_secure_key_path_.string(), key)) {
+ LOG(FATAL) << _("Failed to read app secure key file")
+ << app_secure_key_path_;
+ throw std::runtime_error(_("Failed to read app secure key file"));
+ }
+ hash_key_ = QCryptographicHash::hash(QByteArray::fromStdString(key),
+ QCryptographicHash::Sha256);
+ LOG(INFO) << "App secure key loaded" << hash_key_.size() << "bytes";
+
+ if (!exists(app_data_objs_path_)) create_directory(app_data_objs_path_);
+}
+
+std::string GpgFrontend::DataObjectOperator::SaveDataObj(
+ const std::string& _key, const nlohmann::json& value) {
+
+ std::string _hash_obj_key = {};
+ if (_key.empty()) {
+ _hash_obj_key =
+ QCryptographicHash::hash(
+ hash_key_ + QByteArray::fromStdString(
+ PassphraseGenerator::GetInstance().Generate(32) +
+ to_iso_extended_string(
+ boost::posix_time::second_clock::local_time())),
+ QCryptographicHash::Sha256)
+ .toHex()
+ .toStdString();
+ } else {
+ _hash_obj_key =
+ QCryptographicHash::hash(hash_key_ + QByteArray::fromStdString(_key),
+ QCryptographicHash::Sha256)
+ .toHex()
+ .toStdString();
+ }
+
+ const auto obj_path = app_data_objs_path_ / _hash_obj_key;
+
+ QAESEncryption encryption(QAESEncryption::AES_256, QAESEncryption::ECB,
+ QAESEncryption::Padding::ISO);
+ auto encoded =
+ encryption.encode(QByteArray::fromStdString(to_string(value)), hash_key_);
+
+ LOG(INFO) << _("Saving data object") << _hash_obj_key << "to" << obj_path << encoded.size() << "bytes";
+
+ FileOperator::WriteFileStd(obj_path.string(), encoded.toStdString());
+
+ return _key.empty() ? _hash_obj_key : std::string();
+}
+
+std::optional<nlohmann::json> GpgFrontend::DataObjectOperator::GetDataObject(
+ const std::string& _key) {
+ try {
+ LOG(INFO) << _("Get data object") << _key;
+ auto _hash_obj_key =
+ QCryptographicHash::hash(hash_key_ + QByteArray::fromStdString(_key),
+ QCryptographicHash::Sha256)
+ .toHex()
+ .toStdString();
+
+ const auto obj_path = app_data_objs_path_ / _hash_obj_key;
+
+ if (!std::filesystem::exists(obj_path)) {
+ LOG(ERROR) << _("Data object not found") << _key;
+ return {};
+ }
+
+ std::string buffer;
+ if (!FileOperator::ReadFileStd(obj_path.string(), buffer)) {
+ LOG(ERROR) << _("Failed to read data object") << _key;
+ return {};
+ }
+
+ LOG(INFO) << _("Data object found") << _key;
+
+ auto encoded = QByteArray::fromStdString(buffer);
+ QAESEncryption encryption(QAESEncryption::AES_256, QAESEncryption::ECB,
+ QAESEncryption::Padding::ISO);
+
+ LOG(INFO) << _("Decrypting data object") << encoded.size() << hash_key_.size();
+
+ auto decoded =
+ encryption.removePadding(encryption.decode(encoded, hash_key_));
+
+ LOG(INFO) << _("Data object decoded") << _key;
+
+ return nlohmann::json::parse(decoded.toStdString());
+ } catch (...) {
+ LOG(ERROR) << _("Failed to get data object") << _key;
+ return {};
+ }
+}
+
+std::optional<nlohmann::json>
+GpgFrontend::DataObjectOperator::GetDataObjectByRef(const std::string& _ref) {
+ if (_ref.size() != 64) return {};
+
+ try {
+ const auto& _hash_obj_key = _ref;
+ const auto obj_path = app_data_objs_path_ / _hash_obj_key;
+
+ if (!std::filesystem::exists(obj_path)) return {};
+
+ std::string buffer;
+ if (!FileOperator::ReadFileStd(obj_path.string(), buffer)) return {};
+ auto encoded = QByteArray::fromStdString(buffer);
+
+ QAESEncryption encryption(QAESEncryption::AES_256, QAESEncryption::ECB,
+ QAESEncryption::Padding::ISO);
+
+ auto decoded =
+ encryption.removePadding(encryption.decode(encoded, hash_key_));
+
+ return nlohmann::json::parse(decoded.toStdString());
+ } catch (...) {
+ return {};
+ }
+}
diff --git a/src/core/function/DataObjectOperator.h b/src/core/function/DataObjectOperator.h
new file mode 100644
index 00000000..0ce4e313
--- /dev/null
+++ b/src/core/function/DataObjectOperator.h
@@ -0,0 +1,82 @@
+/**
+ * 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_DATAOBJECTOPERATOR_H
+#define GPGFRONTEND_DATAOBJECTOPERATOR_H
+
+#include <json/single_include/nlohmann/json.hpp>
+
+#include "core/GpgFrontendCore.h"
+#include "core/GpgFunctionObject.h"
+#include "core/function/GlobalSettingStation.h"
+
+namespace GpgFrontend {
+
+class DataObjectOperator : public SingletonFunctionObject<DataObjectOperator> {
+ public:
+ /**
+ * @brief DataObjectOperator constructor
+ *
+ * @param channel channel
+ */
+ explicit DataObjectOperator(
+ int channel = SingletonFunctionObject::GetDefaultChannel());
+
+ std::string SaveDataObj(const std::string &_key, const nlohmann::json &value);
+
+ std::optional<nlohmann::json> GetDataObject(const std::string &_key);
+
+ std::optional<nlohmann::json> GetDataObjectByRef(const std::string &_ref);
+
+ private:
+ /**
+ * @brief init the secure key of application data object
+ *
+ */
+ void init_app_secure_key();
+
+ GlobalSettingStation &global_setting_station_ =
+ GlobalSettingStation::GetInstance(); ///< GlobalSettingStation
+ std::filesystem::path app_secure_path_ =
+ global_setting_station_.GetAppConfigPath() /
+ "secure"; ///< Where sensitive information is stored
+ std::filesystem::path app_secure_key_path_ =
+ app_secure_path_ / "app.key"; ///< Where the key of data object is stored
+ std::filesystem::path app_data_objs_path_ =
+ global_setting_station_.GetAppDataPath() / "data_objs"; ///< Where data
+ ///< object is
+ ///< stored
+
+ std::random_device rd_; ///< Random device
+ std::mt19937 mt_ = std::mt19937(rd_()); ///< Mersenne twister
+ QByteArray hash_key_; ///< Hash key
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_DATAOBJECTOPERATOR_H
diff --git a/src/core/function/FileOperator.cpp b/src/core/function/FileOperator.cpp
new file mode 100644
index 00000000..d0a3df23
--- /dev/null
+++ b/src/core/function/FileOperator.cpp
@@ -0,0 +1,119 @@
+/**
+* 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 "FileOperator.h"
+
+bool GpgFrontend::FileOperator::ReadFile(const QString& file_name,
+ QByteArray& data) {
+ QFile file(file_name);
+ if (!file.open(QIODevice::ReadOnly)) {
+ LOG(ERROR) << "failed to open file" << file_name.toStdString();
+ return false;
+ }
+ data = file.readAll();
+ file.close();
+ return true;
+}
+
+bool GpgFrontend::FileOperator::WriteFile(const QString& file_name,
+ const QByteArray& data) {
+ QFile file(file_name);
+ if (!file.open(QIODevice::WriteOnly)) {
+ LOG(ERROR) << "failed to open file" << file_name.toStdString();
+ return false;
+ }
+ file.write(data);
+ file.close();
+ return true;
+}
+
+bool GpgFrontend::FileOperator::ReadFileStd(
+ const std::filesystem::path& file_name, std::string& data) {
+ QByteArray byte_data;
+ bool res = ReadFile(QString::fromStdString(file_name.string()), byte_data);
+ data = byte_data.toStdString();
+ return res;
+}
+
+bool GpgFrontend::FileOperator::WriteFileStd(
+ const std::filesystem::path& file_name, const std::string& data) {
+ return WriteFile(QString::fromStdString(file_name.string()),
+ QByteArray::fromStdString(data));
+}
+
+std::string GpgFrontend::FileOperator::CalculateHash(
+ const std::filesystem::path& file_path) {
+ // Returns empty QByteArray() on failure.
+ QFileInfo info(QString::fromStdString(file_path.string()));
+ std::stringstream ss;
+
+ if (info.isFile() && info.isReadable()) {
+ ss << "[#] " << _("File Hash Information") << std::endl;
+ ss << " " << _("filename") << _(": ")
+ << file_path.filename().string().c_str() << std::endl;
+
+
+ QFile f(info.filePath());
+ f.open(QFile::ReadOnly);
+ auto buffer = f.readAll();
+ ss << " " << _("file size(bytes)") << _(": ")
+ << buffer.size() << std::endl;
+ f.close();
+ if (f.open(QFile::ReadOnly)) {
+ auto hash_md5 = QCryptographicHash(QCryptographicHash::Md5);
+ // md5
+ hash_md5.addData(buffer);
+ auto md5 = hash_md5.result().toHex().toStdString();
+ LOG(INFO) << "md5" << md5;
+ ss << " "
+ << "md5" << _(": ") << md5 << std::endl;
+
+ auto hash_sha1 = QCryptographicHash(QCryptographicHash::Sha1);
+ // sha1
+ hash_sha1.addData(buffer);
+ auto sha1 = hash_sha1.result().toHex().toStdString();
+ LOG(INFO) << "sha1" << sha1;
+ ss << " "
+ << "sha1" << _(": ") << sha1 << std::endl;
+
+ auto hash_sha256 = QCryptographicHash(QCryptographicHash::Sha256);
+ // sha1
+ hash_sha256.addData(buffer);
+ auto sha256 = hash_sha256.result().toHex().toStdString();
+ LOG(INFO) << "sha256" << sha256;
+ ss << " "
+ << "sha256" << _(": ") << sha256 << std::endl;
+
+ ss << std::endl;
+ }
+ } else {
+ ss << "[#] " << _("Error in Calculating File Hash ") << std::endl;
+ }
+
+ return ss.str();
+}
diff --git a/src/core/function/FileOperator.h b/src/core/function/FileOperator.h
new file mode 100644
index 00000000..aa2c3b73
--- /dev/null
+++ b/src/core/function/FileOperator.h
@@ -0,0 +1,92 @@
+/**
+ * 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_FILEOPERATOR_H
+#define GPGFRONTEND_FILEOPERATOR_H
+
+#include "core/GpgFrontendCore.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief provides file operations
+ *
+ */
+class FileOperator {
+ public:
+ /**
+ * @brief read file content using std struct
+ *
+ *
+ * @param file_name file name
+ * @param data data read from file
+ * @return
+ */
+ static bool ReadFileStd(const std::filesystem::path &file_name,
+ std::string &data);
+
+ /**
+ * @brief write file content using std struct
+ *
+ * @param file_name file name
+ * @param data data to write to file
+ * @return
+ */
+ static bool WriteFileStd(const std::filesystem::path &file_name,
+ const std::string &data);
+
+ /**
+ * @brief read file content
+ *
+ * @param file_name file name
+ * @param data data read from file
+ * @return true if success
+ * @return false if failed
+ */
+ static bool ReadFile(const QString &file_name, QByteArray &data);
+
+ /**
+ * @brief write file content
+ *
+ * @param file_name file name
+ * @param data data to write to file
+ * @return true if success
+ * @return false if failed
+ */
+ static bool WriteFile(const QString &file_name, const QByteArray &data);
+
+ /**
+ * calculate the hash of a file
+ * @param file_path
+ * @return
+ */
+ static std::string CalculateHash(const std::filesystem::path &file_path);
+};
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_FILEOPERATOR_H
diff --git a/src/core/function/GlobalSettingStation.cpp b/src/core/function/GlobalSettingStation.cpp
new file mode 100644
index 00000000..7b3e868e
--- /dev/null
+++ b/src/core/function/GlobalSettingStation.cpp
@@ -0,0 +1,141 @@
+/**
+ * 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 "GlobalSettingStation.h"
+
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+
+#include <vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp>
+#include <vmime/vmime.hpp>
+
+#include "core/function/FileOperator.h"
+
+void GpgFrontend::GlobalSettingStation::SyncSettings() noexcept {
+ using namespace libconfig;
+ try {
+ ui_cfg_.writeFile(ui_config_path_.string().c_str());
+ LOG(INFO) << _("Updated ui configuration successfully written to")
+ << ui_config_path_;
+
+ } catch (const FileIOException &fioex) {
+ LOG(ERROR) << _("I/O error while writing ui configuration file")
+ << ui_config_path_;
+ }
+}
+
+GpgFrontend::GlobalSettingStation::GlobalSettingStation(int channel) noexcept
+ : SingletonFunctionObject<GlobalSettingStation>(channel) {
+ using namespace std::filesystem;
+ using namespace libconfig;
+
+ el::Loggers::addFlag(el::LoggingFlag::AutoSpacing);
+
+ LOG(INFO) << _("App Path") << app_path_;
+ LOG(INFO) << _("App Configure Path") << app_configure_path_;
+ LOG(INFO) << _("App Data Path") << app_data_path_;
+ LOG(INFO) << _("App Log Path") << app_log_path_;
+ LOG(INFO) << _("App Locale Path") << app_locale_path_;
+
+ if (!is_directory(app_configure_path_)) create_directory(app_configure_path_);
+
+ if (!is_directory(app_data_path_)) create_directory(app_data_path_);
+
+ if (!is_directory(app_log_path_)) create_directory(app_log_path_);
+
+ if (!is_directory(ui_config_dir_path_)) create_directory(ui_config_dir_path_);
+
+ if (!exists(ui_config_path_)) {
+ try {
+ this->ui_cfg_.writeFile(ui_config_path_.string().c_str());
+ LOG(INFO) << _("UserInterface configuration successfully written to")
+ << ui_config_path_;
+
+ } catch (const FileIOException &fioex) {
+ LOG(ERROR)
+ << _("I/O error while writing UserInterface configuration file")
+ << ui_config_path_;
+ }
+ } else {
+ try {
+ this->ui_cfg_.readFile(ui_config_path_.string().c_str());
+ LOG(INFO) << _("UserInterface configuration successfully read from")
+ << ui_config_path_;
+ } catch (const FileIOException &fioex) {
+ LOG(ERROR) << _("I/O error while reading UserInterface configure file");
+ } catch (const ParseException &pex) {
+ LOG(ERROR) << _("Parse error at ") << pex.getFile() << ":"
+ << pex.getLine() << " - " << pex.getError();
+ }
+ }
+}
+
+void GpgFrontend::GlobalSettingStation::AddRootCert(
+ const std::filesystem::path &path) {
+ std::string out_buffer;
+ if (!FileOperator::ReadFileStd(path.string(), out_buffer)) {
+ LOG(ERROR) << _("Failed to read root certificate file") << path;
+ return;
+ }
+
+ auto mem_bio = std::shared_ptr<BIO>(
+ BIO_new_mem_buf(out_buffer.data(), static_cast<int>(out_buffer.size())),
+ [](BIO *_p) { BIO_free(_p); });
+
+ auto x509 = std::shared_ptr<X509>(
+ PEM_read_bio_X509(mem_bio.get(), nullptr, nullptr, nullptr),
+ [](X509 *_p) { X509_free(_p); });
+
+ if (!x509) return;
+
+ root_certs_.push_back(x509);
+}
+
+vmime::shared_ptr<vmime::security::cert::defaultCertificateVerifier>
+GpgFrontend::GlobalSettingStation::GetCertVerifier() const {
+ auto p_cv =
+ vmime::make_shared<vmime::security::cert::defaultCertificateVerifier>();
+
+ std::vector<vmime::shared_ptr<vmime::security::cert::X509Certificate>>
+ _root_certs;
+ for (const auto &cert : root_certs_) {
+ _root_certs.push_back(
+ std::make_shared<vmime::security::cert::X509Certificate_OpenSSL>(
+ cert.get()));
+ }
+ return p_cv;
+}
+
+const std::vector<std::shared_ptr<X509>>
+ &GpgFrontend::GlobalSettingStation::GetRootCerts() {
+ return root_certs_;
+}
+
+void GpgFrontend::GlobalSettingStation::init_app_secure_key() {}
+
+GpgFrontend::GlobalSettingStation::~GlobalSettingStation() noexcept = default;
diff --git a/src/core/function/GlobalSettingStation.h b/src/core/function/GlobalSettingStation.h
new file mode 100644
index 00000000..d6521c8a
--- /dev/null
+++ b/src/core/function/GlobalSettingStation.h
@@ -0,0 +1,232 @@
+/**
+ * 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_GLOBALSETTINGSTATION_H
+#define GPGFRONTEND_GLOBALSETTINGSTATION_H
+
+#include <openssl/x509.h>
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+
+#include "GpgFrontendBuildInstallInfo.h"
+#include "core/GpgFrontendCore.h"
+#include "core/GpgFunctionObject.h"
+
+namespace vmime::security::cert {
+class defaultCertificateVerifier;
+class X509Certificate;
+} // namespace vmime::security::cert
+
+namespace GpgFrontend {
+
+/**
+ * @brief
+ *
+ */
+class GlobalSettingStation
+ : public SingletonFunctionObject<GlobalSettingStation> {
+ public:
+ /**
+ * @brief Construct a new Global Setting Station object
+ *
+ */
+ explicit GlobalSettingStation(
+ int channel = SingletonFunctionObject::GetDefaultChannel()) noexcept;
+
+ /**
+ * @brief Destroy the Global Setting Station object
+ *
+ */
+ ~GlobalSettingStation() noexcept override;
+
+ /**
+ * @brief
+ *
+ * @return libconfig::Setting&
+ */
+ libconfig::Setting &GetUISettings() noexcept { return ui_cfg_.getRoot(); }
+
+ /**
+ * @brief Get the App Dir object
+ *
+ * @return std::filesystem::path
+ */
+ [[nodiscard]] std::filesystem::path GetAppDir() const { return app_path_; }
+
+ [[nodiscard]] std::filesystem::path GetAppDataPath() const {
+ return app_data_path_;
+ }
+
+ /**
+ * @brief Get the Log Dir object
+ *
+ * @return std::filesystem::path
+ */
+ [[nodiscard]] std::filesystem::path GetLogDir() const {
+ return app_log_path_;
+ }
+
+ /**
+ * @brief Get the Standalone Database Dir object
+ *
+ * @return std::filesystem::path
+ */
+ [[nodiscard]] std::filesystem::path GetStandaloneDatabaseDir() const {
+ auto db_path = app_configure_path_ / "db";
+ if (!std::filesystem::exists(db_path)) {
+ std::filesystem::create_directory(db_path);
+ }
+ return db_path;
+ }
+
+ [[nodiscard]] std::filesystem::path GetAppConfigPath() const {
+ return app_configure_path_;
+ }
+
+ /**
+ * @brief Get the Standalone Gpg Bin Dir object
+ *
+ * @return std::filesystem::path
+ */
+ [[nodiscard]] std::filesystem::path GetStandaloneGpgBinDir() const {
+ return app_resource_path_ / "gpg1.4" / "gpg";
+ }
+
+ /**
+ * @brief Get the Locale Dir object
+ *
+ * @return std::filesystem::path
+ */
+ [[nodiscard]] std::filesystem::path GetLocaleDir() const {
+ return app_locale_path_;
+ }
+
+ /**
+ * @brief Get the Resource Dir object
+ *
+ * @return std::filesystem::path
+ */
+ [[nodiscard]] std::filesystem::path GetResourceDir() const {
+ return app_resource_path_;
+ }
+
+ /**
+ * @brief Get the Certs Dir object
+ *
+ * @return std::filesystem::path
+ */
+ [[nodiscard]] std::filesystem::path GetCertsDir() const {
+ return app_resource_path_ / "certs";
+ }
+
+ /**
+ * @brief Get the Cert Verifier object
+ *
+ * @return std::shared_ptr<
+ * vmime::security::cert::defaultCertificateVerifier>
+ */
+ [[nodiscard]] std::shared_ptr<
+ vmime::security::cert::defaultCertificateVerifier>
+ GetCertVerifier() const;
+
+ /**
+ * @brief
+ *
+ * @param path
+ */
+ void AddRootCert(const std::filesystem::path &path);
+
+ /**
+ * @brief Get the Root Certs object
+ *
+ * @return const std::vector<std::shared_ptr<X509>>&
+ */
+ const std::vector<std::shared_ptr<X509>> &GetRootCerts();
+
+ /**
+ * @brief
+ *
+ */
+ void ResetRootCerts() { root_certs_.clear(); }
+
+ /**
+ * @brief sync the settings to the file
+ *
+ */
+ void SyncSettings() noexcept;
+
+ private:
+ std::filesystem::path app_path_ =
+ qApp->applicationDirPath().toStdString(); ///< Program Location
+ std::filesystem::path app_data_path_ =
+ QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)
+ .toStdString(); ///< Program Data Location
+ std::filesystem::path app_log_path_ =
+ app_data_path_ / "logs"; ///< Program Data Location
+ std::filesystem::path app_data_objs_path_ =
+ app_data_path_ / "objs"; ///< Object storage path
+
+#ifdef LINUX_INSTALL_BUILD
+ std::filesystem::path app_resource_path_ =
+ std::filesystem::path(APP_LOCALSTATE_PATH) /
+ "gpgfrontend"; ///< Program Data Location
+#else
+ std::filesystem::path app_resource_path_ =
+ RESOURCE_DIR_BOOST_PATH(app_path_); ///< Program Data Location
+#endif
+
+#ifdef LINUX_INSTALL_BUILD
+ std::filesystem::path app_locale_path_ =
+ std::string(APP_LOCALE_PATH); ///< Program Data Location
+#else
+ std::filesystem::path app_locale_path_ =
+ app_resource_path_ / "locales"; ///< Program Data Location
+#endif
+
+ std::filesystem::path app_configure_path_ =
+ QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation)
+ .toStdString(); ///< Program Configure Location
+ std::filesystem::path ui_config_dir_path_ =
+ app_configure_path_ /
+ "UserInterface"; ///< Configure File Directory Location
+ std::filesystem::path ui_config_path_ =
+ ui_config_dir_path_ / "ui.cfg"; ///< UI Configure File Location
+
+ libconfig::Config ui_cfg_; ///<
+ std::vector<std::shared_ptr<X509>> root_certs_; ///<
+
+ /**
+ * @brief
+ *
+ */
+ void init_app_secure_key();
+};
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_GLOBALSETTINGSTATION_H
diff --git a/src/core/function/KeyPackageOperator.cpp b/src/core/function/KeyPackageOperator.cpp
new file mode 100644
index 00000000..2b2802f7
--- /dev/null
+++ b/src/core/function/KeyPackageOperator.cpp
@@ -0,0 +1,120 @@
+/**
+ * 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 "FileOperator.h"
+#include "function/PassphraseGenerator.h"
+#include "function/gpg/GpgKeyGetter.h"
+#include "function/gpg/GpgKeyImportExporter.h"
+#include "qt-aes/qaesencryption.h"
+
+namespace GpgFrontend {
+
+bool KeyPackageOperator::GeneratePassphrase(
+ const std::filesystem::path& phrase_path, std::string& phrase) {
+ phrase = PassphraseGenerator::GetInstance().Generate(256);
+ LOG(INFO) << "Generated passphrase: " << phrase.size() << " bytes";
+ 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) {
+ LOG(INFO) << "Generating key package: " << key_package_name;
+
+ ByteArrayPtr key_export_data = nullptr;
+ if (!GpgKeyImportExporter::GetInstance().ExportKeys(key_ids, key_export_data,
+ secret)) {
+ LOG(ERROR) << "Failed to export keys";
+ 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);
+
+ LOG(INFO) << "Writing key package: " << key_package_name;
+ 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) {
+
+ LOG(INFO) << "Importing key package: " << key_package_path.string();
+
+ std::string encrypted_data;
+ FileOperator::ReadFileStd(key_package_path, encrypted_data);
+
+ if (encrypted_data.empty()) {
+ LOG(ERROR) << "Failed to read key package: " << key_package_path.string();
+ return false;
+ };
+
+ std::string passphrase;
+ FileOperator::ReadFileStd(phrase_path, passphrase);
+ LOG(INFO) << "Passphrase: " << passphrase.size() << " bytes";
+ if (passphrase.size() != 256) {
+ LOG(ERROR) << "Failed to read passphrase: " << phrase_path.string();
+ 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);
+
+ LOG(INFO) << "key data" << key_data.size();
+ 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/function/KeyPackageOperator.h b/src/core/function/KeyPackageOperator.h
new file mode 100644
index 00000000..cd344688
--- /dev/null
+++ b/src/core/function/KeyPackageOperator.h
@@ -0,0 +1,107 @@
+/**
+ * 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/gpg/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 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/core/function/PassphraseGenerator.cpp b/src/core/function/PassphraseGenerator.cpp
new file mode 100644
index 00000000..0267edda
--- /dev/null
+++ b/src/core/function/PassphraseGenerator.cpp
@@ -0,0 +1,29 @@
+/**
+* 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 "PassphraseGenerator.h"
diff --git a/src/core/function/PassphraseGenerator.h b/src/core/function/PassphraseGenerator.h
new file mode 100644
index 00000000..d1cc7607
--- /dev/null
+++ b/src/core/function/PassphraseGenerator.h
@@ -0,0 +1,83 @@
+/**
+ * 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_PASSPHRASEGENERATOR_H
+#define GPGFRONTEND_PASSPHRASEGENERATOR_H
+
+#include "core/GpgFrontendCore.h"
+#include "core/GpgFunctionObject.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief The PassphraseGenerator class
+ *
+ * This class is used to generate a passphrase.
+ */
+class PassphraseGenerator
+ : public SingletonFunctionObject<PassphraseGenerator> {
+ public:
+ /**
+ * @brief PassphraseGenerator constructor
+ *
+ * @param channel The channel to use
+ */
+ explicit PassphraseGenerator(
+ int channel = SingletonFunctionObject::GetDefaultChannel())
+ : SingletonFunctionObject<PassphraseGenerator>(channel) {}
+
+ /**
+ * @brief generate passphrase
+ *
+ * @param len length of the passphrase
+ * @return std::string passphrase
+ */
+ std::string Generate(int len) {
+ std::uniform_int_distribution<int> dist(999, 99999);
+
+ auto file_string = boost::format("KeyPackage_%1%") % dist(mt_);
+ 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;
+ }
+
+ std::random_device rd_; ///< Random device
+ std::mt19937 mt_ = std::mt19937(rd_()); ///< Mersenne twister
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_PASSPHRASEGENERATOR_H
diff --git a/src/core/function/aes/aes_ssl.h b/src/core/function/aes/aes_ssl.h
new file mode 100644
index 00000000..b5f0820f
--- /dev/null
+++ b/src/core/function/aes/aes_ssl.h
@@ -0,0 +1,74 @@
+/**
+ * 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_AES_SSL_H
+#define GPGFRONTEND_AES_SSL_H
+
+#include "GpgFrontend.h"
+
+#include <openssl/aes.h>
+#include <openssl/evp.h>
+
+namespace GpgFrontend::RawAPI {
+
+/**
+ * @brief
+ *
+ * @param key_data
+ * @param key_data_len
+ * @param salt
+ * @param e_ctx
+ * @param d_ctx
+ * @return int
+ */
+int aes_256_cbc_init(uint8_t *key_data, int key_data_len, uint8_t *salt,
+ EVP_CIPHER_CTX *e_ctx, EVP_CIPHER_CTX *d_ctx);
+
+/**
+ * @brief
+ *
+ * @param e
+ * @param plaintext
+ * @param len
+ * @return uint8_t*
+ */
+uint8_t *aes_256_cbc_encrypt(EVP_CIPHER_CTX *e, uint8_t *plaintext, int *len);
+
+/**
+ * @brief
+ *
+ * @param e
+ * @param ciphertext
+ * @param len
+ * @return uint8_t*
+ */
+uint8_t *aes_256_cbc_decrypt(EVP_CIPHER_CTX *e, uint8_t *ciphertext, int *len);
+
+} // namespace GpgFrontend::RawAPI
+
+#endif // GPGFRONTEND_AES_SSL_H
diff --git a/src/core/function/aes/aes_ssl_cbc.cpp b/src/core/function/aes/aes_ssl_cbc.cpp
new file mode 100644
index 00000000..95ae0ce2
--- /dev/null
+++ b/src/core/function/aes/aes_ssl_cbc.cpp
@@ -0,0 +1,99 @@
+/**
+ * AES encryption/decryption demo program using OpenSSL EVP apis
+ * gcc -Wall openssl_aes.c -lcrypto
+ * this is public domain code.
+ * Saju Pillai ([email protected])
+ **/
+
+#include "aes_ssl.h"
+
+namespace GpgFrontend::RawAPI {
+
+/**
+ * @brief Create a 256 bit key and IV using the supplied key_data. salt can be
+ * added for taste. Fills in the encryption and decryption ctx objects and
+ * returns 0 on success
+ *
+ * @param key_data
+ * @param key_data_len
+ * @param salt
+ * @param e_ctx
+ * @param d_ctx
+ * @return int
+ */
+int aes_256_cbc_init(uint8_t *key_data, int key_data_len, uint8_t *salt,
+ EVP_CIPHER_CTX *e_ctx, EVP_CIPHER_CTX *d_ctx) {
+ int i, nrounds = 5;
+ uint8_t key[32], iv[32];
+
+ /*
+ * Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the
+ * supplied key material. nrounds is the number of times the we hash the
+ * material. More rounds are more secure but slower.
+ */
+ i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data,
+ key_data_len, nrounds, key, iv);
+ if (i != 32) {
+ printf("Key size is %d bits - should be 256 bits\n", i);
+ return -1;
+ }
+
+ EVP_CIPHER_CTX_init(e_ctx);
+ EVP_EncryptInit_ex(e_ctx, EVP_aes_256_cbc(), NULL, key, iv);
+ EVP_CIPHER_CTX_init(d_ctx);
+ EVP_DecryptInit_ex(d_ctx, EVP_aes_256_cbc(), NULL, key, iv);
+
+ return 0;
+}
+
+/**
+ * @brief Encrypt *len bytes of data All data going in & out is considered
+ * binary (uint8_t[])
+ *
+ * @param e
+ * @param plaintext
+ * @param len
+ * @return uint8_t*
+ */
+uint8_t *aes_256_cbc_encrypt(EVP_CIPHER_CTX *e, uint8_t *plaintext, int *len) {
+ /* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1
+ * bytes */
+ int c_len = *len + AES_BLOCK_SIZE, f_len = 0;
+ auto *ciphertext = (uint8_t *)malloc(c_len);
+
+ /* allows reusing of 'e' for multiple encryption cycles */
+ EVP_EncryptInit_ex(e, nullptr, nullptr, nullptr, nullptr);
+
+ /* update ciphertext, c_len is filled with the length of ciphertext generated,
+ *len is the size of plaintext in bytes */
+ EVP_EncryptUpdate(e, ciphertext, &c_len, plaintext, *len);
+
+ /* update ciphertext with the final remaining bytes */
+ EVP_EncryptFinal_ex(e, ciphertext + c_len, &f_len);
+
+ *len = c_len + f_len;
+ return ciphertext;
+}
+
+/**
+ * @brief Decrypt *len bytes of ciphertext
+ *
+ * @param e
+ * @param ciphertext
+ * @param len
+ * @return uint8_t*
+ */
+uint8_t *aes_256_cbc_decrypt(EVP_CIPHER_CTX *e, uint8_t *ciphertext, int *len) {
+ /* plaintext will always be equal to or lesser than length of ciphertext*/
+ int p_len = *len, f_len = 0;
+ auto *plaintext = (uint8_t *)malloc(p_len);
+
+ EVP_DecryptInit_ex(e, nullptr, nullptr, nullptr, nullptr);
+ EVP_DecryptUpdate(e, plaintext, &p_len, ciphertext, *len);
+ EVP_DecryptFinal_ex(e, plaintext + p_len, &f_len);
+
+ *len = p_len + f_len;
+ return plaintext;
+}
+
+} // namespace GpgFrontend::RawAPI \ No newline at end of file
diff --git a/src/core/function/gpg/GpgBasicOperator.cpp b/src/core/function/gpg/GpgBasicOperator.cpp
new file mode 100644
index 00000000..b92404a9
--- /dev/null
+++ b/src/core/function/gpg/GpgBasicOperator.cpp
@@ -0,0 +1,220 @@
+/**
+ * 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 "GpgBasicOperator.h"
+
+#include <vector>
+
+#include "GpgKeyGetter.h"
+
+GpgFrontend::GpgError GpgFrontend::GpgBasicOperator::Encrypt(
+ KeyListPtr keys, GpgFrontend::BypeArrayRef in_buffer,
+ GpgFrontend::ByteArrayPtr& out_buffer, GpgFrontend::GpgEncrResult& result) {
+ // gpgme_encrypt_result_t e_result;
+ gpgme_key_t recipients[keys->size() + 1];
+
+ int index = 0;
+ for (const auto& key : *keys) recipients[index++] = gpgme_key_t(key);
+
+ // Last entry data_in array has to be nullptr
+ recipients[keys->size()] = nullptr;
+
+ GpgData data_in(in_buffer.data(), in_buffer.size()), data_out;
+
+ gpgme_error_t err = check_gpg_error(gpgme_op_encrypt(
+ ctx_, recipients, GPGME_ENCRYPT_ALWAYS_TRUST, data_in, data_out));
+
+ auto temp_data_out = data_out.Read2Buffer();
+ std::swap(temp_data_out, out_buffer);
+
+ auto temp_result = _new_result(gpgme_op_encrypt_result(ctx_));
+ std::swap(result, temp_result);
+
+ return err;
+}
+
+GpgFrontend::GpgError GpgFrontend::GpgBasicOperator::Decrypt(
+ BypeArrayRef in_buffer, GpgFrontend::ByteArrayPtr& out_buffer,
+ GpgFrontend::GpgDecrResult& result) {
+ gpgme_error_t err;
+
+ GpgData data_in(in_buffer.data(), in_buffer.size()), data_out;
+ err = check_gpg_error(gpgme_op_decrypt(ctx_, data_in, data_out));
+
+ auto temp_data_out = data_out.Read2Buffer();
+ std::swap(temp_data_out, out_buffer);
+
+ auto temp_result = _new_result(gpgme_op_decrypt_result(ctx_));
+ std::swap(result, temp_result);
+
+ return err;
+}
+
+GpgFrontend::GpgError GpgFrontend::GpgBasicOperator::Verify(
+ BypeArrayRef& in_buffer, ByteArrayPtr& sig_buffer,
+ GpgVerifyResult& result) const {
+ gpgme_error_t err;
+
+ GpgData data_in(in_buffer.data(), in_buffer.size());
+ GpgData data_out;
+
+ if (sig_buffer != nullptr) {
+ GpgData sig_data(sig_buffer->data(), sig_buffer->size());
+ err = check_gpg_error(gpgme_op_verify(ctx_, sig_data, data_in, nullptr));
+ } else
+ err = check_gpg_error(gpgme_op_verify(ctx_, data_in, nullptr, data_out));
+
+ auto temp_result = _new_result(gpgme_op_verify_result(ctx_));
+ std::swap(result, temp_result);
+
+ return err;
+}
+
+GpgFrontend::GpgError GpgFrontend::GpgBasicOperator::Sign(KeyListPtr signers,
+ BypeArrayRef in_buffer,
+ ByteArrayPtr& out_buffer,
+ gpgme_sig_mode_t mode,
+ GpgSignResult& result) {
+ gpgme_error_t err;
+
+ // Set Singers of this opera
+ SetSigners(*signers);
+
+ GpgData data_in(in_buffer.data(), in_buffer.size()), data_out;
+
+ err = check_gpg_error(gpgme_op_sign(ctx_, data_in, data_out, mode));
+
+ auto temp_data_out = data_out.Read2Buffer();
+ std::swap(temp_data_out, out_buffer);
+
+ auto temp_result = _new_result(gpgme_op_sign_result(ctx_));
+
+ std::swap(result, temp_result);
+
+ return err;
+}
+
+gpgme_error_t GpgFrontend::GpgBasicOperator::DecryptVerify(
+ BypeArrayRef in_buffer, ByteArrayPtr& out_buffer,
+ GpgDecrResult& decrypt_result, GpgVerifyResult& verify_result) {
+ gpgme_error_t err;
+
+ GpgData data_in(in_buffer.data(), in_buffer.size()), data_out;
+
+ err = check_gpg_error(gpgme_op_decrypt_verify(ctx_, data_in, data_out));
+
+ auto temp_data_out = data_out.Read2Buffer();
+ std::swap(temp_data_out, out_buffer);
+
+ auto temp_decr_result = _new_result(gpgme_op_decrypt_result(ctx_));
+ std::swap(decrypt_result, temp_decr_result);
+
+ auto temp_verify_result = _new_result(gpgme_op_verify_result(ctx_));
+ std::swap(verify_result, temp_verify_result);
+
+ return err;
+}
+
+gpgme_error_t GpgFrontend::GpgBasicOperator::EncryptSign(
+ KeyListPtr keys, KeyListPtr signers, BypeArrayRef in_buffer,
+ ByteArrayPtr& out_buffer, GpgEncrResult& encr_result,
+ GpgSignResult& sign_result) {
+ gpgme_error_t err;
+ SetSigners(*signers);
+
+ // gpgme_encrypt_result_t e_result;
+ gpgme_key_t recipients[keys->size() + 1];
+
+ // set key for user
+ int index = 0;
+ for (const auto& key : *keys) recipients[index++] = gpgme_key_t(key);
+
+ // Last entry dataIn array has to be nullptr
+ recipients[keys->size()] = nullptr;
+
+ GpgData data_in(in_buffer.data(), in_buffer.size()), data_out;
+
+ // If the last parameter isnt 0, a private copy of data is made
+ err = check_gpg_error(gpgme_op_encrypt_sign(
+ ctx_, recipients, GPGME_ENCRYPT_ALWAYS_TRUST, data_in, data_out));
+
+ auto temp_data_out = data_out.Read2Buffer();
+ std::swap(temp_data_out, out_buffer);
+
+ auto temp_encr_result = _new_result(gpgme_op_encrypt_result(ctx_));
+ swap(encr_result, temp_encr_result);
+ auto temp_sign_result = _new_result(gpgme_op_sign_result(ctx_));
+ swap(sign_result, temp_sign_result);
+
+ return err;
+}
+
+void GpgFrontend::GpgBasicOperator::SetSigners(KeyArgsList& signers) {
+ gpgme_signers_clear(ctx_);
+ for (const GpgKey& key : signers) {
+ DLOG(INFO) << "key" << key.GetFingerprint();
+ if (key.IsHasActualSigningCapability()) {
+ DLOG(INFO) << "signer";
+ auto error = gpgme_signers_add(ctx_, gpgme_key_t(key));
+ check_gpg_error(error);
+ }
+ }
+ if (signers.size() != gpgme_signers_count(ctx_))
+ DLOG(INFO) << "No All Signers Added";
+}
+
+std::unique_ptr<GpgFrontend::KeyArgsList>
+GpgFrontend::GpgBasicOperator::GetSigners() {
+ auto count = gpgme_signers_count(ctx_);
+ auto signers = std::make_unique<std::vector<GpgKey>>();
+ for (auto i = 0u; i < count; i++) {
+ auto key = GpgKey(gpgme_signers_enum(ctx_, i));
+ signers->push_back(GpgKey(std::move(key)));
+ }
+ return signers;
+}
+
+gpg_error_t GpgFrontend::GpgBasicOperator::EncryptSymmetric(
+ GpgFrontend::ByteArray& in_buffer, GpgFrontend::ByteArrayPtr& out_buffer,
+ GpgFrontend::GpgEncrResult& result) {
+ GpgData data_in(in_buffer.data(), in_buffer.size()), data_out;
+
+ gpgme_error_t err = check_gpg_error(gpgme_op_encrypt(
+ ctx_, nullptr, GPGME_ENCRYPT_SYMMETRIC, data_in, data_out));
+
+ auto temp_data_out = data_out.Read2Buffer();
+ std::swap(temp_data_out, out_buffer);
+
+ // TODO(Saturneric): maybe a bug of gpgme
+ if (gpgme_err_code(err) == GPG_ERR_NO_ERROR) {
+ auto temp_result = _new_result(gpgme_op_encrypt_result(ctx_));
+ std::swap(result, temp_result);
+ }
+
+ return err;
+}
diff --git a/src/core/function/gpg/GpgBasicOperator.h b/src/core/function/gpg/GpgBasicOperator.h
new file mode 100644
index 00000000..9b9d9f63
--- /dev/null
+++ b/src/core/function/gpg/GpgBasicOperator.h
@@ -0,0 +1,179 @@
+/**
+ * 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_ZH_CN_TS_BASICOPERATOR_H
+#define GPGFRONTEND_ZH_CN_TS_BASICOPERATOR_H
+
+#include "core/GpgConstants.h"
+#include "core/GpgContext.h"
+#include "core/GpgFunctionObject.h"
+#include "core/GpgModel.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief Basic operation collection
+ *
+ */
+class GpgBasicOperator : public SingletonFunctionObject<GpgBasicOperator> {
+ public:
+ /**
+ * @brief Construct a new Basic Operator object
+ *
+ * @param channel Channel corresponding to the context
+ */
+ explicit GpgBasicOperator(
+ int channel = SingletonFunctionObject::GetDefaultChannel())
+ : SingletonFunctionObject<GpgBasicOperator>(channel) {}
+
+ /**
+ * @brief Call the interface provided by gpgme for encryption operation
+ *
+ * All incoming data pointers out_buffer will be replaced with new valid
+ * values
+ *
+ * @param keys list of public keys
+ * @param in_buffer data that needs to be encrypted
+ * @param out_buffer encrypted data
+ * @param result the result of the operation
+ * @return error code
+ */
+ gpg_error_t Encrypt(KeyListPtr keys, BypeArrayRef in_buffer,
+ ByteArrayPtr& out_buffer, GpgEncrResult& result);
+
+ /**
+ * @brief Call the interface provided by GPGME to symmetrical encryption
+ *
+ * @param in_buffer Data for encryption
+ * @param out_buffer Encrypted data
+ * @param result Encrypted results
+ * @return gpg_error_t
+ */
+ gpg_error_t EncryptSymmetric(BypeArrayRef in_buffer, ByteArrayPtr& out_buffer,
+ GpgEncrResult& result);
+
+ /**
+ *
+ * @brief Call the interface provided by gpgme to perform encryption and
+ * signature operations at the same time.
+ *
+ * @param keys List of public keys
+ * @param signers Private key for signatures
+ * @param in_buffer Data for operation
+ * @param out_buffer Encrypted data
+ * @param encr_result Encrypted results
+ * @param sign_result Signature result
+ * @return
+ */
+ gpgme_error_t EncryptSign(KeyListPtr keys, KeyListPtr signers,
+ BypeArrayRef in_buffer, ByteArrayPtr& out_buffer,
+ GpgEncrResult& encr_result,
+ GpgSignResult& sign_result);
+
+ /**
+ * @brief Call the interface provided by gpgme for decryption operation
+ *
+ * @param in_buffer data that needs to be decrypted
+ * @param out_buffer decrypted data
+ * @param result the result of the operation
+ * @return error code
+ */
+ gpgme_error_t Decrypt(BypeArrayRef in_buffer, ByteArrayPtr& out_buffer,
+ GpgDecrResult& result);
+
+ /**
+ * @brief Call the interface provided by gpgme to perform decryption and
+ * verification operations at the same time.
+ *
+ * @param in_buffer data to be manipulated
+ * @param out_buffer data resulting from decryption operation
+ * @param decrypt_result the result of the decrypting operation
+ * @param verify_result the result of the verifying operation
+ * @return error code
+ */
+ gpgme_error_t DecryptVerify(BypeArrayRef in_buffer, ByteArrayPtr& out_buffer,
+ GpgDecrResult& decrypt_result,
+ GpgVerifyResult& verify_result);
+
+ /**
+ * @brief Call the interface provided by gpgme for verification operation
+ *
+ * @param in_buffer data that needs to be verified
+ * @param out_buffer verified data
+ * @param result the result of the operation
+ * @return error code
+ */
+ gpgme_error_t Verify(BypeArrayRef in_buffer, ByteArrayPtr& sig_buffer,
+ GpgVerifyResult& result) const;
+
+ /**
+ * @brief Call the interface provided by gpgme for signing operation
+ *
+ * The signing modes are as follows:
+ * `GPGME_SIG_MODE_NORMAL'
+ * A normal signature is made, the output includes the plaintext and the
+ * signature.
+ * `GPGME_SIG_MODE_DETACH'
+ * A detached signature is made.
+ * `GPGME_SIG_MODE_CLEAR'
+ * A clear text signature is made. The ASCII armor and text mode settings
+ * of the context are ignored.
+ *
+ * @param signers private keys for signing operations
+ * @param in_buffer data that needs to be signed
+ * @param out_buffer verified data
+ * @param mode signing mode
+ * @param result the result of the operation
+ * @return error code
+ */
+ gpg_error_t Sign(KeyListPtr signers, BypeArrayRef in_buffer,
+ ByteArrayPtr& out_buffer, gpgme_sig_mode_t mode,
+ GpgSignResult& result);
+
+ /**
+ * @brief Set the private key for signatures, this operation is a global
+ * operation.
+ *
+ * @param keys
+ */
+ void SetSigners(KeyArgsList& signers);
+
+ /**
+ * @brief Get a global signature private keys that has been set.
+ *
+ * @return Intelligent pointer pointing to the private key list
+ */
+ std::unique_ptr<KeyArgsList> GetSigners();
+
+ private:
+ GpgContext& ctx_ = GpgContext::GetInstance(
+ SingletonFunctionObject::GetChannel()); ///< Corresponding context
+};
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_ZH_CN_TS_BASICOPERATOR_H
diff --git a/src/core/function/gpg/GpgCommandExecutor.cpp b/src/core/function/gpg/GpgCommandExecutor.cpp
new file mode 100644
index 00000000..a6a67d08
--- /dev/null
+++ b/src/core/function/gpg/GpgCommandExecutor.cpp
@@ -0,0 +1,63 @@
+/**
+ * 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 "GpgCommandExecutor.h"
+#ifndef WINDOWS
+#include <boost/asio.hpp>
+#endif
+
+#ifndef WINDOWS
+
+using boost::process::async_pipe;
+
+void GpgFrontend::GpgCommandExecutor::Execute(
+ StringArgsRef arguments,
+ const std::function<void(async_pipe& in, async_pipe& out)>& interact_func) {
+ using namespace boost::process;
+
+ boost::asio::io_service ios;
+
+ std::vector<char> buf;
+
+ async_pipe in_pipe_stream(ios);
+ async_pipe out_pipe_stream(ios);
+
+ child child_process(ctx_.GetInfo().AppPath.c_str(), arguments,
+ std_out > in_pipe_stream, std_in < out_pipe_stream);
+
+ boost::asio::async_read(
+ in_pipe_stream, boost::asio::buffer(buf),
+ [&](const boost::system::error_code& ec, std::size_t size) {
+ interact_func(in_pipe_stream, out_pipe_stream);
+ });
+
+ ios.run();
+ child_process.wait();
+ child_process.exit_code();
+}
+
+#endif
diff --git a/src/core/function/gpg/GpgCommandExecutor.h b/src/core/function/gpg/GpgCommandExecutor.h
new file mode 100644
index 00000000..49baf406
--- /dev/null
+++ b/src/core/function/gpg/GpgCommandExecutor.h
@@ -0,0 +1,77 @@
+/**
+ * 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_ZH_CN_TS_GPGCOMMANDEXECUTOR_H
+#define GPGFRONTEND_ZH_CN_TS_GPGCOMMANDEXECUTOR_H
+
+#ifndef WINDOWS
+#include <boost/process.hpp>
+#endif
+
+#include "core/GpgContext.h"
+#include "core/GpgFunctionObject.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief Extra commands related to GPG
+ *
+ */
+class GpgCommandExecutor : public SingletonFunctionObject<GpgCommandExecutor> {
+ public:
+ /**
+ * @brief Construct a new Gpg Command Executor object
+ *
+ * @param channel Corresponding context
+ */
+ explicit GpgCommandExecutor(
+ int channel = SingletonFunctionObject::GetDefaultChannel())
+ : SingletonFunctionObject<GpgCommandExecutor>(channel) {}
+
+#ifndef WINDOWS
+
+ /**
+ * @brief Excuting an order
+ *
+ * @param arguments Command parameters
+ * @param interact_func Command answering function
+ */
+ void Execute(StringArgsRef arguments,
+ const std::function<void(boost::process::async_pipe &in,
+ boost::process::async_pipe &out)>
+ &interact_func);
+#endif
+
+ private:
+ GpgContext &ctx_ = GpgContext::GetInstance(
+ SingletonFunctionObject::GetChannel()); ///< Corresponding context
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_ZH_CN_TS_GPGCOMMANDEXECUTOR_H
diff --git a/src/core/function/gpg/GpgFileOpera.cpp b/src/core/function/gpg/GpgFileOpera.cpp
new file mode 100644
index 00000000..7044353b
--- /dev/null
+++ b/src/core/function/gpg/GpgFileOpera.cpp
@@ -0,0 +1,182 @@
+/**
+ * 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 "GpgFileOpera.h"
+
+#include <memory>
+#include <string>
+
+#include "GpgConstants.h"
+#include "GpgBasicOperator.h"
+#include "function/FileOperator.h"
+
+GpgFrontend::GpgError GpgFrontend::GpgFileOpera::EncryptFile(
+ KeyListPtr keys, const std::string& in_path, const std::string& out_path,
+ GpgEncrResult& result, int _channel) {
+
+ std::string in_buffer;
+ if(!FileOperator::ReadFileStd(in_path, in_buffer)) {
+ throw std::runtime_error("read file error");
+ }
+ std::unique_ptr<std::string> out_buffer = nullptr;
+
+ auto err = GpgBasicOperator::GetInstance(_channel).Encrypt(
+ std::move(keys), in_buffer, out_buffer, result);
+
+ if (check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR)
+ if (!FileOperator::WriteFileStd(out_path, *out_buffer)) {
+ throw std::runtime_error("write_buffer_to_file error");
+ };
+
+ return err;
+}
+
+GpgFrontend::GpgError GpgFrontend::GpgFileOpera::DecryptFile(
+ const std::string& in_path, const std::string& out_path,
+ GpgDecrResult& result) {
+ std::string in_buffer;
+ if(!FileOperator::ReadFileStd(in_path, in_buffer)) {
+ throw std::runtime_error("read file error");
+ }
+ std::unique_ptr<std::string> out_buffer;
+
+ auto err =
+ GpgBasicOperator::GetInstance().Decrypt(in_buffer, out_buffer, result);
+
+ assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR);
+
+ if (check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR)
+ if (!FileOperator::WriteFileStd(out_path, *out_buffer)) {
+ throw std::runtime_error("write_buffer_to_file error");
+ };
+
+ return err;
+}
+
+gpgme_error_t GpgFrontend::GpgFileOpera::SignFile(KeyListPtr keys,
+ const std::string& in_path,
+ const std::string& out_path,
+ GpgSignResult& result,
+ int _channel) {
+ std::string in_buffer;
+ if(!FileOperator::ReadFileStd(in_path, in_buffer)) {
+ throw std::runtime_error("read file error");
+ }
+ std::unique_ptr<std::string> out_buffer;
+
+ auto err = GpgBasicOperator::GetInstance(_channel).Sign(
+ std::move(keys), in_buffer, out_buffer, GPGME_SIG_MODE_DETACH, result);
+
+ if (check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR)
+ if (!FileOperator::WriteFileStd(out_path, *out_buffer)) {
+ throw std::runtime_error("write_buffer_to_file error");
+ };
+
+ return err;
+}
+
+gpgme_error_t GpgFrontend::GpgFileOpera::VerifyFile(
+ const std::string& data_path, const std::string& sign_path,
+ GpgVerifyResult& result, int _channel) {
+ std::string in_buffer;
+ if(!FileOperator::ReadFileStd(data_path, in_buffer)) {
+ throw std::runtime_error("read file error");
+ }
+ std::unique_ptr<std::string> sign_buffer = nullptr;
+ if (!sign_path.empty()) {
+ std::string sign_buffer_str;
+ if (!FileOperator::ReadFileStd(sign_path, sign_buffer_str)) {
+ throw std::runtime_error("read file error");
+ }
+ sign_buffer =
+ std::make_unique<std::string>(sign_buffer_str);
+ }
+ auto err = GpgBasicOperator::GetInstance(_channel).Verify(in_buffer, sign_buffer,
+ result);
+ return err;
+}
+
+gpg_error_t GpgFrontend::GpgFileOpera::EncryptSignFile(
+ KeyListPtr keys, KeyListPtr signer_keys, const std::string& in_path,
+ const std::string& out_path, GpgEncrResult& encr_res,
+ GpgSignResult& sign_res, int _channel) {
+ std::string in_buffer;
+ if(!FileOperator::ReadFileStd(in_path, in_buffer)) {
+ throw std::runtime_error("read file error");
+ }
+ std::unique_ptr<std::string> out_buffer = nullptr;
+
+ auto err = GpgBasicOperator::GetInstance(_channel).EncryptSign(
+ std::move(keys), std::move(signer_keys), in_buffer, out_buffer, encr_res,
+ sign_res);
+
+ if (check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR)
+ if (!FileOperator::WriteFileStd(out_path, *out_buffer)) {
+ throw std::runtime_error("write_buffer_to_file error");
+ };
+
+ return err;
+}
+
+gpg_error_t GpgFrontend::GpgFileOpera::DecryptVerifyFile(
+ const std::string& in_path, const std::string& out_path,
+ GpgDecrResult& decr_res, GpgVerifyResult& verify_res) {
+ std::string in_buffer;
+ if(!FileOperator::ReadFileStd(in_path, in_buffer)) {
+ throw std::runtime_error("read file error");
+ }
+
+ std::unique_ptr<std::string> out_buffer = nullptr;
+ auto err = GpgBasicOperator::GetInstance().DecryptVerify(in_buffer, out_buffer,
+ decr_res, verify_res);
+
+ if (check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR)
+ if (!FileOperator::WriteFileStd(out_path, *out_buffer)) {
+ throw std::runtime_error("write file error");
+ };
+
+ return err;
+}
+unsigned int GpgFrontend::GpgFileOpera::EncryptFileSymmetric(
+ const std::string& in_path, const std::string& out_path,
+ GpgFrontend::GpgEncrResult& result, int _channel) {
+ std::string in_buffer;
+ if(!FileOperator::ReadFileStd(in_path, in_buffer)) {
+ throw std::runtime_error("read file error");
+ }
+
+ std::unique_ptr<std::string> out_buffer;
+ auto err = GpgBasicOperator::GetInstance(_channel).EncryptSymmetric(
+ in_buffer, out_buffer, result);
+
+ if (check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR)
+ if (!FileOperator::WriteFileStd(out_path, *out_buffer)) {
+ throw std::runtime_error("write_buffer_to_file error");
+ };
+
+ return err;
+}
diff --git a/src/core/function/gpg/GpgFileOpera.h b/src/core/function/gpg/GpgFileOpera.h
new file mode 100644
index 00000000..f21bf04c
--- /dev/null
+++ b/src/core/function/gpg/GpgFileOpera.h
@@ -0,0 +1,153 @@
+/**
+ * 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_GPGFILEOPERA_H
+#define GPGFRONTEND_GPGFILEOPERA_H
+
+#include "core/GpgConstants.h"
+#include "core/GpgContext.h"
+#include "core/GpgModel.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief Executive files related to the basic operations that are provided by
+ * GpgBasicOperator
+ * @class class: GpgBasicOperator
+ */
+class GpgFileOpera : public SingletonFunctionObject<GpgFileOpera> {
+ public:
+ explicit GpgFileOpera(
+ int channel = SingletonFunctionObject::GetDefaultChannel())
+ : SingletonFunctionObject<GpgFileOpera>(channel) {}
+
+ /**
+ * @brief Encrypted file
+ *
+ * @param keys Used public key
+ * @param in_path The path where the enter file is located
+ * @param out_path The path where the output file is located
+ * @param result Encrypted results
+ * @param _channel Channel in context
+ * @return unsigned int error code
+ */
+ static unsigned int EncryptFile(KeyListPtr keys, const std::string& in_path,
+ const std::string& out_path,
+ GpgEncrResult& result,
+ int _channel = GPGFRONTEND_DEFAULT_CHANNEL);
+
+ /**
+ * @brief 运用对称加密算法加密文件
+ *
+ * @param in_path
+ * @param out_path
+ * @param result
+ * @param _channel
+ * @return unsigned int
+ */
+ static unsigned int EncryptFileSymmetric(
+ const std::string& in_path, const std::string& out_path,
+ GpgEncrResult& result, int _channel = GPGFRONTEND_DEFAULT_CHANNEL);
+
+ /**
+ * @brief
+ *
+ * @param in_path
+ * @param out_path
+ * @param result
+ * @return GpgError
+ */
+ static GpgError DecryptFile(const std::string& in_path,
+ const std::string& out_path,
+ GpgDecrResult& result);
+
+ /**
+ * @brief
+ *
+ * @param keys
+ * @param in_path
+ * @param out_path
+ * @param result
+ * @param _channel
+ * @return GpgError
+ */
+ static GpgError SignFile(KeyListPtr keys, const std::string& in_path,
+ const std::string& out_path, GpgSignResult& result,
+ int _channel = GPGFRONTEND_DEFAULT_CHANNEL);
+
+ /**
+ * @brief
+ *
+ * @param data_path
+ * @param sign_path
+ * @param result
+ * @param _channel
+ * @return GpgError
+ */
+ static GpgError VerifyFile(const std::string& data_path,
+ const std::string& sign_path,
+ GpgVerifyResult& result,
+ int _channel = GPGFRONTEND_DEFAULT_CHANNEL);
+
+ /**
+ * @brief
+ *
+ * @param keys
+ * @param signer_keys
+ * @param in_path
+ * @param out_path
+ * @param encr_res
+ * @param sign_res
+ * @param _channel
+ * @return GpgError
+ */
+ static GpgError EncryptSignFile(KeyListPtr keys, KeyListPtr signer_keys,
+ const std::string& in_path,
+ const std::string& out_path,
+ GpgEncrResult& encr_res,
+ GpgSignResult& sign_res,
+ int _channel = GPGFRONTEND_DEFAULT_CHANNEL);
+
+ /**
+ * @brief
+ *
+ * @param in_path
+ * @param out_path
+ * @param decr_res
+ * @param verify_res
+ * @return GpgError
+ */
+ static GpgError DecryptVerifyFile(const std::string& in_path,
+ const std::string& out_path,
+ GpgDecrResult& decr_res,
+ GpgVerifyResult& verify_res);
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_GPGFILEOPERA_H
diff --git a/src/core/function/gpg/GpgKeyGetter.cpp b/src/core/function/gpg/GpgKeyGetter.cpp
new file mode 100644
index 00000000..1a4715e7
--- /dev/null
+++ b/src/core/function/gpg/GpgKeyGetter.cpp
@@ -0,0 +1,96 @@
+/**
+ * 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 "GpgKeyGetter.h"
+
+#include <gpg-error.h>
+
+#include "GpgConstants.h"
+
+GpgFrontend::GpgKey GpgFrontend::GpgKeyGetter::GetKey(const std::string& fpr) {
+ gpgme_key_t _p_key = nullptr;
+ gpgme_get_key(ctx_, fpr.c_str(), &_p_key, 1);
+ if (_p_key == nullptr) {
+ DLOG(WARNING) << "GpgKeyGetter GetKey Private _p_key Null fpr" << fpr;
+ return GetPubkey(fpr);
+ } else {
+ return GpgKey(std::move(_p_key));
+ }
+}
+
+GpgFrontend::GpgKey GpgFrontend::GpgKeyGetter::GetPubkey(
+ const std::string& fpr) {
+ gpgme_key_t _p_key = nullptr;
+ gpgme_get_key(ctx_, fpr.c_str(), &_p_key, 0);
+ if (_p_key == nullptr)
+ DLOG(WARNING) << "GpgKeyGetter GetKey _p_key Null" << fpr;
+ return GpgKey(std::move(_p_key));
+}
+
+GpgFrontend::KeyLinkListPtr GpgFrontend::GpgKeyGetter::FetchKey() {
+ gpgme_error_t err;
+
+ auto keys_list = std::make_unique<GpgKeyLinkList>();
+
+ err = gpgme_op_keylist_start(ctx_, nullptr, 0);
+ assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR);
+
+ gpgme_key_t key;
+ while ((err = gpgme_op_keylist_next(ctx_, &key)) == GPG_ERR_NO_ERROR) {
+ keys_list->push_back(GetKey(key->fpr));
+ }
+
+ assert(check_gpg_error_2_err_code(err, GPG_ERR_EOF) == GPG_ERR_EOF);
+
+ err = gpgme_op_keylist_end(ctx_);
+
+ assert(check_gpg_error_2_err_code(err, GPG_ERR_EOF) == GPG_ERR_NO_ERROR);
+
+ return keys_list;
+}
+
+GpgFrontend::KeyListPtr GpgFrontend::GpgKeyGetter::GetKeys(
+ const KeyIdArgsListPtr& ids) {
+ auto keys = std::make_unique<KeyArgsList>();
+ for (const auto& id : *ids) keys->push_back(GetKey(id));
+ return keys;
+}
+
+GpgFrontend::KeyLinkListPtr GpgFrontend::GpgKeyGetter::GetKeysCopy(
+ const GpgFrontend::KeyLinkListPtr& keys) {
+ auto keys_copy = std::make_unique<GpgKeyLinkList>();
+ for (const auto& key : *keys) keys_copy->push_back(key.Copy());
+ return keys_copy;
+}
+
+GpgFrontend::KeyListPtr GpgFrontend::GpgKeyGetter::GetKeysCopy(
+ const GpgFrontend::KeyListPtr& keys) {
+ auto keys_copy = std::make_unique<KeyArgsList>();
+ for (const auto& key : *keys) keys_copy->push_back(key.Copy());
+ return keys_copy;
+}
diff --git a/src/core/function/gpg/GpgKeyGetter.h b/src/core/function/gpg/GpgKeyGetter.h
new file mode 100644
index 00000000..cde027a0
--- /dev/null
+++ b/src/core/function/gpg/GpgKeyGetter.h
@@ -0,0 +1,110 @@
+/**
+ * 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_ZH_CN_TS_GPGKEYGETTER_H
+#define GPGFRONTEND_ZH_CN_TS_GPGKEYGETTER_H
+
+#include "core/GpgContext.h"
+#include "core/GpgFunctionObject.h"
+#include "core/GpgModel.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief
+ *
+ */
+class GpgKeyGetter : public SingletonFunctionObject<GpgKeyGetter> {
+ public:
+ /**
+ * @brief Construct a new Gpg Key Getter object
+ *
+ * @param channel
+ */
+ explicit GpgKeyGetter(
+ int channel = SingletonFunctionObject::GetDefaultChannel())
+ : SingletonFunctionObject<GpgKeyGetter>(channel) {}
+
+ /**
+ * @brief Get the Key object
+ *
+ * @param fpr
+ * @return GpgKey
+ */
+ GpgKey GetKey(const std::string& fpr);
+
+ /**
+ * @brief Get the Keys object
+ *
+ * @param ids
+ * @return KeyListPtr
+ */
+ KeyListPtr GetKeys(const KeyIdArgsListPtr& ids);
+
+ /**
+ * @brief Get the Pubkey object
+ *
+ * @param fpr
+ * @return GpgKey
+ */
+ GpgKey GetPubkey(const std::string& fpr);
+
+ /**
+ * @brief
+ *
+ * @return KeyLinkListPtr
+ */
+ KeyLinkListPtr FetchKey();
+
+ /**
+ * @brief Get the Keys Copy object
+ *
+ * @param keys
+ * @return KeyListPtr
+ */
+ static KeyListPtr GetKeysCopy(const KeyListPtr& keys);
+
+ /**
+ * @brief Get the Keys Copy object
+ *
+ * @param keys
+ * @return KeyLinkListPtr
+ */
+ static KeyLinkListPtr GetKeysCopy(const KeyLinkListPtr& keys);
+
+ private:
+ /**
+ * @brief
+ *
+ */
+ GpgContext& ctx_ =
+ GpgContext::GetInstance(SingletonFunctionObject::GetChannel());
+};
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_ZH_CN_TS_GPGKEYGETTER_H
diff --git a/src/core/function/gpg/GpgKeyImportExporter.cpp b/src/core/function/gpg/GpgKeyImportExporter.cpp
new file mode 100644
index 00000000..0f1ebfa2
--- /dev/null
+++ b/src/core/function/gpg/GpgKeyImportExporter.cpp
@@ -0,0 +1,178 @@
+/**
+ * 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 "GpgKeyImportExporter.h"
+
+#include "GpgConstants.h"
+#include "GpgKeyGetter.h"
+
+/**
+ * Import key pair
+ * @param inBuffer input byte array
+ * @return Import information
+ */
+GpgFrontend::GpgImportInformation GpgFrontend::GpgKeyImportExporter::ImportKey(
+ StdBypeArrayPtr in_buffer) {
+ if (in_buffer->empty()) return {};
+
+ GpgData data_in(in_buffer->data(), in_buffer->size());
+ auto err = check_gpg_error(gpgme_op_import(ctx_, data_in));
+ if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) return {};
+
+ gpgme_import_result_t result;
+ result = gpgme_op_import_result(ctx_);
+ gpgme_import_status_t status = result->imports;
+ auto import_info = std::make_unique<GpgImportInformation>(result);
+ while (status != nullptr) {
+ GpgImportedKey key;
+ key.import_status = static_cast<int>(status->status);
+ key.fpr = status->fpr;
+ import_info->importedKeys.emplace_back(key);
+ status = status->next;
+ }
+
+ return *import_info;
+}
+
+/**
+ * Export Key
+ * @param uid_list key ids
+ * @param out_buffer output byte array
+ * @return if success
+ */
+bool GpgFrontend::GpgKeyImportExporter::ExportKeys(KeyIdArgsListPtr& uid_list,
+ ByteArrayPtr& out_buffer,
+ bool secret) const {
+ if (uid_list->empty()) return false;
+
+ int _mode = 0;
+ if (secret) _mode |= GPGME_EXPORT_MODE_SECRET;
+
+ auto keys = GpgKeyGetter::GetInstance().GetKeys(uid_list);
+ auto keys_array = new gpgme_key_t[keys->size() + 1];
+
+ int index = 0;
+ for (const auto& key : *keys) {
+ keys_array[index++] = gpgme_key_t(key);
+ }
+ keys_array[index] = nullptr;
+
+ GpgData data_out;
+ auto err = gpgme_op_export_keys(ctx_, keys_array, _mode, data_out);
+ if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) return false;
+
+ delete[] keys_array;
+
+ DLOG(INFO) << "exportKeys read_bytes"
+ << gpgme_data_seek(data_out, 0, SEEK_END);
+
+ auto temp_out_buffer = data_out.Read2Buffer();
+
+ swap(temp_out_buffer, out_buffer);
+
+ return true;
+}
+
+/**
+ * Export keys
+ * @param keys keys used
+ * @param outBuffer output byte array
+ * @return if success
+ */
+bool GpgFrontend::GpgKeyImportExporter::ExportKeys(const KeyArgsList& keys,
+ ByteArrayPtr& out_buffer,
+ bool secret) const {
+ KeyIdArgsListPtr key_ids = std::make_unique<std::vector<std::string>>();
+ for (const auto& key : keys) key_ids->push_back(key.GetId());
+ return ExportKeys(key_ids, out_buffer, secret);
+}
+
+/**
+ * Export the secret key of a key pair(including subkeys)
+ * @param key target key pair
+ * @param outBuffer output byte array
+ * @return if successful
+ */
+bool GpgFrontend::GpgKeyImportExporter::ExportSecretKey(
+ const GpgKey& key, ByteArrayPtr& out_buffer) const {
+ DLOG(INFO) << "Export Secret Key" << key.GetId().c_str();
+
+ gpgme_key_t target_key[2] = {gpgme_key_t(key), nullptr};
+
+ GpgData data_out;
+ // export private key to outBuffer
+ gpgme_error_t err = gpgme_op_export_keys(ctx_, target_key,
+ GPGME_EXPORT_MODE_SECRET, data_out);
+
+ auto temp_out_buffer = data_out.Read2Buffer();
+ std::swap(out_buffer, temp_out_buffer);
+
+ return check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR;
+}
+
+bool GpgFrontend::GpgKeyImportExporter::ExportKey(
+ const GpgFrontend::GpgKey& key,
+ GpgFrontend::ByteArrayPtr& out_buffer) const {
+ GpgData data_out;
+ auto err = gpgme_op_export(ctx_, key.GetId().c_str(), 0, data_out);
+
+ DLOG(INFO) << "exportKeys read_bytes"
+ << gpgme_data_seek(data_out, 0, SEEK_END);
+
+ auto temp_out_buffer = data_out.Read2Buffer();
+ std::swap(out_buffer, temp_out_buffer);
+ return check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR;
+}
+
+bool GpgFrontend::GpgKeyImportExporter::ExportKeyOpenSSH(
+ const GpgFrontend::GpgKey& key,
+ GpgFrontend::ByteArrayPtr& out_buffer) const {
+ GpgData data_out;
+ auto err = gpgme_op_export(ctx_, key.GetId().c_str(), GPGME_EXPORT_MODE_SSH,
+ data_out);
+
+ DLOG(INFO) << "read_bytes" << gpgme_data_seek(data_out, 0, SEEK_END);
+
+ auto temp_out_buffer = data_out.Read2Buffer();
+ std::swap(out_buffer, temp_out_buffer);
+ return check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR;
+}
+
+bool GpgFrontend::GpgKeyImportExporter::ExportSecretKeyShortest(
+ const GpgFrontend::GpgKey& key,
+ GpgFrontend::ByteArrayPtr& out_buffer) const {
+ GpgData data_out;
+ auto err = gpgme_op_export(ctx_, key.GetId().c_str(),
+ GPGME_EXPORT_MODE_MINIMAL, data_out);
+
+ DLOG(INFO) << "read_bytes" << gpgme_data_seek(data_out, 0, SEEK_END);
+
+ auto temp_out_buffer = data_out.Read2Buffer();
+ std::swap(out_buffer, temp_out_buffer);
+ return check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR;
+}
diff --git a/src/core/function/gpg/GpgKeyImportExporter.h b/src/core/function/gpg/GpgKeyImportExporter.h
new file mode 100644
index 00000000..d7e6deae
--- /dev/null
+++ b/src/core/function/gpg/GpgKeyImportExporter.h
@@ -0,0 +1,195 @@
+/**
+ * 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 _GPGKEYIMPORTEXPORTOR_H
+#define _GPGKEYIMPORTEXPORTOR_H
+
+#include <string>
+
+#include "core/GpgConstants.h"
+#include "core/GpgContext.h"
+#include "core/GpgFunctionObject.h"
+#include "core/GpgModel.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief
+ *
+ */
+class GpgImportedKey {
+ public:
+ std::string fpr; ///<
+ int import_status; ///<
+};
+
+typedef std::list<GpgImportedKey> GpgImportedKeyList; ///<
+
+/**
+ * @brief
+ *
+ */
+class GpgImportInformation {
+ public:
+ GpgImportInformation() = default;
+
+ /**
+ * @brief Construct a new Gpg Import Information object
+ *
+ * @param result
+ */
+ explicit GpgImportInformation(gpgme_import_result_t result) {
+ if (result->unchanged) unchanged = result->unchanged;
+ if (result->considered) considered = result->considered;
+ if (result->no_user_id) no_user_id = result->no_user_id;
+ if (result->imported) imported = result->imported;
+ if (result->imported_rsa) imported_rsa = result->imported_rsa;
+ if (result->unchanged) unchanged = result->unchanged;
+ if (result->new_user_ids) new_user_ids = result->new_user_ids;
+ if (result->new_sub_keys) new_sub_keys = result->new_sub_keys;
+ if (result->new_signatures) new_signatures = result->new_signatures;
+ if (result->new_revocations) new_revocations = result->new_revocations;
+ if (result->secret_read) secret_read = result->secret_read;
+ if (result->secret_imported) secret_imported = result->secret_imported;
+ if (result->secret_unchanged) secret_unchanged = result->secret_unchanged;
+ if (result->not_imported) not_imported = result->not_imported;
+ }
+
+ int considered = 0; ///<
+ int no_user_id = 0; ///<
+ int imported = 0; ///<
+ int imported_rsa = 0; ///<
+ int unchanged = 0; ///<
+ int new_user_ids = 0; ///<
+ int new_sub_keys = 0; ///<
+ int new_signatures = 0; ///<
+ int new_revocations = 0; ///<
+ int secret_read = 0; ///<
+ int secret_imported = 0; ///<
+ int secret_unchanged = 0; ///<
+ int not_imported = 0; ///<
+ GpgImportedKeyList importedKeys; ///<
+};
+
+/**
+ * @brief
+ *
+ */
+class GpgKeyImportExporter
+ : public SingletonFunctionObject<GpgKeyImportExporter> {
+ public:
+ /**
+ * @brief Construct a new Gpg Key Import Exporter object
+ *
+ * @param channel
+ */
+ explicit GpgKeyImportExporter(
+ int channel = SingletonFunctionObject::GetDefaultChannel())
+ : SingletonFunctionObject<GpgKeyImportExporter>(channel) {}
+
+ /**
+ * @brief
+ *
+ * @param inBuffer
+ * @return GpgImportInformation
+ */
+ GpgImportInformation ImportKey(StdBypeArrayPtr inBuffer);
+
+ /**
+ * @brief
+ *
+ * @param uid_list
+ * @param out_buffer
+ * @param secret
+ * @return true
+ * @return false
+ */
+ bool ExportKeys(KeyIdArgsListPtr& uid_list, ByteArrayPtr& out_buffer,
+ bool secret = false) const;
+
+ /**
+ * @brief
+ *
+ * @param keys
+ * @param outBuffer
+ * @param secret
+ * @return true
+ * @return false
+ */
+ bool ExportKeys(const KeyArgsList& keys, ByteArrayPtr& outBuffer,
+ bool secret = false) const;
+
+ /**
+ * @brief
+ *
+ * @param key
+ * @param out_buffer
+ * @return true
+ * @return false
+ */
+ bool ExportKey(const GpgKey& key, ByteArrayPtr& out_buffer) const;
+
+ /**
+ * @brief
+ *
+ * @param key
+ * @param out_buffer
+ * @return true
+ * @return false
+ */
+ bool ExportKeyOpenSSH(const GpgKey& key, ByteArrayPtr& out_buffer) const;
+
+ /**
+ * @brief
+ *
+ * @param key
+ * @param outBuffer
+ * @return true
+ * @return false
+ */
+ bool ExportSecretKey(const GpgKey& key, ByteArrayPtr& outBuffer) const;
+
+ /**
+ * @brief
+ *
+ * @param key
+ * @param outBuffer
+ * @return true
+ * @return false
+ */
+ bool ExportSecretKeyShortest(const GpgKey& key,
+ ByteArrayPtr& outBuffer) const;
+
+ private:
+ GpgContext& ctx_ =
+ GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); ///<
+};
+
+} // namespace GpgFrontend
+
+#endif // _GPGKEYIMPORTEXPORTOR_H \ No newline at end of file
diff --git a/src/core/function/gpg/GpgKeyManager.cpp b/src/core/function/gpg/GpgKeyManager.cpp
new file mode 100644
index 00000000..c17df49e
--- /dev/null
+++ b/src/core/function/gpg/GpgKeyManager.cpp
@@ -0,0 +1,92 @@
+/**
+ * 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 "GpgKeyManager.h"
+
+#include <boost/date_time/posix_time/conversion.hpp>
+#include <string>
+
+#include "GpgBasicOperator.h"
+#include "GpgKeyGetter.h"
+
+bool GpgFrontend::GpgKeyManager::SignKey(
+ const GpgFrontend::GpgKey& target, GpgFrontend::KeyArgsList& keys,
+ const std::string& uid,
+ const std::unique_ptr<boost::posix_time::ptime>& expires) {
+ using namespace boost::posix_time;
+
+ GpgBasicOperator::GetInstance().SetSigners(keys);
+
+ unsigned int flags = 0;
+ unsigned int expires_time_t = 0;
+
+ if (expires == nullptr)
+ flags |= GPGME_KEYSIGN_NOEXPIRE;
+ else
+ expires_time_t = to_time_t(*expires);
+
+ auto err = check_gpg_error(gpgme_op_keysign(
+ ctx_, gpgme_key_t(target), uid.c_str(), expires_time_t, flags));
+
+ return check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR;
+}
+
+bool GpgFrontend::GpgKeyManager::RevSign(
+ const GpgFrontend::GpgKey& key,
+ const GpgFrontend::SignIdArgsListPtr& signature_id) {
+ auto& key_getter = GpgKeyGetter::GetInstance();
+
+ for (const auto& sign_id : *signature_id) {
+ auto signing_key = key_getter.GetKey(sign_id.first);
+ assert(signing_key.IsGood());
+ auto err = check_gpg_error(gpgme_op_revsig(ctx_, gpgme_key_t(key),
+ gpgme_key_t(signing_key),
+ sign_id.second.c_str(), 0));
+ if (check_gpg_error_2_err_code(err) != GPG_ERR_NO_ERROR) return false;
+ }
+ return true;
+}
+
+bool GpgFrontend::GpgKeyManager::SetExpire(
+ const GpgFrontend::GpgKey& key, std::unique_ptr<GpgSubKey>& subkey,
+ std::unique_ptr<boost::posix_time::ptime>& expires) {
+ using namespace boost::posix_time;
+
+ unsigned long expires_time = 0;
+
+ if (expires != nullptr) expires_time = to_time_t(ptime(*expires));
+
+ const char* sub_fprs = nullptr;
+
+ if (subkey != nullptr) sub_fprs = subkey->GetFingerprint().c_str();
+
+ auto err = check_gpg_error(
+ gpgme_op_setexpire(ctx_, gpgme_key_t(key), expires_time, sub_fprs, 0));
+
+ return check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR;
+}
diff --git a/src/core/function/gpg/GpgKeyManager.h b/src/core/function/gpg/GpgKeyManager.h
new file mode 100644
index 00000000..5bcac545
--- /dev/null
+++ b/src/core/function/gpg/GpgKeyManager.h
@@ -0,0 +1,93 @@
+/**
+ * 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_ZH_CN_TS_GPGKEYMANAGER_H
+#define GPGFRONTEND_ZH_CN_TS_GPGKEYMANAGER_H
+
+#include "core/GpgContext.h"
+#include "core/GpgFunctionObject.h"
+#include "core/GpgModel.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief
+ *
+ */
+class GpgKeyManager : public SingletonFunctionObject<GpgKeyManager> {
+ public:
+ /**
+ * @brief Construct a new Gpg Key Manager object
+ *
+ * @param channel
+ */
+ explicit GpgKeyManager(
+ int channel = SingletonFunctionObject::GetDefaultChannel())
+ : SingletonFunctionObject<GpgKeyManager>(channel) {}
+
+ /**
+ * @brief Sign a key pair(actually a certain uid)
+ * @param target target key pair
+ * @param uid target
+ * @param expires expire date and time of the signature
+ * @return if successful
+ */
+ bool SignKey(const GpgKey& target, KeyArgsList& keys, const std::string& uid,
+ const std::unique_ptr<boost::posix_time::ptime>& expires);
+
+ /**
+ * @brief
+ *
+ * @param key
+ * @param signature_id
+ * @return true
+ * @return false
+ */
+ bool RevSign(const GpgFrontend::GpgKey& key,
+ const GpgFrontend::SignIdArgsListPtr& signature_id);
+
+ /**
+ * @brief Set the Expire object
+ *
+ * @param key
+ * @param subkey
+ * @param expires
+ * @return true
+ * @return false
+ */
+ bool SetExpire(const GpgKey& key, std::unique_ptr<GpgSubKey>& subkey,
+ std::unique_ptr<boost::posix_time::ptime>& expires);
+
+ private:
+ GpgContext& ctx_ =
+ GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); ///<
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_ZH_CN_TS_GPGKEYMANAGER_H
diff --git a/src/core/function/gpg/GpgKeyOpera.cpp b/src/core/function/gpg/GpgKeyOpera.cpp
new file mode 100644
index 00000000..23dcae9f
--- /dev/null
+++ b/src/core/function/gpg/GpgKeyOpera.cpp
@@ -0,0 +1,293 @@
+/**
+ * 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 "GpgKeyOpera.h"
+
+#include <boost/asio.hpp>
+#include <boost/date_time/posix_time/conversion.hpp>
+#include <boost/format.hpp>
+#include <boost/process/async_pipe.hpp>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "core/GpgConstants.h"
+#include "core/GpgGenKeyInfo.h"
+#include "GpgCommandExecutor.h"
+#include "GpgKeyGetter.h"
+
+/**
+ * Delete keys
+ * @param uidList key ids
+ */
+void GpgFrontend::GpgKeyOpera::DeleteKeys(
+ GpgFrontend::KeyIdArgsListPtr key_ids) {
+ GpgError err;
+ for (const auto& tmp : *key_ids) {
+ auto key = GpgKeyGetter::GetInstance().GetKey(tmp);
+ if (key.IsGood()) {
+ err = check_gpg_error(
+ gpgme_op_delete_ext(ctx_, gpgme_key_t(key),
+ GPGME_DELETE_ALLOW_SECRET | GPGME_DELETE_FORCE));
+ assert(gpg_err_code(err) == GPG_ERR_NO_ERROR);
+ } else {
+ LOG(WARNING) << "GpgKeyOpera DeleteKeys get key failed" << tmp;
+ }
+ }
+}
+
+/**
+ * Set the expire date and time of a key pair(actually the primary key) or
+ * subkey
+ * @param key target key pair
+ * @param subkey null if primary key
+ * @param expires date and time
+ * @return if successful
+ */
+GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::SetExpire(
+ const GpgKey& key, const SubkeyId& subkey_fpr,
+ std::unique_ptr<boost::posix_time::ptime>& expires) {
+ unsigned long expires_time = 0;
+
+ if (expires != nullptr) {
+ using namespace boost::posix_time;
+ using namespace std::chrono;
+ expires_time =
+ to_time_t(*expires) - system_clock::to_time_t(system_clock::now());
+ }
+
+ LOG(INFO) << key.GetId() << subkey_fpr << expires_time;
+
+ GpgError err;
+ if (key.GetFingerprint() == subkey_fpr || subkey_fpr.empty())
+ err = gpgme_op_setexpire(ctx_, gpgme_key_t(key), expires_time, nullptr, 0);
+ else
+ err = gpgme_op_setexpire(ctx_, gpgme_key_t(key), expires_time,
+ subkey_fpr.c_str(), 0);
+
+ return err;
+}
+
+/**
+ * Generate revoke cert of a key pair
+ * @param key target key pair
+ * @param outputFileName out file name(path)
+ * @return the process doing this job
+ */
+void GpgFrontend::GpgKeyOpera::GenerateRevokeCert(
+ const GpgKey& key, const std::string& output_file_name) {
+ auto args = std::vector<std::string>{"--no-tty",
+ "--command-fd",
+ "0",
+ "--status-fd",
+ "1",
+ "-o",
+ output_file_name,
+ "--gen-revoke",
+ key.GetFingerprint()};
+
+ using boost::asio::async_write;
+ using boost::process::async_pipe;
+#ifndef WINDOWS
+ GpgCommandExecutor::GetInstance().Execute(
+ args, [](async_pipe& in, async_pipe& out) -> void {
+ // boost::asio::streambuf buff;
+ // boost::asio::read_until(in, buff, '\n');
+ //
+ // std::istream is(&buff);
+ //
+ // while (!is.eof()) {
+ // std::string line;
+ // is >> line;
+ // LOG(INFO) << "line" << line;
+ // boost::algorithm::trim(line);
+ // if (line == std::string("[GNUPG:] GET_BOOL
+ // gen_revoke.okay")) {
+ //
+ // } else if (line ==
+ // std::string(
+ // "[GNUPG:] GET_LINE
+ // ask_revocation_reason.code")) {
+ //
+ // } else if (line ==
+ // std::string(
+ // "[GNUPG:] GET_LINE
+ // ask_revocation_reason.text")) {
+ //
+ // } else if (line ==
+ // std::string("[GNUPG:] GET_BOOL
+ // openfile.overwrite.okay")) {
+ //
+ // } else if (line ==
+ // std::string(
+ // "[GNUPG:] GET_BOOL
+ // ask_revocation_reason.okay")) {
+ //
+ // }
+ // }
+ });
+#endif
+}
+
+/**
+ * Generate a new key pair
+ * @param params key generation args
+ * @return error information
+ */
+GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::GenerateKey(
+ const std::unique_ptr<GenKeyInfo>& params, GpgGenKeyResult& result) {
+ auto userid_utf8 = params->GetUserid();
+ const char* userid = userid_utf8.c_str();
+ auto algo_utf8 = params->GetAlgo() + params->GetKeySizeStr();
+
+ LOG(INFO) << "params" << params->GetAlgo() << params->GetKeySizeStr();
+
+ const char* algo = algo_utf8.c_str();
+ unsigned long expires = 0;
+ {
+ using namespace boost::posix_time;
+ using namespace std::chrono;
+ expires = to_time_t(ptime(params->GetExpireTime())) -
+ system_clock::to_time_t(system_clock::now());
+ }
+
+ GpgError err;
+
+ if (ctx_.GetInfo().GnupgVersion >= "2.1.0") {
+ unsigned int flags = 0;
+
+ if (!params->IsSubKey()) flags |= GPGME_CREATE_CERT;
+ if (params->IsAllowEncryption()) flags |= GPGME_CREATE_ENCR;
+ if (params->IsAllowSigning()) flags |= GPGME_CREATE_SIGN;
+ if (params->IsAllowAuthentication()) flags |= GPGME_CREATE_AUTH;
+ if (params->IsNonExpired()) flags |= GPGME_CREATE_NOEXPIRE;
+ if (params->IsNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD;
+
+ LOG(INFO) << "args: " << userid << algo << expires << flags;
+
+ err = gpgme_op_createkey(ctx_, userid, algo, 0, expires, nullptr, flags);
+
+ } else {
+ std::stringstream ss;
+ auto param_format =
+ boost::format{
+ "<GnupgKeyParms format=\"internal\">\n"
+ "Key-Type: %1%\n"
+ "Key-Usage: sign\n"
+ "Key-Length: %2%\n"
+ "Name-Real: %3%\n"
+ "Name-Comment: %4%\n"
+ "Name-Email: %5%\n"} %
+ params->GetAlgo() % params->GetKeyLength() % params->GetName() %
+ params->GetComment() % params->GetEmail();
+ ss << param_format;
+
+ if (!params->IsNonExpired()) {
+ auto date = params->GetExpireTime().date();
+ ss << boost::format{"Expire-Date: %1%\n"} % to_iso_string(date);
+ } else
+ ss << boost::format{"Expire-Date: 0\n"};
+ if (!params->IsNoPassPhrase())
+ ss << boost::format{"Passphrase: %1%\n"} % params->GetPassPhrase();
+
+ ss << "</GnupgKeyParms>";
+
+ DLOG(INFO) << "params" << std::endl << ss.str();
+
+ err = gpgme_op_genkey(ctx_, ss.str().c_str(), nullptr, nullptr);
+ }
+
+ if (check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR) {
+ auto temp_result = _new_result(gpgme_op_genkey_result(ctx_));
+ std::swap(temp_result, result);
+ }
+
+ return check_gpg_error(err);
+}
+
+/**
+ * Generate a new subkey of a certain key pair
+ * @param key target key pair
+ * @param params opera args
+ * @return error info
+ */
+GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::GenerateSubkey(
+ const GpgKey& key, const std::unique_ptr<GenKeyInfo>& params) {
+ if (!params->IsSubKey()) return GPG_ERR_CANCELED;
+
+ auto algo_utf8 = (params->GetAlgo() + params->GetKeySizeStr());
+ const char* algo = algo_utf8.c_str();
+ unsigned long expires = 0;
+ {
+ using namespace boost::posix_time;
+ using namespace std::chrono;
+ expires = to_time_t(ptime(params->GetExpireTime())) -
+ system_clock::to_time_t(system_clock::now());
+ }
+ unsigned int flags = 0;
+
+ if (!params->IsSubKey()) flags |= GPGME_CREATE_CERT;
+ if (params->IsAllowEncryption()) flags |= GPGME_CREATE_ENCR;
+ if (params->IsAllowSigning()) flags |= GPGME_CREATE_SIGN;
+ if (params->IsAllowAuthentication()) flags |= GPGME_CREATE_AUTH;
+ if (params->IsNonExpired()) flags |= GPGME_CREATE_NOEXPIRE;
+
+ flags |= GPGME_CREATE_NOPASSWD;
+
+ LOG(INFO) << "GpgFrontend::GpgKeyOpera::GenerateSubkey Args: " << key.GetId()
+ << algo << expires << flags;
+
+ auto err =
+ gpgme_op_createsubkey(ctx_, gpgme_key_t(key), algo, 0, expires, flags);
+ return check_gpg_error(err);
+}
+
+GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::ModifyPassword(
+ const GpgFrontend::GpgKey& key) {
+ if (ctx_.GetInfo().GnupgVersion < "2.0.15") {
+ LOG(ERROR) << _("operator not support");
+ return GPG_ERR_NOT_SUPPORTED;
+ }
+ auto err = gpgme_op_passwd(ctx_, gpgme_key_t(key), 0);
+ return check_gpg_error(err);
+}
+GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::ModifyTOFUPolicy(
+ const GpgFrontend::GpgKey& key, gpgme_tofu_policy_t tofu_policy) {
+ if (ctx_.GetInfo().GnupgVersion < "2.1.10") {
+ LOG(ERROR) << _("operator not support");
+ return GPG_ERR_NOT_SUPPORTED;
+ }
+ auto err = gpgme_op_tofu_policy(ctx_, gpgme_key_t(key), tofu_policy);
+ return check_gpg_error(err);
+}
+
+void GpgFrontend::GpgKeyOpera::DeleteKey(const GpgFrontend::KeyId& key_id) {
+ auto keys = std::make_unique<KeyIdArgsList>();
+ keys->push_back(key_id);
+ DeleteKeys(std::move(keys));
+}
diff --git a/src/core/function/gpg/GpgKeyOpera.h b/src/core/function/gpg/GpgKeyOpera.h
new file mode 100644
index 00000000..04571c10
--- /dev/null
+++ b/src/core/function/gpg/GpgKeyOpera.h
@@ -0,0 +1,135 @@
+/**
+ * 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 _GPGKEYOPERA_H
+#define _GPGKEYOPERA_H
+
+#include "core/GpgConstants.h"
+#include "core/GpgContext.h"
+#include "core/GpgModel.h"
+
+namespace GpgFrontend {
+/**
+ * @brief
+ *
+ */
+class GenKeyInfo;
+
+/**
+ * @brief
+ *
+ */
+class GpgKeyOpera : public SingletonFunctionObject<GpgKeyOpera> {
+ public:
+ /**
+ * @brief Construct a new Gpg Key Opera object
+ *
+ * @param channel
+ */
+ explicit GpgKeyOpera(
+ int channel = SingletonFunctionObject::GetDefaultChannel())
+ : SingletonFunctionObject<GpgKeyOpera>(channel) {}
+
+ /**
+ * @brief
+ *
+ * @param key_ids
+ */
+ void DeleteKeys(KeyIdArgsListPtr key_ids);
+
+ /**
+ * @brief
+ *
+ * @param key_id
+ */
+ void DeleteKey(const KeyId& key_id);
+
+ /**
+ * @brief Set the Expire object
+ *
+ * @param key
+ * @param subkey_fpr
+ * @param expires
+ * @return GpgError
+ */
+ GpgError SetExpire(const GpgKey& key, const SubkeyId& subkey_fpr,
+ std::unique_ptr<boost::posix_time::ptime>& expires);
+
+ /**
+ * @brief
+ *
+ * @param key
+ * @param output_file_name
+ */
+ static void GenerateRevokeCert(const GpgKey& key,
+ const std::string& output_file_name);
+
+ /**
+ * @brief
+ *
+ * @param key
+ * @return GpgFrontend::GpgError
+ */
+ GpgFrontend::GpgError ModifyPassword(const GpgKey& key);
+
+ /**
+ * @brief
+ *
+ * @param key
+ * @param tofu_policy
+ * @return GpgFrontend::GpgError
+ */
+ GpgFrontend::GpgError ModifyTOFUPolicy(const GpgKey& key,
+ gpgme_tofu_policy_t tofu_policy);
+ /**
+ * @brief
+ *
+ * @param params
+ * @param result
+ * @return GpgFrontend::GpgError
+ */
+ GpgFrontend::GpgError GenerateKey(const std::unique_ptr<GenKeyInfo>& params,
+ GpgGenKeyResult& result);
+
+ /**
+ * @brief
+ *
+ * @param key
+ * @param params
+ * @return GpgFrontend::GpgError
+ */
+ GpgFrontend::GpgError GenerateSubkey(
+ const GpgKey& key, const std::unique_ptr<GenKeyInfo>& params);
+
+ private:
+ GpgContext& ctx_ =
+ GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); ///<
+};
+} // namespace GpgFrontend
+
+#endif // _GPGKEYOPERA_H \ No newline at end of file
diff --git a/src/core/function/gpg/GpgUIDOperator.cpp b/src/core/function/gpg/GpgUIDOperator.cpp
new file mode 100644
index 00000000..dd0c43f6
--- /dev/null
+++ b/src/core/function/gpg/GpgUIDOperator.cpp
@@ -0,0 +1,68 @@
+/**
+ * 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 "GpgUIDOperator.h"
+
+#include "boost/format.hpp"
+
+bool GpgFrontend::GpgUIDOperator::AddUID(const GpgFrontend::GpgKey& key,
+ const std::string& uid) {
+ auto err = gpgme_op_adduid(ctx_, gpgme_key_t(key), uid.c_str(), 0);
+ if (check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR)
+ return true;
+ else
+ return false;
+}
+
+bool GpgFrontend::GpgUIDOperator::RevUID(const GpgFrontend::GpgKey& key,
+ const std::string& uid) {
+ auto err =
+ check_gpg_error(gpgme_op_revuid(ctx_, gpgme_key_t(key), uid.c_str(), 0));
+ if (check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR)
+ return true;
+ else
+ return false;
+}
+
+bool GpgFrontend::GpgUIDOperator::SetPrimaryUID(const GpgFrontend::GpgKey& key,
+ const std::string& uid) {
+ auto err = check_gpg_error(gpgme_op_set_uid_flag(
+ ctx_, gpgme_key_t(key), uid.c_str(), "primary", nullptr));
+ if (check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR)
+ return true;
+ else
+ return false;
+}
+bool GpgFrontend::GpgUIDOperator::AddUID(const GpgFrontend::GpgKey& key,
+ const std::string& name,
+ const std::string& comment,
+ const std::string& email) {
+ LOG(INFO) << "GpgFrontend::UidOperator::AddUID" << name << comment << email;
+ auto uid = boost::format("%1%(%2%)<%3%>") % name % comment % email;
+ return AddUID(key, uid.str());
+}
diff --git a/src/core/function/gpg/GpgUIDOperator.h b/src/core/function/gpg/GpgUIDOperator.h
new file mode 100644
index 00000000..479505e5
--- /dev/null
+++ b/src/core/function/gpg/GpgUIDOperator.h
@@ -0,0 +1,88 @@
+/**
+ * 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_ZH_CN_TS_UIDOPERATOR_H
+#define GPGFRONTEND_ZH_CN_TS_UIDOPERATOR_H
+
+#include "core/GpgContext.h"
+#include "core/GpgModel.h"
+
+namespace GpgFrontend {
+/**
+ * @brief
+ *
+ */
+class GpgUIDOperator : public SingletonFunctionObject<GpgUIDOperator> {
+ public:
+ explicit GpgUIDOperator(
+ int channel = SingletonFunctionObject::GetDefaultChannel())
+ : SingletonFunctionObject<GpgUIDOperator>(channel) {}
+
+ /**
+ * create a new uid in certain key pair
+ * @param key target key pair
+ * @param uid uid args(combine name&comment&email)
+ * @return if successful
+ */
+ bool AddUID(const GpgKey& key, const std::string& uid);
+
+ /**
+ * create a new uid in certain key pair
+ * @param key target key pair
+ * @param name
+ * @param comment
+ * @param email
+ * @return
+ */
+ bool AddUID(const GpgKey& key, const std::string& name,
+ const std::string& comment, const std::string& email);
+
+ /**
+ * Revoke(Delete) UID from certain key pair
+ * @param key target key pair
+ * @param uid target uid
+ * @return if successful
+ */
+ bool RevUID(const GpgKey& key, const std::string& uid);
+
+ /**
+ * Set one of a uid of a key pair as primary
+ * @param key target key pair
+ * @param uid target uid
+ * @return if successful
+ */
+ bool SetPrimaryUID(const GpgKey& key, const std::string& uid);
+
+ private:
+ GpgContext& ctx_ =
+ GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); ///<
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_ZH_CN_TS_UIDOPERATOR_H
diff --git a/src/core/function/result_analyse/GpgDecryptResultAnalyse.cpp b/src/core/function/result_analyse/GpgDecryptResultAnalyse.cpp
new file mode 100644
index 00000000..ff3d2e27
--- /dev/null
+++ b/src/core/function/result_analyse/GpgDecryptResultAnalyse.cpp
@@ -0,0 +1,97 @@
+/**
+ * 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 "GpgDecryptResultAnalyse.h"
+
+#include "function/gpg/GpgKeyGetter.h"
+
+GpgFrontend::GpgDecryptResultAnalyse::GpgDecryptResultAnalyse(GpgError m_error,
+ GpgDecrResult m_result)
+ : error_(m_error), result_(std::move(m_result)) {}
+
+void GpgFrontend::GpgDecryptResultAnalyse::do_analyse() {
+ stream_ << "[#] " << _("Decrypt Operation");
+
+ if (gpgme_err_code(error_) == GPG_ERR_NO_ERROR) {
+ stream_ << "[" << _("Success") << "]" << std::endl;
+ } else {
+ stream_ << "[" << _("Failed") << "] " << gpgme_strerror(error_)
+ << std::endl;
+ set_status(-1);
+ if (result_ != nullptr && result_->unsupported_algorithm != nullptr) {
+ stream_ << "------------>" << std::endl;
+ stream_ << _("Unsupported Algo") << ": " << result_->unsupported_algorithm
+ << std::endl;
+ }
+ }
+
+ if (result_ != nullptr && result_->recipients != nullptr) {
+ stream_ << "------------>" << std::endl;
+ if (result_->file_name != nullptr) {
+ stream_ << _("File Name") << ": " << result_->file_name << std::endl;
+ stream_ << std::endl;
+ }
+ if (result_->is_mime) {
+ stream_ << _("MIME") << ": " << _("true") << std::endl;
+ }
+
+ auto recipient = result_->recipients;
+ if (recipient != nullptr) stream_ << _("Recipient(s)") << ": " << std::endl;
+ while (recipient != nullptr) {
+ print_recipient(stream_, recipient);
+ recipient = recipient->next;
+ }
+ stream_ << "<------------" << std::endl;
+ }
+
+ stream_ << std::endl;
+}
+
+void GpgFrontend::GpgDecryptResultAnalyse::print_recipient(
+ std::stringstream &stream, gpgme_recipient_t recipient) {
+ // check
+ if (recipient->keyid == nullptr) return;
+
+ stream << " {>} " << _("Recipient") << ": ";
+ auto key = GpgFrontend::GpgKeyGetter::GetInstance().GetKey(recipient->keyid);
+ if (key.IsGood()) {
+ stream << key.GetName().c_str();
+ if (!key.GetEmail().empty()) {
+ stream << "<" << key.GetEmail().c_str() << ">";
+ }
+ } else {
+ stream << "<" << _("Unknown") << ">";
+ set_status(0);
+ }
+
+ stream << std::endl;
+
+ stream << " " << _("Key ID") << ": " << recipient->keyid << std::endl;
+ stream << " " << _("Public Key Algo") << ": "
+ << gpgme_pubkey_algo_name(recipient->pubkey_algo) << std::endl;
+}
diff --git a/src/core/function/result_analyse/GpgDecryptResultAnalyse.h b/src/core/function/result_analyse/GpgDecryptResultAnalyse.h
new file mode 100644
index 00000000..af42f995
--- /dev/null
+++ b/src/core/function/result_analyse/GpgDecryptResultAnalyse.h
@@ -0,0 +1,73 @@
+/**
+ * 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_GPGDECRYPTRESULTANALYSE_H
+#define GPGFRONTEND_GPGDECRYPTRESULTANALYSE_H
+
+#include "GpgResultAnalyse.h"
+#include "core/GpgConstants.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief
+ *
+ */
+class GpgDecryptResultAnalyse : public GpgResultAnalyse {
+ public:
+ /**
+ * @brief Construct a new Decrypt Result Analyse object
+ *
+ * @param m_error
+ * @param m_result
+ */
+ explicit GpgDecryptResultAnalyse(GpgError m_error, GpgDecrResult m_result);
+
+ protected:
+ /**
+ * @brief
+ *
+ */
+ void do_analyse() final;
+
+ private:
+ /**
+ * @brief
+ *
+ * @param stream
+ * @param recipient
+ */
+ void print_recipient(std::stringstream &stream, gpgme_recipient_t recipient);
+
+ GpgError error_; ///<
+ GpgDecrResult result_; ///<
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_GPGDECRYPTRESULTANALYSE_H
diff --git a/src/core/function/result_analyse/GpgEncryptResultAnalyse.cpp b/src/core/function/result_analyse/GpgEncryptResultAnalyse.cpp
new file mode 100644
index 00000000..053a15a5
--- /dev/null
+++ b/src/core/function/result_analyse/GpgEncryptResultAnalyse.cpp
@@ -0,0 +1,66 @@
+/**
+ * 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 "GpgEncryptResultAnalyse.h"
+
+GpgFrontend::GpgEncryptResultAnalyse::GpgEncryptResultAnalyse(GpgError error,
+ GpgEncrResult result)
+ : error_(error), result_(std::move(result)) {}
+
+void GpgFrontend::GpgEncryptResultAnalyse::do_analyse() {
+ LOG(INFO) << _("Start Encrypt Result Analyse");
+
+ stream_ << "[#] " << _("Encrypt Operation") << " ";
+
+ if (gpgme_err_code(error_) == GPG_ERR_NO_ERROR)
+ stream_ << "[" << _("Success") << "]" << std::endl;
+ else {
+ stream_ << "[" << _("Failed") << "] " << gpgme_strerror(error_)
+ << std::endl;
+ set_status(-1);
+ }
+
+ if (!~status_) {
+ stream_ << "------------>" << std::endl;
+ if (result_ != nullptr) {
+ stream_ << _("Invalid Recipients") << ": " << std::endl;
+ auto inv_reci = result_->invalid_recipients;
+ while (inv_reci != nullptr) {
+ stream_ << _("Fingerprint") << ": " << inv_reci->fpr << std::endl;
+ stream_ << _("Reason") << ": " << gpgme_strerror(inv_reci->reason)
+ << std::endl;
+ stream_ << std::endl;
+
+ inv_reci = inv_reci->next;
+ }
+ }
+ stream_ << "<------------" << std::endl;
+ }
+
+ stream_ << std::endl;
+}
diff --git a/src/core/function/result_analyse/GpgEncryptResultAnalyse.h b/src/core/function/result_analyse/GpgEncryptResultAnalyse.h
new file mode 100644
index 00000000..c5125fdc
--- /dev/null
+++ b/src/core/function/result_analyse/GpgEncryptResultAnalyse.h
@@ -0,0 +1,63 @@
+/**
+ * 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_GPGENCRYPTRESULTANALYSE_H
+#define GPGFRONTEND_GPGENCRYPTRESULTANALYSE_H
+
+#include "GpgResultAnalyse.h"
+#include "core/GpgConstants.h"
+
+namespace GpgFrontend {
+/**
+ * @brief
+ *
+ */
+class GpgEncryptResultAnalyse : public GpgResultAnalyse {
+ public:
+ /**
+ * @brief Construct a new Encrypt Result Analyse object
+ *
+ * @param error
+ * @param result
+ */
+ explicit GpgEncryptResultAnalyse(GpgError error, GpgEncrResult result);
+
+ protected:
+ /**
+ * @brief
+ *
+ */
+ void do_analyse() final;
+
+ private:
+ GpgError error_; ///<
+ GpgEncrResult result_; ///<
+};
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_GPGENCRYPTRESULTANALYSE_H
diff --git a/src/core/function/result_analyse/GpgResultAnalyse.cpp b/src/core/function/result_analyse/GpgResultAnalyse.cpp
new file mode 100644
index 00000000..40ba4c3e
--- /dev/null
+++ b/src/core/function/result_analyse/GpgResultAnalyse.cpp
@@ -0,0 +1,46 @@
+/**
+ * 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 "GpgResultAnalyse.h"
+
+const std::string GpgFrontend::GpgResultAnalyse::GetResultReport() const {
+ return stream_.str();
+}
+
+int GpgFrontend::GpgResultAnalyse::GetStatus() const { return status_; }
+
+void GpgFrontend::GpgResultAnalyse::set_status(int m_status) {
+ if (m_status < status_) status_ = m_status;
+}
+
+void GpgFrontend::GpgResultAnalyse::Analyse() {
+ if (!analysed_) {
+ do_analyse();
+ analysed_ = true;
+ }
+}
diff --git a/src/core/function/result_analyse/GpgResultAnalyse.h b/src/core/function/result_analyse/GpgResultAnalyse.h
new file mode 100644
index 00000000..888c6449
--- /dev/null
+++ b/src/core/function/result_analyse/GpgResultAnalyse.h
@@ -0,0 +1,86 @@
+/**
+ * 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_GPGRESULTANALYSE_H
+#define GPGFRONTEND_GPGRESULTANALYSE_H
+
+#include <sstream>
+#include <string>
+
+#include "core/GpgConstants.h"
+namespace GpgFrontend {
+
+class GpgResultAnalyse {
+ public:
+ /**
+ * @brief Construct a new Result Analyse object
+ *
+ */
+ GpgResultAnalyse() = default;
+
+ /**
+ * @brief Get the Result Report object
+ *
+ * @return const std::string
+ */
+ [[nodiscard]] const std::string GetResultReport() const;
+
+ /**
+ * @brief Get the Status object
+ *
+ * @return int
+ */
+ [[nodiscard]] int GetStatus() const;
+
+ /**
+ * @brief
+ *
+ */
+ void Analyse();
+
+ protected:
+ /**
+ * @brief
+ *
+ */
+ virtual void do_analyse() = 0;
+
+ /**
+ * @brief Set the status object
+ *
+ * @param m_status
+ */
+ void set_status(int m_status);
+
+ std::stringstream stream_; ///<
+ int status_ = 1; ///<
+ bool analysed_ = false; ///<
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_GPGRESULTANALYSE_H
diff --git a/src/core/function/result_analyse/GpgSignResultAnalyse.cpp b/src/core/function/result_analyse/GpgSignResultAnalyse.cpp
new file mode 100644
index 00000000..e389523c
--- /dev/null
+++ b/src/core/function/result_analyse/GpgSignResultAnalyse.cpp
@@ -0,0 +1,115 @@
+/**
+ * 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 "GpgSignResultAnalyse.h"
+
+#include "function/gpg/GpgKeyGetter.h"
+
+GpgFrontend::GpgSignResultAnalyse::GpgSignResultAnalyse(GpgError error,
+ GpgSignResult result)
+ : error_(error), result_(std::move(result)) {}
+
+void GpgFrontend::GpgSignResultAnalyse::do_analyse() {
+ LOG(INFO) << _("Start Sign Result Analyse");
+
+ stream_ << "[#] " << _("Sign Operation") << " ";
+
+ if (gpgme_err_code(error_) == GPG_ERR_NO_ERROR)
+ stream_ << "[" << _("Success") << "]" << std::endl;
+ else {
+ stream_ << "[" << _("Failed") << "] " << gpgme_strerror(error_)
+ << std::endl;
+ set_status(-1);
+ }
+
+ if (result_ != nullptr &&
+ (result_->signatures != nullptr || result_->invalid_signers != nullptr)) {
+ LOG(INFO) << _("Sign Result Analyse Getting Result");
+ stream_ << "------------>" << std::endl;
+ auto new_sign = result_->signatures;
+
+ while (new_sign != nullptr) {
+ stream_ << "[>]" << _("New Signature") << ": " << std::endl;
+
+ LOG(INFO) << _("Signers Fingerprint") << ": " << new_sign->fpr;
+
+ stream_ << " " << _("Sign Mode") << ": ";
+ if (new_sign->type == GPGME_SIG_MODE_NORMAL)
+ stream_ << _("Normal");
+ else if (new_sign->type == GPGME_SIG_MODE_CLEAR)
+ stream_ << _("Clear");
+ else if (new_sign->type == GPGME_SIG_MODE_DETACH)
+ stream_ << _("Detach");
+
+ stream_ << std::endl;
+
+ auto singerKey =
+ GpgFrontend::GpgKeyGetter::GetInstance().GetKey(new_sign->fpr);
+ if (singerKey.IsGood()) {
+ stream_ << " " << _("Signer") << ": "
+ << singerKey.GetUIDs()->front().GetUID() << std::endl;
+ } else {
+ stream_ << " " << _("Signer") << ": "
+ << "<unknown>" << std::endl;
+ }
+ stream_ << " " << _("Public Key Algo") << ": "
+ << gpgme_pubkey_algo_name(new_sign->pubkey_algo) << std::endl;
+ stream_ << " " << _("Hash Algo") << ": "
+ << gpgme_hash_algo_name(new_sign->hash_algo) << std::endl;
+ stream_ << " " << _("Date") << "(" << _("UTC") << ")"
+ << ": "
+ << boost::posix_time::to_iso_extended_string(
+ boost::posix_time::from_time_t(new_sign->timestamp))
+ << std::endl;
+
+ stream_ << std::endl;
+
+ new_sign = new_sign->next;
+ }
+
+ LOG(INFO) << _("Sign Result Analyse Getting Invalid Signer");
+
+ auto invalid_signer = result_->invalid_signers;
+
+ if (invalid_signer != nullptr)
+ stream_ << _("Invalid Signers") << ": " << std::endl;
+
+ while (invalid_signer != nullptr) {
+ set_status(0);
+ stream_ << "[>] " << _("Signer") << ": " << std::endl;
+ stream_ << " " << _("Fingerprint") << ": " << invalid_signer->fpr
+ << std::endl;
+ stream_ << " " << _("Reason") << ": "
+ << gpgme_strerror(invalid_signer->reason) << std::endl;
+ stream_ << std::endl;
+
+ invalid_signer = invalid_signer->next;
+ }
+ stream_ << "<------------" << std::endl;
+ }
+} \ No newline at end of file
diff --git a/src/core/function/result_analyse/GpgSignResultAnalyse.h b/src/core/function/result_analyse/GpgSignResultAnalyse.h
new file mode 100644
index 00000000..d593b33d
--- /dev/null
+++ b/src/core/function/result_analyse/GpgSignResultAnalyse.h
@@ -0,0 +1,65 @@
+/**
+ * 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_GPGSIGNRESULTANALYSE_H
+#define GPGFRONTEND_GPGSIGNRESULTANALYSE_H
+
+#include "GpgResultAnalyse.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief
+ *
+ */
+class GpgSignResultAnalyse : public GpgResultAnalyse {
+ public:
+ /**
+ * @brief Construct a new Sign Result Analyse object
+ *
+ * @param error
+ * @param result
+ */
+ explicit GpgSignResultAnalyse(GpgError error, GpgSignResult result);
+
+ protected:
+ /**
+ * @brief
+ *
+ */
+ void do_analyse();
+
+ private:
+ GpgError error_; ///<
+
+ GpgSignResult result_; ///<
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_GPGSIGNRESULTANALYSE_H
diff --git a/src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp b/src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp
new file mode 100644
index 00000000..44031e67
--- /dev/null
+++ b/src/core/function/result_analyse/GpgVerifyResultAnalyse.cpp
@@ -0,0 +1,214 @@
+/**
+ * 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 "GpgVerifyResultAnalyse.h"
+
+#include <boost/format.hpp>
+
+#include "GpgFrontend.h"
+#include "core/GpgConstants.h"
+#include "function/gpg/GpgKeyGetter.h"
+
+GpgFrontend::GpgVerifyResultAnalyse::GpgVerifyResultAnalyse(GpgError error,
+ GpgVerifyResult result)
+ : error_(error), result_(std::move(result)) {}
+
+void GpgFrontend::GpgVerifyResultAnalyse::do_analyse() {
+ LOG(INFO) << _("started");
+
+ stream_ << "[#] " << _("Verify Operation") << " ";
+
+ if (gpgme_err_code(error_) == GPG_ERR_NO_ERROR)
+ stream_ << "[" << _("Success") << "]" << std::endl;
+ else {
+ stream_ << "[" << _("Failed") << "] " << gpgme_strerror(error_)
+ << std::endl;
+ set_status(-1);
+ }
+
+ if (result_ != nullptr && result_->signatures != nullptr) {
+ stream_ << "------------>" << std::endl;
+ auto sign = result_->signatures;
+
+ stream_ << "[>] " << _("Signed On") << "(" << _("UTC") << ")"
+ << " "
+ << boost::posix_time::to_iso_extended_string(
+ boost::posix_time::from_time_t(sign->timestamp))
+ << std::endl;
+
+ stream_ << std::endl << "[>] " << _("Signatures List") << ":" << std::endl;
+
+ bool canContinue = true;
+
+ int count = 1;
+ while (sign && canContinue) {
+ stream_ << boost::format(_("Signature [%1%]:")) % count++ << std::endl;
+ switch (gpg_err_code(sign->status)) {
+ case GPG_ERR_BAD_SIGNATURE:
+ stream_ << _("A Bad Signature.") << std::endl;
+ print_signer(stream_, sign);
+ stream_ << _("This Signature is invalid.") << std::endl;
+ canContinue = false;
+ set_status(-1);
+ break;
+ case GPG_ERR_NO_ERROR:
+ stream_ << _("A") << " ";
+ if (sign->summary & GPGME_SIGSUM_GREEN) {
+ stream_ << _("Good") << " ";
+ }
+ if (sign->summary & GPGME_SIGSUM_RED) {
+ stream_ << _("Bad") << " ";
+ }
+ if (sign->summary & GPGME_SIGSUM_SIG_EXPIRED) {
+ stream_ << _("Expired") << " ";
+ }
+ if (sign->summary & GPGME_SIGSUM_KEY_MISSING) {
+ stream_ << _("Missing Key's") << " ";
+ }
+ if (sign->summary & GPGME_SIGSUM_KEY_REVOKED) {
+ stream_ << _("Revoked Key's") << " ";
+ }
+ if (sign->summary & GPGME_SIGSUM_KEY_EXPIRED) {
+ stream_ << _("Expired Key's") << " ";
+ }
+ if (sign->summary & GPGME_SIGSUM_CRL_MISSING) {
+ stream_ << _("Missing CRL's") << " ";
+ }
+
+ if (sign->summary & GPGME_SIGSUM_VALID) {
+ stream_ << _("Signature Fully Valid.") << std::endl;
+ } else {
+ stream_ << _("Signature Not Fully Valid.") << std::endl;
+ }
+
+ if (!(sign->status & GPGME_SIGSUM_KEY_MISSING)) {
+ if (!print_signer(stream_, sign)) set_status(0);
+ } else {
+ stream_ << _("Key is NOT present with ID 0x") << sign->fpr
+ << std::endl;
+ }
+
+ set_status(1);
+
+ break;
+ case GPG_ERR_NO_PUBKEY:
+ stream_ << _("A signature could NOT be verified due to a Missing Key")
+ << std::endl;
+ set_status(-2);
+ break;
+ case GPG_ERR_CERT_REVOKED:
+ stream_ << _("A signature is valid but the key used to verify the "
+ "signature has been revoked")
+ << std::endl;
+ if (!print_signer(stream_, sign)) {
+ set_status(0);
+ }
+ set_status(-1);
+ break;
+ case GPG_ERR_SIG_EXPIRED:
+ stream_ << _("A signature is valid but expired") << std::endl;
+ if (!print_signer(stream_, sign)) {
+ set_status(0);
+ }
+ set_status(-1);
+ break;
+ case GPG_ERR_KEY_EXPIRED:
+ stream_ << _("A signature is valid but the key used to "
+ "verify the signature has expired.")
+ << std::endl;
+ if (!print_signer(stream_, sign)) {
+ set_status(0);
+ }
+ break;
+ case GPG_ERR_GENERAL:
+ stream_ << _("There was some other error which prevented "
+ "the signature verification.")
+ << std::endl;
+ status_ = -1;
+ canContinue = false;
+ break;
+ default:
+ auto fpr = std::string(sign->fpr);
+ stream_ << _("Error for key with fingerprint") << " "
+ << GpgFrontend::beautify_fingerprint(fpr);
+ set_status(-1);
+ }
+ stream_ << std::endl;
+ sign = sign->next;
+ }
+ stream_ << "<------------" << std::endl;
+ } else {
+ stream_
+ << "[>] "
+ << _("Could not find information that can be used for verification.")
+ << std::endl;
+ set_status(0);
+ return;
+ }
+}
+
+bool GpgFrontend::GpgVerifyResultAnalyse::print_signer(std::stringstream &stream,
+ gpgme_signature_t sign) {
+ bool keyFound = true;
+ auto key = GpgFrontend::GpgKeyGetter::GetInstance().GetKey(sign->fpr);
+
+ if (!key.IsGood()) {
+ stream << " " << _("Signed By") << ": "
+ << "<" << _("Unknown") << ">" << std::endl;
+ set_status(0);
+ keyFound = false;
+ } else {
+ stream << " " << _("Signed By") << ": "
+ << key.GetUIDs()->front().GetUID() << std::endl;
+ }
+ if (sign->pubkey_algo)
+ stream << " " << _("Public Key Algo") << ": "
+ << gpgme_pubkey_algo_name(sign->pubkey_algo) << std::endl;
+ if (sign->hash_algo)
+ stream << " " << _("Hash Algo") << ": "
+ << gpgme_hash_algo_name(sign->hash_algo) << std::endl;
+ if (sign->timestamp)
+ stream << " " << _("Date") << "(" << _("UTC") << ")"
+ << ": "
+ << boost::posix_time::to_iso_extended_string(
+ boost::posix_time::from_time_t(sign->timestamp))
+ << std::endl;
+ stream << std::endl;
+ return keyFound;
+}
+
+gpgme_signature_t GpgFrontend::GpgVerifyResultAnalyse::GetSignatures() const {
+ if (result_)
+ return result_->signatures;
+ else
+ return nullptr;
+}
+GpgFrontend::GpgVerifyResult
+GpgFrontend::GpgVerifyResultAnalyse::TakeChargeOfResult() {
+ return std::move(result_);
+}
diff --git a/src/core/function/result_analyse/GpgVerifyResultAnalyse.h b/src/core/function/result_analyse/GpgVerifyResultAnalyse.h
new file mode 100644
index 00000000..12e4b7ff
--- /dev/null
+++ b/src/core/function/result_analyse/GpgVerifyResultAnalyse.h
@@ -0,0 +1,88 @@
+/**
+ * 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_GPGVERIFYRESULTANALYSE_H
+#define GPGFRONTEND_GPGVERIFYRESULTANALYSE_H
+
+#include "GpgResultAnalyse.h"
+#include "core/model/GpgKeySignature.h"
+
+namespace GpgFrontend {
+/**
+ * @brief
+ *
+ */
+class GpgVerifyResultAnalyse : public GpgResultAnalyse {
+ public:
+ /**
+ * @brief Construct a new Verify Result Analyse object
+ *
+ * @param error
+ * @param result
+ */
+ explicit GpgVerifyResultAnalyse(GpgError error, GpgVerifyResult result);
+
+ /**
+ * @brief Get the Signatures object
+ *
+ * @return gpgme_signature_t
+ */
+ gpgme_signature_t GetSignatures() const;
+
+ /**
+ * @brief
+ *
+ * @return GpgVerifyResult
+ */
+ GpgVerifyResult TakeChargeOfResult();
+
+ private:
+ /**
+ * @brief
+ *
+ */
+ void do_analyse();
+
+ private:
+ /**
+ * @brief
+ *
+ * @param stream
+ * @param sign
+ * @return true
+ * @return false
+ */
+ bool print_signer(std::stringstream &stream, gpgme_signature_t sign);
+
+ GpgError error_; ///<
+ GpgVerifyResult result_; ///<
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_GPGVERIFYRESULTANALYSE_H
diff --git a/src/core/model/GpgData.cpp b/src/core/model/GpgData.cpp
new file mode 100644
index 00000000..7fda4416
--- /dev/null
+++ b/src/core/model/GpgData.cpp
@@ -0,0 +1,76 @@
+/**
+ * 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 "core/model/GpgData.h"
+
+GpgFrontend::GpgData::GpgData() {
+ gpgme_data_t data;
+
+ auto err = gpgme_data_new(&data);
+ assert(gpgme_err_code(err) == GPG_ERR_NO_ERROR);
+
+ data_ref_ = std::unique_ptr<struct gpgme_data, _data_ref_deleter>(data);
+}
+
+GpgFrontend::GpgData::GpgData(void* buffer, size_t size, bool copy) {
+ gpgme_data_t data;
+
+ auto err = gpgme_data_new_from_mem(&data, (const char*)buffer, size, copy);
+ assert(gpgme_err_code(err) == GPG_ERR_NO_ERROR);
+
+ data_ref_ = std::unique_ptr<struct gpgme_data, _data_ref_deleter>(data);
+}
+
+/**
+ * Read gpgme-Data to QByteArray
+ * mainly from http://basket.kde.org/ (kgpgme.cpp)
+ */
+#define BUF_SIZE (32 * 1024)
+
+GpgFrontend::ByteArrayPtr GpgFrontend::GpgData::Read2Buffer() {
+ gpgme_off_t ret = gpgme_data_seek(*this, 0, SEEK_SET);
+ ByteArrayPtr out_buffer = std::make_unique<std::string>();
+
+ if (ret) {
+ gpgme_error_t err = gpgme_err_code_from_errno(errno);
+ assert(gpgme_err_code(err) == GPG_ERR_NO_ERROR);
+ } else {
+ char buf[BUF_SIZE + 2];
+
+ while ((ret = gpgme_data_read(*this, buf, BUF_SIZE)) > 0) {
+ const size_t size = out_buffer->size();
+ out_buffer->resize(static_cast<int>(size + ret));
+ memcpy(out_buffer->data() + size, buf, ret);
+ }
+ if (ret < 0) {
+ gpgme_error_t err = gpgme_err_code_from_errno(errno);
+ assert(gpgme_err_code(err) == GPG_ERR_NO_ERROR);
+ }
+ }
+ return out_buffer;
+} \ No newline at end of file
diff --git a/src/core/model/GpgData.h b/src/core/model/GpgData.h
new file mode 100644
index 00000000..c06f78d6
--- /dev/null
+++ b/src/core/model/GpgData.h
@@ -0,0 +1,87 @@
+/**
+ * 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 _GPGDATA_H
+#define _GPGDATA_H
+
+#include "core/GpgConstants.h"
+
+namespace GpgFrontend {
+/**
+ * @brief
+ *
+ */
+class GpgData {
+ public:
+ /**
+ * @brief Construct a new Gpg Data object
+ *
+ */
+ GpgData();
+
+ /**
+ * @brief Construct a new Gpg Data object
+ *
+ * @param buffer
+ * @param size
+ * @param copy
+ */
+ GpgData(void* buffer, size_t size, bool copy = true);
+
+ /**
+ * @brief
+ *
+ * @return gpgme_data_t
+ */
+ operator gpgme_data_t() { return data_ref_.get(); }
+
+ /**
+ * @brief
+ *
+ * @return ByteArrayPtr
+ */
+ ByteArrayPtr Read2Buffer();
+
+ private:
+ /**
+ * @brief
+ *
+ */
+ struct _data_ref_deleter {
+ void operator()(gpgme_data_t _data) {
+ if (_data != nullptr) gpgme_data_release(_data);
+ }
+ };
+
+ std::unique_ptr<struct gpgme_data, _data_ref_deleter> data_ref_ =
+ nullptr; ///<
+};
+
+} // namespace GpgFrontend
+
+#endif // _GPGDATA_H \ No newline at end of file
diff --git a/src/core/model/GpgKey.cpp b/src/core/model/GpgKey.cpp
new file mode 100644
index 00000000..b0952cfa
--- /dev/null
+++ b/src/core/model/GpgKey.cpp
@@ -0,0 +1,115 @@
+/**
+ * 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 "core/model/GpgKey.h"
+
+GpgFrontend::GpgKey::GpgKey(gpgme_key_t &&key) : key_ref_(std::move(key)) {}
+
+GpgFrontend::GpgKey::GpgKey(GpgKey &&k) noexcept { swap(key_ref_, k.key_ref_); }
+
+GpgFrontend::GpgKey &GpgFrontend::GpgKey::operator=(GpgKey &&k) noexcept {
+ swap(key_ref_, k.key_ref_);
+ return *this;
+}
+
+std::unique_ptr<std::vector<GpgFrontend::GpgSubKey>>
+GpgFrontend::GpgKey::GetSubKeys() const {
+ auto p_keys = std::make_unique<std::vector<GpgSubKey>>();
+ auto next = key_ref_->subkeys;
+ while (next != nullptr) {
+ p_keys->push_back(GpgSubKey(next));
+ next = next->next;
+ }
+ return p_keys;
+}
+
+std::unique_ptr<std::vector<GpgFrontend::GpgUID>> GpgFrontend::GpgKey::GetUIDs()
+ const {
+ auto p_uids = std::make_unique<std::vector<GpgUID>>();
+ auto uid_next = key_ref_->uids;
+ while (uid_next != nullptr) {
+ p_uids->push_back(GpgUID(uid_next));
+ uid_next = uid_next->next;
+ }
+ return p_uids;
+}
+
+bool GpgFrontend::GpgKey::IsHasActualSigningCapability() const {
+ auto subkeys = GetSubKeys();
+ if (std::any_of(subkeys->begin(), subkeys->end(),
+ [](const GpgSubKey &subkey) -> bool {
+ return subkey.IsSecretKey() &&
+ subkey.IsHasSigningCapability() &&
+ !subkey.IsDisabled() && !subkey.IsRevoked() &&
+ !subkey.IsExpired();
+ }))
+ return true;
+ else
+ return false;
+}
+
+bool GpgFrontend::GpgKey::IsHasActualAuthenticationCapability() const {
+ auto subkeys = GetSubKeys();
+ if (std::any_of(subkeys->begin(), subkeys->end(),
+ [](const GpgSubKey &subkey) -> bool {
+ return subkey.IsSecretKey() &&
+ subkey.IsHasAuthenticationCapability() &&
+ !subkey.IsDisabled() && !subkey.IsRevoked() &&
+ !subkey.IsExpired();
+ }))
+ return true;
+ else
+ return false;
+}
+
+/**
+ * check if key can certify(actually)
+ * @param key target key
+ * @return if key certify
+ */
+bool GpgFrontend::GpgKey::IsHasActualCertificationCapability() const {
+ return IsHasMasterKey() && !IsExpired() && !IsRevoked() && !IsDisabled();
+}
+
+/**
+ * check if key can encrypt(actually)
+ * @param key target key
+ * @return if key encrypt
+ */
+bool GpgFrontend::GpgKey::IsHasActualEncryptionCapability() const {
+ auto subkeys = GetSubKeys();
+ if (std::any_of(subkeys->begin(), subkeys->end(),
+ [](const GpgSubKey &subkey) -> bool {
+ return subkey.IsHasEncryptionCapability() &&
+ !subkey.IsDisabled() && !subkey.IsRevoked() &&
+ !subkey.IsExpired();
+ }))
+ return true;
+ else
+ return false;
+}
diff --git a/src/core/model/GpgKey.h b/src/core/model/GpgKey.h
new file mode 100644
index 00000000..14315d4c
--- /dev/null
+++ b/src/core/model/GpgKey.h
@@ -0,0 +1,415 @@
+/**
+ * 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_GPGKEY_H
+#define GPGFRONTEND_GPGKEY_H
+
+#include <boost/date_time.hpp>
+#include <boost/date_time/posix_time/conversion.hpp>
+
+#include "GpgSubKey.h"
+#include "GpgUID.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief
+ *
+ */
+class GpgKey {
+ public:
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsGood() const { return key_ref_ != nullptr; }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetId() const { return key_ref_->subkeys->keyid; }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetName() const { return key_ref_->uids->name; };
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetEmail() const { return key_ref_->uids->email; }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetComment() const {
+ return key_ref_->uids->comment;
+ }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetFingerprint() const { return key_ref_->fpr; }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetProtocol() const {
+ return gpgme_get_protocol_name(key_ref_->protocol);
+ }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetOwnerTrust() const {
+ switch (key_ref_->owner_trust) {
+ case GPGME_VALIDITY_UNKNOWN:
+ return "Unknown";
+ case GPGME_VALIDITY_UNDEFINED:
+ return "Undefined";
+ case GPGME_VALIDITY_NEVER:
+ return "Never";
+ case GPGME_VALIDITY_MARGINAL:
+ return "Marginal";
+ case GPGME_VALIDITY_FULL:
+ return "FULL";
+ case GPGME_VALIDITY_ULTIMATE:
+ return "Ultimate";
+ }
+ return "Invalid";
+ }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetPublicKeyAlgo() const {
+ return gpgme_pubkey_algo_name(key_ref_->subkeys->pubkey_algo);
+ }
+
+ /**
+ * @brief
+ *
+ * @return boost::posix_time::ptime
+ */
+ [[nodiscard]] boost::posix_time::ptime GetLastUpdateTime() const {
+ return boost::posix_time::from_time_t(
+ static_cast<time_t>(key_ref_->last_update));
+ }
+
+ /**
+ * @brief
+ *
+ * @return boost::posix_time::ptime
+ */
+ [[nodiscard]] boost::posix_time::ptime GetExpireTime() const {
+ return boost::posix_time::from_time_t(key_ref_->subkeys->expires);
+ };
+
+ /**
+ * @brief Create a time object
+ *
+ * @return boost::posix_time::ptime
+ */
+ [[nodiscard]] boost::posix_time::ptime GetCreateTime() const {
+ return boost::posix_time::from_time_t(key_ref_->subkeys->timestamp);
+ };
+
+ /**
+ * @brief s
+ *
+ * @return unsigned int
+ */
+ [[nodiscard]] unsigned int GetPrimaryKeyLength() const {
+ return key_ref_->subkeys->length;
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsHasEncryptionCapability() const {
+ return key_ref_->can_encrypt;
+ }
+
+ /**
+ * @brief
+
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsHasActualEncryptionCapability() const;
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsHasSigningCapability() const {
+ return key_ref_->can_sign;
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsHasActualSigningCapability() const;
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsHasCertificationCapability() const {
+ return key_ref_->can_certify;
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsHasActualCertificationCapability() const;
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsHasAuthenticationCapability() const {
+ return key_ref_->can_authenticate;
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsHasActualAuthenticationCapability() const;
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsHasCardKey() const {
+ auto subkeys = GetSubKeys();
+ return std::any_of(
+ subkeys->begin(), subkeys->end(),
+ [](const GpgSubKey& subkey) -> bool { return subkey.IsCardKey(); });
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsPrivateKey() const { return key_ref_->secret; }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsExpired() const { return key_ref_->expired; }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsRevoked() const { return key_ref_->revoked; }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsDisabled() const { return key_ref_->disabled; }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsHasMasterKey() const {
+ return key_ref_->subkeys->secret;
+ }
+
+ /**
+ * @brief
+ *
+ * @return std::unique_ptr<std::vector<GpgSubKey>>
+ */
+ [[nodiscard]] std::unique_ptr<std::vector<GpgSubKey>> GetSubKeys() const;
+
+ /**
+ * @brief
+ *
+ * @return std::unique_ptr<std::vector<GpgUID>>
+ */
+ [[nodiscard]] std::unique_ptr<std::vector<GpgUID>> GetUIDs() const;
+
+ /**
+ * @brief Construct a new Gpg Key object
+ *
+ */
+ GpgKey() = default;
+
+ /**
+ * @brief Construct a new Gpg Key object
+ *
+ * @param key
+ */
+ explicit GpgKey(gpgme_key_t&& key);
+
+ /**
+ * @brief Destroy the Gpg Key objects
+ *
+ */
+ ~GpgKey() = default;
+
+ /**
+ * @brief Construct a new Gpg Key object
+ *
+ * @param key
+ */
+ GpgKey(const gpgme_key_t& key) = delete;
+
+ /**
+ * @brief Construct a new Gpg Key object
+ *
+ * @param k
+ */
+ GpgKey(GpgKey&& k) noexcept;
+
+ /**
+ * @brief
+ *
+ * @param k
+ * @return GpgKey&
+ */
+ GpgKey& operator=(GpgKey&& k) noexcept;
+
+ /**
+ * @brief
+ *
+ * @param key
+ * @return GpgKey&
+ */
+ GpgKey& operator=(const gpgme_key_t& key) = delete;
+
+ /**
+ * @brief
+ *
+ * @param o
+ * @return true
+ * @return false
+ */
+ bool operator==(const GpgKey& o) const { return o.GetId() == this->GetId(); }
+
+ /**
+ * @brief
+ *
+ * @param o
+ * @return true
+ * @return false
+ */
+ bool operator<=(const GpgKey& o) const { return this->GetId() < o.GetId(); }
+
+ /**
+ * @brief
+ *
+ * @return gpgme_key_t
+ */
+ explicit operator gpgme_key_t() const { return key_ref_.get(); }
+
+ /**
+ * @brief
+ *
+ * @return GpgKey
+ */
+ [[nodiscard]] GpgKey Copy() const {
+ gpgme_key_ref(key_ref_.get());
+ auto* _new_key_ref = key_ref_.get();
+ return GpgKey(std::move(_new_key_ref));
+ }
+
+ private:
+ /**
+ * @brief
+ *
+ */
+ struct _key_ref_deleter {
+ void operator()(gpgme_key_t _key) {
+ if (_key != nullptr) gpgme_key_unref(_key);
+ }
+ };
+
+ using KeyRefHandler =
+ std::unique_ptr<struct _gpgme_key, _key_ref_deleter>; ///<
+
+ KeyRefHandler key_ref_ = nullptr; ///<
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_GPGKEY_H
diff --git a/src/core/model/GpgKeySignature.cpp b/src/core/model/GpgKeySignature.cpp
new file mode 100644
index 00000000..0c11a93b
--- /dev/null
+++ b/src/core/model/GpgKeySignature.cpp
@@ -0,0 +1,32 @@
+/**
+ * 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 "core/model/GpgKeySignature.h"
+
+GpgFrontend::GpgKeySignature::GpgKeySignature(gpgme_key_sig_t sig)
+ : signature_ref_(sig, [&](gpgme_key_sig_t signature) {}) {}
diff --git a/src/core/model/GpgKeySignature.h b/src/core/model/GpgKeySignature.h
new file mode 100644
index 00000000..33b84904
--- /dev/null
+++ b/src/core/model/GpgKeySignature.h
@@ -0,0 +1,209 @@
+/**
+ * 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_GPGKEYSIGNATURE_H
+#define GPGFRONTEND_GPGKEYSIGNATURE_H
+
+#include <boost/date_time.hpp>
+#include <string>
+
+#include "core/GpgConstants.h"
+
+/**
+ * @brief
+ *
+ */
+namespace GpgFrontend {
+
+/**
+ * @brief
+ *
+ */
+class GpgKeySignature {
+ public:
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsRevoked() const { return signature_ref_->revoked; }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsExpired() const { return signature_ref_->expired; }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsInvalid() const { return signature_ref_->invalid; }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsExportable() const { return signature_ref_->exportable; }
+
+ /**
+ * @brief
+ *
+ * @return gpgme_error_t
+ */
+ [[nodiscard]] gpgme_error_t GetStatus() const {
+ return signature_ref_->status;
+ }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetKeyID() const { return signature_ref_->keyid; }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetPubkeyAlgo() const {
+ return gpgme_pubkey_algo_name(signature_ref_->pubkey_algo);
+ }
+
+ /**
+ * @brief Create a time object
+ *
+ * @return boost::posix_time::ptime
+ */
+ [[nodiscard]] boost::posix_time::ptime GetCreateTime() const {
+ return boost::posix_time::from_time_t(signature_ref_->timestamp);
+ }
+
+ /**
+ * @brief
+ *
+ * @return boost::posix_time::ptime
+ */
+ [[nodiscard]] boost::posix_time::ptime GetExpireTime() const {
+ return boost::posix_time::from_time_t(signature_ref_->expires);
+ }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetUID() const { return signature_ref_->uid; }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetName() const { return signature_ref_->name; }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetEmail() const { return signature_ref_->email; }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetComment() const {
+ return signature_ref_->comment;
+ }
+
+ /**
+ * @brief Construct a new Gpg Key Signature object
+ *
+ */
+ GpgKeySignature() = default;
+
+ /**
+ * @brief Destroy the Gpg Key Signature object
+ *
+ */
+ ~GpgKeySignature() = default;
+
+ /**
+ * @brief Construct a new Gpg Key Signature object
+ *
+ * @param sig
+ */
+ explicit GpgKeySignature(gpgme_key_sig_t sig);
+
+ /**
+ * @brief Construct a new Gpg Key Signature object
+ *
+ */
+ GpgKeySignature(GpgKeySignature &&) noexcept = default;
+
+ /**
+ * @brief Construct a new Gpg Key Signature object
+ *
+ */
+ GpgKeySignature(const GpgKeySignature &) = delete;
+
+ /**
+ * @brief
+ *
+ * @return GpgKeySignature&
+ */
+ GpgKeySignature &operator=(GpgKeySignature &&) noexcept = default;
+
+ /**
+ * @brief
+ *
+ * @return GpgKeySignature&
+ */
+ GpgKeySignature &operator=(const GpgKeySignature &) = delete;
+
+ private:
+ using KeySignatrueRefHandler =
+ std::unique_ptr<struct _gpgme_key_sig,
+ std::function<void(gpgme_key_sig_t)>>; ///<
+
+ KeySignatrueRefHandler signature_ref_ = nullptr; ///<
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_GPGKEYSIGNATURE_H
diff --git a/src/core/model/GpgSignature.cpp b/src/core/model/GpgSignature.cpp
new file mode 100644
index 00000000..f8084442
--- /dev/null
+++ b/src/core/model/GpgSignature.cpp
@@ -0,0 +1,32 @@
+/**
+ * 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 "GpgSignature.h"
+
+GpgFrontend::GpgSignature::GpgSignature(gpgme_signature_t sig)
+ : signature_ref_(sig, [&](gpgme_signature_t signature) {}) {}
diff --git a/src/core/model/GpgSignature.h b/src/core/model/GpgSignature.h
new file mode 100644
index 00000000..942f0097
--- /dev/null
+++ b/src/core/model/GpgSignature.h
@@ -0,0 +1,171 @@
+/**
+ * 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_GPGSIGNATURE_H
+#define GPGFRONTEND_GPGSIGNATURE_H
+
+#include <boost/date_time/gregorian/greg_date.hpp>
+#include <boost/date_time/posix_time/conversion.hpp>
+
+#include "core/GpgConstants.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief
+ *
+ */
+class GpgSignature {
+ public:
+ /**
+ * @brief
+ *
+ * @return gpgme_validity_t
+ */
+ [[nodiscard]] gpgme_validity_t GetValidity() const {
+ return signature_ref_->validity;
+ }
+
+ /**
+ * @brief
+ *
+ * @return gpgme_error_t
+ */
+ [[nodiscard]] gpgme_error_t GetStatus() const {
+ return signature_ref_->status;
+ }
+
+ /**
+ * @brief
+ *
+ * @return gpgme_error_t
+ */
+ [[nodiscard]] gpgme_error_t GetSummary() const {
+ return signature_ref_->summary;
+ }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetPubkeyAlgo() const {
+ return gpgme_pubkey_algo_name(signature_ref_->pubkey_algo);
+ }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetHashAlgo() const {
+ return gpgme_hash_algo_name(signature_ref_->hash_algo);
+ }
+
+ /**
+ * @brief Create a time object
+ *
+ * @return boost::posix_time::ptime
+ */
+ [[nodiscard]] boost::posix_time::ptime GetCreateTime() const {
+ return boost::posix_time::from_time_t(signature_ref_->timestamp);
+ }
+
+ /**
+ * @brief
+ *
+ * @return boost::posix_time::ptime
+ */
+ [[nodiscard]] boost::posix_time::ptime GetExpireTime() const {
+ return boost::posix_time::from_time_t(signature_ref_->exp_timestamp);
+ }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetFingerprint() const {
+ return signature_ref_->fpr;
+ }
+
+ /**
+ * @brief Construct a new Gpg Signature object
+ *
+ */
+ GpgSignature() = default;
+
+ /**
+ * @brief Destroy the Gpg Signature object
+ *
+ */
+ ~GpgSignature() = default;
+
+ /**
+ * @brief Construct a new Gpg Signature object
+ *
+ * @param sig
+ */
+ explicit GpgSignature(gpgme_signature_t sig);
+
+ /**
+ * @brief Construct a new Gpg Signature object
+ *
+ */
+ GpgSignature(GpgSignature &&) noexcept = default;
+
+ /**
+ * @brief Construct a new Gpg Signature object
+ *
+ */
+ GpgSignature(const GpgSignature &) = delete;
+
+ /**
+ * @brief
+ *
+ * @return GpgSignature&
+ */
+ GpgSignature &operator=(GpgSignature &&) noexcept = default;
+
+ /**
+ * @brief
+ *
+ * @return GpgSignature&
+ */
+ GpgSignature &operator=(const GpgSignature &) = delete;
+
+ private:
+ using KeySignatrueRefHandler =
+ std::unique_ptr<struct _gpgme_signature,
+ std::function<void(gpgme_signature_t)>>; ///<
+
+ KeySignatrueRefHandler signature_ref_ = nullptr; ///<
+};
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_GPGSIGNATURE_H
diff --git a/src/core/model/GpgSubKey.cpp b/src/core/model/GpgSubKey.cpp
new file mode 100644
index 00000000..767f9c5d
--- /dev/null
+++ b/src/core/model/GpgSubKey.cpp
@@ -0,0 +1,31 @@
+/**
+ * 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 "core/model/GpgSubKey.h"
+
+GpgFrontend::GpgSubKey::GpgSubKey(gpgme_subkey_t subkey)
+ : _subkey_ref(subkey, [&](gpgme_subkey_t subkey) {}) {}
diff --git a/src/core/model/GpgSubKey.h b/src/core/model/GpgSubKey.h
new file mode 100644
index 00000000..1aadcdac
--- /dev/null
+++ b/src/core/model/GpgSubKey.h
@@ -0,0 +1,248 @@
+/**
+ * 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_GPGSUBKEY_H
+#define GPGFRONTEND_GPGSUBKEY_H
+
+#include <boost/date_time.hpp>
+#include <string>
+
+#include "core/GpgConstants.h"
+
+namespace GpgFrontend {
+
+/**
+ * @brief
+ *
+ */
+class GpgSubKey {
+ public:
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetID() const { return _subkey_ref->keyid; }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetFingerprint() const { return _subkey_ref->fpr; }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetPubkeyAlgo() const {
+ return gpgme_pubkey_algo_name(_subkey_ref->pubkey_algo);
+ }
+
+ /**
+ * @brief
+ *
+ * @return unsigned int
+ */
+ [[nodiscard]] unsigned int GetKeyLength() const {
+ return _subkey_ref->length;
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsHasEncryptionCapability() const {
+ return _subkey_ref->can_encrypt;
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsHasSigningCapability() const {
+ return _subkey_ref->can_sign;
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsHasCertificationCapability() const {
+ return _subkey_ref->can_certify;
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsHasAuthenticationCapability() const {
+ return _subkey_ref->can_authenticate;
+ }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsPrivateKey() const { return _subkey_ref->secret; }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsExpired() const { return _subkey_ref->expired; }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsRevoked() const { return _subkey_ref->revoked; }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsDisabled() const { return _subkey_ref->disabled; }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsSecretKey() const { return _subkey_ref->secret; }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool IsCardKey() const { return _subkey_ref->is_cardkey; }
+
+ /**
+ * @brief
+ *
+ * @return boost::posix_time::ptime
+ */
+ [[nodiscard]] boost::posix_time::ptime GetCreateTime() const {
+ return boost::posix_time::from_time_t(_subkey_ref->timestamp);
+ }
+
+ /**
+ * @brief
+ *
+ * @return boost::posix_time::ptime
+ */
+ [[nodiscard]] boost::posix_time::ptime GetExpireTime() const {
+ return boost::posix_time::from_time_t(_subkey_ref->expires);
+ }
+
+ /**
+ * @brief Construct a new Gpg Sub Key object
+ *
+ */
+ GpgSubKey() = default;
+
+ /**
+ * @brief Construct a new Gpg Sub Key object
+ *
+ * @param subkey
+ */
+ explicit GpgSubKey(gpgme_subkey_t subkey);
+
+ /**
+ * @brief Construct a new Gpg Sub Key object
+ *
+ * @param o
+ */
+ GpgSubKey(GpgSubKey&& o) noexcept { swap(_subkey_ref, o._subkey_ref); }
+
+ /**
+ * @brief Construct a new Gpg Sub Key object
+ *
+ */
+ GpgSubKey(const GpgSubKey&) = delete;
+
+ /**
+ * @brief
+ *
+ * @param o
+ * @return GpgSubKey&
+ */
+ GpgSubKey& operator=(GpgSubKey&& o) noexcept {
+ swap(_subkey_ref, o._subkey_ref);
+ return *this;
+ };
+
+ /**
+ * @brief
+ *
+ * @return GpgSubKey&
+ */
+ GpgSubKey& operator=(const GpgSubKey&) = delete;
+
+ /**
+ * @brief
+ *
+ * @param o
+ * @return true
+ * @return false
+ */
+ bool operator==(const GpgSubKey& o) const {
+ return GetFingerprint() == o.GetFingerprint();
+ }
+
+ private:
+ using SubkeyRefHandler =
+ std::unique_ptr<struct _gpgme_subkey,
+ std::function<void(gpgme_subkey_t)>>; ///<
+
+ SubkeyRefHandler _subkey_ref = nullptr; ///<
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_GPGSUBKEY_H
diff --git a/src/core/model/GpgTOFUInfo.cpp b/src/core/model/GpgTOFUInfo.cpp
new file mode 100644
index 00000000..8c83b360
--- /dev/null
+++ b/src/core/model/GpgTOFUInfo.cpp
@@ -0,0 +1,32 @@
+/**
+ * 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 "GpgTOFUInfo.h"
+
+GpgFrontend::GpgTOFUInfo::GpgTOFUInfo(gpgme_tofu_info_t tofu_info)
+ : _tofu_info_ref(tofu_info, [&](gpgme_tofu_info_t tofu_info) {}) {}
diff --git a/src/core/model/GpgTOFUInfo.h b/src/core/model/GpgTOFUInfo.h
new file mode 100644
index 00000000..b2fea4cf
--- /dev/null
+++ b/src/core/model/GpgTOFUInfo.h
@@ -0,0 +1,167 @@
+/**
+ * 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_GPGTOFU_H
+#define GPGFRONTEND_GPGTOFU_H
+
+#include "core/GpgConstants.h"
+
+namespace GpgFrontend {
+/**
+ * @brief
+ *
+ */
+class GpgTOFUInfo {
+ public:
+ /**
+ * @brief
+ *
+ * @return unsigned
+ */
+ [[nodiscard]] unsigned GetValidity() const {
+ return _tofu_info_ref->validity;
+ }
+
+ /**
+ * @brief
+ *
+ * @return unsigned
+ */
+ [[nodiscard]] unsigned GetPolicy() const { return _tofu_info_ref->policy; }
+
+ /**
+ * @brief
+ *
+ * @return unsigned long
+ */
+ [[nodiscard]] unsigned long GetSignCount() const {
+ return _tofu_info_ref->signcount;
+ }
+
+ /**
+ * @brief
+ *
+ * @return unsigned long
+ */
+ [[nodiscard]] unsigned long GetEncrCount() const {
+ return _tofu_info_ref->encrcount;
+ }
+
+ /**
+ * @brief
+ *
+ * @return unsigned long
+ */
+ [[nodiscard]] unsigned long GetSignFirst() const {
+ return _tofu_info_ref->signfirst;
+ }
+
+ /**
+ * @brief
+ *
+ * @return unsigned long
+ */
+ [[nodiscard]] unsigned long GetSignLast() const {
+ return _tofu_info_ref->signlast;
+ }
+
+ /**
+ * @brief
+ *
+ * @return unsigned long
+ */
+ [[nodiscard]] unsigned long GetEncrLast() const {
+ return _tofu_info_ref->encrlast;
+ }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetDescription() const {
+ return _tofu_info_ref->description;
+ }
+
+ /**
+ * @brief Construct a new Gpg T O F U Info object
+ *
+ */
+ GpgTOFUInfo() = default;
+
+ /**
+ * @brief Construct a new Gpg T O F U Info object
+ *
+ * @param tofu_info
+ */
+ explicit GpgTOFUInfo(gpgme_tofu_info_t tofu_info);
+
+ /**
+ * @brief Construct a new Gpg T O F U Info object
+ *
+ * @param o
+ */
+ GpgTOFUInfo(GpgTOFUInfo&& o) noexcept {
+ swap(_tofu_info_ref, o._tofu_info_ref);
+ }
+
+ /**
+ * @brief Construct a new Gpg T O F U Info object
+ *
+ */
+ GpgTOFUInfo(const GpgTOFUInfo&) = delete;
+
+ /**
+ * @brief
+ *
+ * @param o
+ * @return GpgTOFUInfo&
+ */
+ GpgTOFUInfo& operator=(GpgTOFUInfo&& o) noexcept {
+ swap(_tofu_info_ref, o._tofu_info_ref);
+ return *this;
+ };
+
+ /**
+ * @brief
+ *
+ * @return GpgTOFUInfo&
+ */
+ GpgTOFUInfo& operator=(const GpgTOFUInfo&) = delete;
+
+ private:
+ using SubkeyRefHandler =
+ std::unique_ptr<struct _gpgme_tofu_info,
+ std::function<void(gpgme_tofu_info_t)>>; ///<
+
+ SubkeyRefHandler _tofu_info_ref = nullptr; ///<
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_GPGTOFU_H
diff --git a/src/core/model/GpgUID.cpp b/src/core/model/GpgUID.cpp
new file mode 100644
index 00000000..6d98c882
--- /dev/null
+++ b/src/core/model/GpgUID.cpp
@@ -0,0 +1,32 @@
+/**
+ * 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 "core/model/GpgUID.h"
+
+GpgFrontend::GpgUID::GpgUID(gpgme_user_id_t uid)
+ : uid_ref_(uid, [&](gpgme_user_id_t uid) {}) {} \ No newline at end of file
diff --git a/src/core/model/GpgUID.h b/src/core/model/GpgUID.h
new file mode 100644
index 00000000..7f8daf98
--- /dev/null
+++ b/src/core/model/GpgUID.h
@@ -0,0 +1,171 @@
+/**
+ * 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_GPGUID_H
+#define GPGFRONTEND_GPGUID_H
+
+#include "GpgKeySignature.h"
+#include "GpgTOFUInfo.h"
+
+namespace GpgFrontend {
+/**
+ * @brief
+ *
+ */
+class GpgUID {
+ public:
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetName() const { return uid_ref_->name; }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetEmail() const { return uid_ref_->email; }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetComment() const { return uid_ref_->comment; }
+
+ /**
+ * @brief
+ *
+ * @return std::string
+ */
+ [[nodiscard]] std::string GetUID() const { return uid_ref_->uid; }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool GetRevoked() const { return uid_ref_->revoked; }
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] bool GetInvalid() const { return uid_ref_->invalid; }
+
+ /**
+ * @brief
+ *
+ * @return std::unique_ptr<std::vector<GpgTOFUInfo>>
+ */
+ [[nodiscard]] std::unique_ptr<std::vector<GpgTOFUInfo>> GetTofuInfos() const {
+ auto infos = std::make_unique<std::vector<GpgTOFUInfo>>();
+ auto info_next = uid_ref_->tofu;
+ while (info_next != nullptr) {
+ infos->push_back(GpgTOFUInfo(info_next));
+ info_next = info_next->next;
+ }
+ return infos;
+ }
+
+ /**
+ * @brief
+ *
+ * @return std::unique_ptr<std::vector<GpgKeySignature>>
+ */
+ [[nodiscard]] std::unique_ptr<std::vector<GpgKeySignature>> GetSignatures()
+ const {
+ auto sigs = std::make_unique<std::vector<GpgKeySignature>>();
+ auto sig_next = uid_ref_->signatures;
+ while (sig_next != nullptr) {
+ sigs->push_back(GpgKeySignature(sig_next));
+ sig_next = sig_next->next;
+ }
+ return sigs;
+ }
+
+ /**
+ * @brief Construct a new Gpg U I D object
+ *
+ */
+ GpgUID() = default;
+
+ /**
+ * @brief Construct a new Gpg U I D object
+ *
+ * @param uid
+ */
+ explicit GpgUID(gpgme_user_id_t uid);
+
+ /**
+ * @brief Construct a new Gpg U I D object
+ *
+ * @param o
+ */
+ GpgUID(GpgUID &&o) noexcept { swap(uid_ref_, o.uid_ref_); }
+
+ /**
+ * @brief Construct a new Gpg U I D object
+ *
+ */
+ GpgUID(const GpgUID &) = delete;
+
+ /**
+ * @brief
+ *
+ * @param o
+ * @return GpgUID&
+ */
+ GpgUID &operator=(GpgUID &&o) noexcept {
+ swap(uid_ref_, o.uid_ref_);
+ return *this;
+ }
+
+ /**
+ * @brief
+ *
+ * @return GpgUID&
+ */
+ GpgUID &operator=(const GpgUID &) = delete;
+
+ private:
+ using UidRefHandler =
+ std::unique_ptr<struct _gpgme_user_id,
+ std::function<void(gpgme_user_id_t)>>; ///<
+
+ UidRefHandler uid_ref_ = nullptr; ///<
+};
+
+} // namespace GpgFrontend
+
+#endif // GPGFRONTEND_GPGUID_H \ No newline at end of file