diff options
Diffstat (limited to 'src/core/function/gpg')
-rw-r--r-- | src/core/function/gpg/GpgBasicOperator.cpp | 220 | ||||
-rw-r--r-- | src/core/function/gpg/GpgBasicOperator.h | 179 | ||||
-rw-r--r-- | src/core/function/gpg/GpgCommandExecutor.cpp | 63 | ||||
-rw-r--r-- | src/core/function/gpg/GpgCommandExecutor.h | 77 | ||||
-rw-r--r-- | src/core/function/gpg/GpgFileOpera.cpp | 182 | ||||
-rw-r--r-- | src/core/function/gpg/GpgFileOpera.h | 153 | ||||
-rw-r--r-- | src/core/function/gpg/GpgKeyGetter.cpp | 96 | ||||
-rw-r--r-- | src/core/function/gpg/GpgKeyGetter.h | 110 | ||||
-rw-r--r-- | src/core/function/gpg/GpgKeyImportExporter.cpp | 178 | ||||
-rw-r--r-- | src/core/function/gpg/GpgKeyImportExporter.h | 195 | ||||
-rw-r--r-- | src/core/function/gpg/GpgKeyManager.cpp | 92 | ||||
-rw-r--r-- | src/core/function/gpg/GpgKeyManager.h | 93 | ||||
-rw-r--r-- | src/core/function/gpg/GpgKeyOpera.cpp | 293 | ||||
-rw-r--r-- | src/core/function/gpg/GpgKeyOpera.h | 135 | ||||
-rw-r--r-- | src/core/function/gpg/GpgUIDOperator.cpp | 68 | ||||
-rw-r--r-- | src/core/function/gpg/GpgUIDOperator.h | 88 |
16 files changed, 2222 insertions, 0 deletions
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 |