diff options
Diffstat (limited to 'src/core')
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 |