diff options
Diffstat (limited to '')
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | src/gpg/GpgGenKeyInfo.cpp | 131 | ||||
-rw-r--r-- | src/gpg/GpgGenKeyInfo.h | 93 | ||||
-rw-r--r-- | src/gpg/function/GpgKeyOpera.cpp | 10 | ||||
-rw-r--r-- | test/GpgCoreTestKeygenAlone.cpp | 156 |
5 files changed, 306 insertions, 85 deletions
@@ -2,6 +2,7 @@ src/GpgFrontend.h src/GpgFrontendBuildInfo.h src/GpgFrontendBuildInstallInfo.h +third_party/AppImageUpdate # gettext *.mo diff --git a/src/gpg/GpgGenKeyInfo.cpp b/src/gpg/GpgGenKeyInfo.cpp index 4a0a99fc..124c66e8 100644 --- a/src/gpg/GpgGenKeyInfo.cpp +++ b/src/gpg/GpgGenKeyInfo.cpp @@ -32,18 +32,41 @@ #include <string> #include <vector> -const std::vector<std::string> GpgFrontend::GenKeyInfo::SupportedKeyAlgo = { - "RSA", "DSA", "ED25519"}; - -const std::vector<std::string> GpgFrontend::GenKeyInfo::SupportedSubkeyAlgo = { - "RSA", "DSA", "ED25519", "ELG"}; - void GpgFrontend::GenKeyInfo::setAlgo(const std::string &m_algo) { - LOG(INFO) << "GpgFrontend::GenKeyInfo::setAlgo m_algo" << 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) { + if (!this->subkey_) { this->setAllowCertification(true); } else { this->setAllowCertification(false); @@ -51,23 +74,20 @@ void GpgFrontend::GenKeyInfo::setAlgo(const std::string &m_algo) { this->allowChangeCertification = false; - std::string lower_algo = std::string(m_algo); - boost::algorithm::to_lower(lower_algo); - - LOG(INFO) << "GpgFrontend::GenKeyInfo::setAlgo lower_algo" << lower_algo; + if (!standalone_) boost::algorithm::to_lower(algo_args); - if (lower_algo == "rsa") { + 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. */ - suggestMinKeySize = 1024; - suggestMaxKeySize = 4096; - suggestSizeAdditionStep = 1024; + suggest_min_key_size_ = 1024; + suggest_max_key_size_ = 4096; + suggest_size_addition_step_ = 1024; setKeySize(2048); - } else if (lower_algo == "dsa") { + } else if (algo_args == "dsa") { /** * Algorithm (DSA) as a government standard for digital signatures. * Originally, it supported key lengths between 512 and 1024 bits. @@ -77,42 +97,40 @@ void GpgFrontend::GenKeyInfo::setAlgo(const std::string &m_algo) { setAllowEncryption(false); allowChangeEncryption = false; - suggestMinKeySize = 1024; - suggestMaxKeySize = 3072; - suggestSizeAdditionStep = 1024; + suggest_min_key_size_ = 1024; + suggest_max_key_size_ = 3072; + suggest_size_addition_step_ = 1024; setKeySize(2048); - } else if (lower_algo == "ed25519") { + } else if (algo_args == "ed25519") { /** * GnuPG supports the Elgamal asymmetric encryption algorithm in key lengths * ranging from 1024 to 4096 bits. */ - setAllowEncryption(false); allowChangeEncryption = false; - suggestMinKeySize = -1; - suggestMaxKeySize = -1; - suggestSizeAdditionStep = -1; + suggest_min_key_size_ = -1; + suggest_max_key_size_ = -1; + suggest_size_addition_step_ = -1; setKeySize(-1); - } else if (lower_algo == "elg") { + } else if (algo_args == "elg") { /** * GnuPG supports the Elgamal asymmetric encryption algorithm in key lengths * ranging from 1024 to 4096 bits. */ - setAllowAuthentication(false); allowChangeAuthentication = false; setAllowSigning(false); allowChangeSigning = false; - suggestMinKeySize = 1024; - suggestMaxKeySize = 4096; - suggestSizeAdditionStep = 1024; + suggest_min_key_size_ = 1024; + suggest_max_key_size_ = 4096; + suggest_size_addition_step_ = 1024; setKeySize(2048); } - this->algo = lower_algo; + this->algo_ = algo_args; } void GpgFrontend::GenKeyInfo::reset_options() { @@ -128,37 +146,38 @@ void GpgFrontend::GenKeyInfo::reset_options() { allowChangeAuthentication = true; setAllowAuthentication(true); - passPhrase.clear(); + passphrase_.clear(); } std::string GpgFrontend::GenKeyInfo::getKeySizeStr() const { - if (keySize > 0) { - return std::to_string(keySize); + if (key_size_ > 0) { + return std::to_string(key_size_); } else { return {}; } } void GpgFrontend::GenKeyInfo::setKeySize(int m_key_size) { - if (m_key_size < suggestMinKeySize || m_key_size > suggestMaxKeySize) { + if (m_key_size < suggest_min_key_size_ || + m_key_size > suggest_max_key_size_) { return; } - GenKeyInfo::keySize = m_key_size; + GenKeyInfo::key_size_ = m_key_size; } void GpgFrontend::GenKeyInfo::setExpired( const boost::posix_time::ptime &m_expired) { using namespace boost::gregorian; auto current = boost::posix_time::second_clock::local_time(); - if (isNonExpired() && m_expired < current + years(2)) { - GenKeyInfo::expired = m_expired; + 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::nonExpired = m_non_expired; + if (!m_non_expired) this->expired_ = from_time_t(0); + GenKeyInfo::non_expired_ = m_non_expired; } void GpgFrontend::GenKeyInfo::setAllowEncryption(bool m_allow_encryption) { @@ -170,3 +189,35 @@ void GpgFrontend::GenKeyInfo::setAllowCertification( if (allowChangeCertification) GenKeyInfo::allowCertification = 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/gpg/GpgGenKeyInfo.h b/src/gpg/GpgGenKeyInfo.h index cc679656..8f7d19ea 100644 --- a/src/gpg/GpgGenKeyInfo.h +++ b/src/gpg/GpgGenKeyInfo.h @@ -34,83 +34,90 @@ namespace GpgFrontend { class GenKeyInfo { - bool subKey = true; - std::string name; - std::string email; - std::string comment; - - std::string algo; - int keySize = 2048; - boost::posix_time::ptime expired = + 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 nonExpired = false; + bool non_expired_ = false; - bool noPassPhrase = false; - bool allowNoPassPhrase = true; + bool no_passphrase_ = false; + bool allow_no_pass_phrase_ = true; - int suggestMaxKeySize = 4096; - int suggestSizeAdditionStep = 1024; - int suggestMinKeySize = 1024; + int suggest_max_key_size_ = 4096; + int suggest_size_addition_step_ = 1024; + int suggest_min_key_size_ = 1024; - std::string passPhrase; + std::string passphrase_; public: - static const std::vector<std::string> SupportedKeyAlgo; + static const std::vector<std::string> &getSupportedKeyAlgo(); - static const std::vector<std::string> SupportedSubkeyAlgo; + static const std::vector<std::string> &getSupportedSubkeyAlgo(); - [[nodiscard]] bool isSubKey() const { return subKey; } + static const std::vector<std::string> &getSupportedKeyAlgoStandalone(); - void setIsSubKey(bool m_sub_key) { GenKeyInfo::subKey = m_sub_key; } + static const std::vector<std::string> &getSupportedSubkeyAlgoStandalone(); + + [[nodiscard]] bool isSubKey() const { return subkey_; } + + void setIsSubKey(bool m_sub_key) { GenKeyInfo::subkey_ = m_sub_key; } [[nodiscard]] std::string getUserid() const { - auto uid_format = boost::format("%1%(%2%)<%3%>") % this->name % - this->comment % this->email; + auto uid_format = boost::format("%1%(%2%)<%3%>") % this->name_ % + this->comment_ % this->email_; return uid_format.str(); } - void setName(const std::string &m_name) { this->name = m_name; } + void setName(const std::string &m_name) { this->name_ = m_name; } - void setEmail(const std::string &m_email) { this->email = m_email; } + void setEmail(const std::string &m_email) { this->email_ = m_email; } - void setComment(const std::string &m_comment) { this->comment = m_comment; } + void setComment(const std::string &m_comment) { this->comment_ = m_comment; } - [[nodiscard]] std::string getName() const { return name; } + [[nodiscard]] std::string getName() const { return name_; } - [[nodiscard]] std::string getEmail() const { return email; } + [[nodiscard]] std::string getEmail() const { return email_; } - [[nodiscard]] std::string getComment() const { return comment; } + [[nodiscard]] std::string getComment() const { return comment_; } - [[nodiscard]] const std::string &getAlgo() const { return algo; } + [[nodiscard]] const std::string &getAlgo() const { return algo_; } void setAlgo(const std::string &m_algo); [[nodiscard]] std::string getKeySizeStr() const; - [[nodiscard]] int getKeySize() const { return keySize; } + [[nodiscard]] int getKeySize() const { return key_size_; } void setKeySize(int m_key_size); [[nodiscard]] const boost::posix_time::ptime &getExpired() const { - return expired; + return expired_; } void setExpired(const boost::posix_time::ptime &m_expired); - [[nodiscard]] bool isNonExpired() const { return nonExpired; } + [[nodiscard]] bool isNonExpired() const { return non_expired_; } void setNonExpired(bool m_non_expired); - [[nodiscard]] bool isNoPassPhrase() const { return this->noPassPhrase; } + [[nodiscard]] bool isNoPassPhrase() const { return this->no_passphrase_; } void setNonPassPhrase(bool m_non_pass_phrase) { - GenKeyInfo::noPassPhrase = m_non_pass_phrase; + GenKeyInfo::no_passphrase_ = m_non_pass_phrase; } [[nodiscard]] bool isAllowSigning() const { return allowSigning; } - [[nodiscard]] bool isAllowNoPassPhrase() const { return allowNoPassPhrase; } + [[nodiscard]] bool isAllowNoPassPhrase() const { + return allow_no_pass_phrase_; + } void setAllowSigning(bool m_allow_signing) { if (allowChangeSigning) GenKeyInfo::allowSigning = m_allow_signing; @@ -133,10 +140,10 @@ class GenKeyInfo { GenKeyInfo::allowAuthentication = m_allow_authentication; } - [[nodiscard]] const std::string &getPassPhrase() const { return passPhrase; } + [[nodiscard]] const std::string &getPassPhrase() const { return passphrase_; } void setPassPhrase(const std::string &m_pass_phrase) { - GenKeyInfo::passPhrase = m_pass_phrase; + GenKeyInfo::passphrase_ = m_pass_phrase; } [[nodiscard]] bool isAllowChangeSigning() const { return allowChangeSigning; } @@ -152,12 +159,16 @@ class GenKeyInfo { return allowChangeAuthentication; } - [[nodiscard]] int getSuggestMaxKeySize() const { return suggestMaxKeySize; } + [[nodiscard]] int getSuggestMaxKeySize() const { + return suggest_max_key_size_; + } - [[nodiscard]] int getSuggestMinKeySize() const { return suggestMinKeySize; } + [[nodiscard]] int getSuggestMinKeySize() const { + return suggest_min_key_size_; + } [[nodiscard]] int getSizeChangeStep() const { - return suggestSizeAdditionStep; + return suggest_size_addition_step_; } private: @@ -176,9 +187,7 @@ class GenKeyInfo { void reset_options(); public: - explicit GenKeyInfo(bool m_is_sub_key = false) : subKey(m_is_sub_key) { - setAlgo("rsa"); - } + explicit GenKeyInfo(bool m_is_sub_key = false, bool m_standalone = false); }; } // namespace GpgFrontend diff --git a/src/gpg/function/GpgKeyOpera.cpp b/src/gpg/function/GpgKeyOpera.cpp index 4cbc1d0a..df89c6f5 100644 --- a/src/gpg/function/GpgKeyOpera.cpp +++ b/src/gpg/function/GpgKeyOpera.cpp @@ -187,7 +187,8 @@ GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::GenerateKey( boost::format{ "<GnupgKeyParms format=\"internal\">\n" "Key-Type: %1%\n" - "Subkey-Type: %2%\n" + "Key-Usage: sign\n" + "Key-Length: %2%\n" "Name-Real: %3%\n" "Name-Comment: %4%\n" "Name-Email: %5%\n"} % @@ -195,8 +196,11 @@ GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::GenerateKey( params->getComment() % params->getEmail(); ss << param_format; - if (!params->isNonExpired()) - ss << boost::format{"Expire-Date: %1%\n"} % expires; + if (!params->isNonExpired()) { + auto date = params->getExpired().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(); diff --git a/test/GpgCoreTestKeygenAlone.cpp b/test/GpgCoreTestKeygenAlone.cpp new file mode 100644 index 00000000..4a725ba7 --- /dev/null +++ b/test/GpgCoreTestKeygenAlone.cpp @@ -0,0 +1,156 @@ +/** + * 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. + * + * Foobar 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 Foobar. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from gpg4usb-team. + * Their source code version also complies with GNU General Public License. + * + * The source code version of this software was modified and released + * by Saturneric<[email protected]> starting on May 12, 2021. + * + */ + +#include "GpgFrontendTest.h" +#include "gpg/GpgGenKeyInfo.h" +#include "gpg/function/GpgKeyGetter.h" +#include "gpg/function/GpgKeyOpera.h" + +TEST_F(GpgCoreTest, GenerateKeyTestAlone) { + auto& key_opera = GpgFrontend::GpgKeyOpera::GetInstance(gpg_alone_channel); + auto keygen_info = std::make_unique<GpgFrontend::GenKeyInfo>(false, true); + keygen_info->setName("foobar"); + keygen_info->setEmail("[email protected]"); + keygen_info->setComment("hello"); + keygen_info->setAlgo("rsa"); + keygen_info->setNonExpired(true); + keygen_info->setNonPassPhrase(true); + + GpgFrontend::GpgGenKeyResult result = nullptr; + auto err = GpgFrontend::check_gpg_error_2_err_code( + key_opera.GenerateKey(keygen_info, result)); + ASSERT_EQ(err, GPG_ERR_NO_ERROR); + + auto fpr = result->fpr; + ASSERT_FALSE(fpr == nullptr); + + auto key = + GpgFrontend::GpgKeyGetter::GetInstance(gpg_alone_channel).GetKey(fpr); + ASSERT_TRUE(key.good()); + key_opera.DeleteKey(fpr); +} + +TEST_F(GpgCoreTest, GenerateKeyTestAlone_1) { + auto& key_opera = GpgFrontend::GpgKeyOpera::GetInstance(gpg_alone_channel); + auto keygen_info = std::make_unique<GpgFrontend::GenKeyInfo>(false, true); + keygen_info->setName("foobar"); + keygen_info->setEmail("[email protected]"); + keygen_info->setComment("hello gpgfrontend"); + keygen_info->setAlgo("rsa"); + keygen_info->setNonExpired(false); + keygen_info->setPassPhrase("abcdefg"); + keygen_info->setExpired(boost::posix_time::second_clock::local_time() + + boost::posix_time::hours(24)); + keygen_info->setNonPassPhrase(false); + + GpgFrontend::GpgGenKeyResult result = nullptr; + auto err = GpgFrontend::check_gpg_error_2_err_code( + key_opera.GenerateKey(keygen_info, result)); + ASSERT_EQ(err, GPG_ERR_NO_ERROR); + + auto fpr = result->fpr; + ASSERT_FALSE(fpr == nullptr); + + auto key = + GpgFrontend::GpgKeyGetter::GetInstance(gpg_alone_channel).GetKey(fpr); + ASSERT_TRUE(key.good()); + key_opera.DeleteKey(fpr); +} + +TEST_F(GpgCoreTest, GenerateKeyTestAlone_2) { + auto& key_opera = GpgFrontend::GpgKeyOpera::GetInstance(gpg_alone_channel); + auto keygen_info = std::make_unique<GpgFrontend::GenKeyInfo>(false, true); + keygen_info->setName("foobar"); + keygen_info->setEmail("[email protected]"); + keygen_info->setComment("hi"); + keygen_info->setAlgo("rsa"); + keygen_info->setKeySize(3072); + keygen_info->setNonExpired(true); + keygen_info->setNonPassPhrase(false); + keygen_info->setPassPhrase("abcdefg"); + + GpgFrontend::GpgGenKeyResult result = nullptr; + auto err = GpgFrontend::check_gpg_error_2_err_code( + key_opera.GenerateKey(keygen_info, result)); + ASSERT_EQ(err, GPG_ERR_NO_ERROR); + + auto fpr = result->fpr; + ASSERT_FALSE(fpr == nullptr); + + auto key = + GpgFrontend::GpgKeyGetter::GetInstance(gpg_alone_channel).GetKey(fpr); + ASSERT_TRUE(key.good()); + key_opera.DeleteKey(fpr); +} + +TEST_F(GpgCoreTest, GenerateKeyTestAlone_3) { + auto& key_opera = GpgFrontend::GpgKeyOpera::GetInstance(gpg_alone_channel); + auto keygen_info = std::make_unique<GpgFrontend::GenKeyInfo>(false, true); + keygen_info->setName("foo"); + keygen_info->setEmail("[email protected]"); + keygen_info->setComment("hello"); + keygen_info->setAlgo("rsa"); + keygen_info->setKeySize(4096); + keygen_info->setNonExpired(true); + keygen_info->setNonPassPhrase(false); + keygen_info->setPassPhrase("abcdefg"); + + GpgFrontend::GpgGenKeyResult result = nullptr; + auto err = GpgFrontend::check_gpg_error_2_err_code( + key_opera.GenerateKey(keygen_info, result)); + ASSERT_EQ(err, GPG_ERR_NO_ERROR); + + auto fpr = result->fpr; + ASSERT_FALSE(fpr == nullptr); + + auto key = + GpgFrontend::GpgKeyGetter::GetInstance(gpg_alone_channel).GetKey(fpr); + ASSERT_TRUE(key.good()); + key_opera.DeleteKey(fpr); +} + +TEST_F(GpgCoreTest, GenerateKeyTestAlone_4) { + auto& key_opera = GpgFrontend::GpgKeyOpera::GetInstance(gpg_alone_channel); + auto keygen_info = std::make_unique<GpgFrontend::GenKeyInfo>(false, true); + keygen_info->setName("foobar"); + keygen_info->setEmail("[email protected]"); + keygen_info->setComment("hello"); + keygen_info->setAlgo("dsa"); + keygen_info->setNonExpired(true); + keygen_info->setNonPassPhrase(false); + keygen_info->setPassPhrase("abcdefg"); + + GpgFrontend::GpgGenKeyResult result = nullptr; + auto err = GpgFrontend::check_gpg_error_2_err_code( + key_opera.GenerateKey(keygen_info, result)); + ASSERT_EQ(err, GPG_ERR_NO_ERROR); + + auto fpr = result->fpr; + ASSERT_FALSE(fpr == nullptr); + + auto key = + GpgFrontend::GpgKeyGetter::GetInstance(gpg_alone_channel).GetKey(fpr); + ASSERT_TRUE(key.good()); + key_opera.DeleteKey(fpr); +}
\ No newline at end of file |