diff options
author | saturneric <[email protected]> | 2025-02-03 14:42:38 +0000 |
---|---|---|
committer | saturneric <[email protected]> | 2025-02-03 14:42:38 +0000 |
commit | a6f82a3cbdbdd269796fecfb857440fda4e6ac6d (patch) | |
tree | d87609a7c8f50079ae648213ca979cb83923bd6d | |
parent | feat: upgrade gpgme to v1.24.1 (diff) | |
download | GpgFrontend-dev/2.1.6/adsk.tar.gz GpgFrontend-dev/2.1.6/adsk.zip |
feat: allow add and show ADSKdev/2.1.6/adsk
-rw-r--r-- | src/core/function/gpg/GpgKeyOpera.cpp | 36 | ||||
-rw-r--r-- | src/core/function/gpg/GpgKeyOpera.h | 25 | ||||
-rw-r--r-- | src/core/model/GpgSubKey.cpp | 2 | ||||
-rw-r--r-- | src/core/model/GpgSubKey.h | 10 | ||||
-rw-r--r-- | src/test/core/GpgCoreTestCache.cpp | 6 | ||||
-rw-r--r-- | src/test/core/GpgCoreTestKeyOpera.cpp | 134 | ||||
-rw-r--r-- | src/ui/dialog/key_generate/SubkeyGenerateDialog.h | 3 | ||||
-rw-r--r-- | src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp | 16 |
8 files changed, 215 insertions, 17 deletions
diff --git a/src/core/function/gpg/GpgKeyOpera.cpp b/src/core/function/gpg/GpgKeyOpera.cpp index 23a848ee..32ae1f83 100644 --- a/src/core/function/gpg/GpgKeyOpera.cpp +++ b/src/core/function/gpg/GpgKeyOpera.cpp @@ -364,4 +364,40 @@ void GpgKeyOpera::DeleteKey(const KeyId& key_id) { keys.push_back(key_id); DeleteKeys(keys); } + +auto AddADSK2KeyImpl(GpgContext& ctx, const GpgKey& key, const SubkeyId& s_fpr, + const DataObjectPtr& data_object) -> GpgError { + unsigned int flags = 0; + flags |= GPGME_CREATE_ADSK; + + auto err = + gpgme_op_createsubkey(ctx.DefaultContext(), static_cast<gpgme_key_t>(key), + s_fpr.toLatin1(), 0, 0, flags); + if (CheckGpgError(err) != GPG_ERR_NO_ERROR) { + data_object->Swap({GpgGenerateKeyResult{}}); + return err; + } + + data_object->Swap( + {GpgGenerateKeyResult{gpgme_op_genkey_result(ctx.DefaultContext())}}); + return CheckGpgError(err); +} + +void GpgKeyOpera::AddADSK2Key(const GpgKey& key, const SubkeyId& s_fpr, + const GpgOperationCallback& callback) { + RunGpgOperaAsync( + [=](const DataObjectPtr& data_object) -> GpgError { + return AddADSK2KeyImpl(ctx_, key, s_fpr, data_object); + }, + callback, "gpgme_op_createsubkey_adsk", "2.4.1"); +} + +auto GpgKeyOpera::AddADSK2KeySync(const GpgKey& key, const SubkeyId& s_fpr) + -> std::tuple<GpgError, DataObjectPtr> { + return RunGpgOperaSync( + [=](const DataObjectPtr& data_object) -> GpgError { + return AddADSK2KeyImpl(ctx_, key, s_fpr, data_object); + }, + "gpgme_op_createsubkey_adsk", "2.4.1"); +} } // namespace GpgFrontend diff --git a/src/core/function/gpg/GpgKeyOpera.h b/src/core/function/gpg/GpgKeyOpera.h index f6b7143e..f84333cc 100644 --- a/src/core/function/gpg/GpgKeyOpera.h +++ b/src/core/function/gpg/GpgKeyOpera.h @@ -28,8 +28,6 @@ #pragma once -#include <functional> - #include "core/function/gpg/GpgContext.h" #include "core/function/gpg/GpgKeyGetter.h" #include "core/typedef/GpgTypedef.h" @@ -108,6 +106,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera */ auto ModifyTOFUPolicy(const GpgKey& key, gpgme_tofu_policy_t tofu_policy) -> GpgFrontend::GpgError; + /** * @brief * @@ -170,6 +169,28 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera const QSharedPointer<KeyGenerateInfo>& s_params) -> std::tuple<GpgError, DataObjectPtr>; + /** + * @brief + * + * @param key + * @param s_fpr + * @param callback + * @return auto + */ + void AddADSK2Key(const GpgKey& key, const SubkeyId& s_fpr, + const GpgOperationCallback& callback); + + /** + * @brief + * + * @param key + * @param s_fpr + * @param callback + * @return auto + */ + auto AddADSK2KeySync(const GpgKey& key, const SubkeyId& s_fpr) + -> std::tuple<GpgError, DataObjectPtr>; + private: GpgContext& ctx_ = GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); ///< diff --git a/src/core/model/GpgSubKey.cpp b/src/core/model/GpgSubKey.cpp index 98b87706..02411726 100644 --- a/src/core/model/GpgSubKey.cpp +++ b/src/core/model/GpgSubKey.cpp @@ -74,6 +74,8 @@ auto GpgSubKey::IsHasAuthCap() const -> bool { return subkey_ref_->can_authenticate; } +auto GpgSubKey::IsADSK() const -> bool { return subkey_ref_->can_renc; } + auto GpgSubKey::IsPrivateKey() const -> bool { return subkey_ref_->secret; } auto GpgSubKey::IsExpired() const -> bool { return subkey_ref_->expired; } diff --git a/src/core/model/GpgSubKey.h b/src/core/model/GpgSubKey.h index f7d6afd9..affd56bd 100644 --- a/src/core/model/GpgSubKey.h +++ b/src/core/model/GpgSubKey.h @@ -167,7 +167,15 @@ class GPGFRONTEND_CORE_EXPORT GpgSubKey { * * @return QDateTime */ - [[nodiscard]] QDateTime GetExpireTime() const; + [[nodiscard]] auto GetExpireTime() const -> QDateTime; + + /** + * @brief + * + * @return true + * @return false + */ + [[nodiscard]] auto IsADSK() const -> bool; /** * @brief Construct a new Gpg Sub Key object diff --git a/src/test/core/GpgCoreTestCache.cpp b/src/test/core/GpgCoreTestCache.cpp index a791bf8d..f3d74b31 100644 --- a/src/test/core/GpgCoreTestCache.cpp +++ b/src/test/core/GpgCoreTestCache.cpp @@ -48,10 +48,10 @@ TEST_F(GpgCoreTest, CoreCacheTestB) { } TEST_F(GpgCoreTest, CoreCacheTestC) { - CacheManager::GetInstance().SaveCache("ABCDEF", "DEFEEE", 2); + CacheManager::GetInstance().SaveCache("ABCDEF", "DEFEEE", 1); ASSERT_EQ(CacheManager::GetInstance().LoadCache("ABCDEF"), QString("DEFEEE")); - std::this_thread::sleep_for(std::chrono::milliseconds(4000)); - ASSERT_EQ(CacheManager::GetInstance().LoadCache("ABCDEF"), QString("")); + std::this_thread::sleep_for(std::chrono::milliseconds(1200)); + ASSERT_TRUE(CacheManager::GetInstance().LoadCache("ABCDEF") == QString()); } } // namespace GpgFrontend::Test
\ No newline at end of file diff --git a/src/test/core/GpgCoreTestKeyOpera.cpp b/src/test/core/GpgCoreTestKeyOpera.cpp new file mode 100644 index 00000000..5a15e005 --- /dev/null +++ b/src/test/core/GpgCoreTestKeyOpera.cpp @@ -0,0 +1,134 @@ +/** + * Copyright (C) 2021-2024 Saturneric <[email protected]> + * + * 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 "GpgCoreTest.h" +#include "core/GpgConstants.h" +#include "core/function/gpg/GpgKeyGetter.h" +#include "core/function/gpg/GpgKeyImportExporter.h" +#include "core/function/gpg/GpgKeyOpera.h" +#include "core/model/GpgImportInformation.h" +#include "core/utils/GpgUtils.h" + +static const char *test_private_key_data = R"( +-----BEGIN PGP PRIVATE KEY BLOCK----- + +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 +cT12+dGCVkzJXnWZXTk/4A== +=VmHj +-----END PGP PRIVATE KEY BLOCK----- + +-----BEGIN PGP PRIVATE KEY BLOCK----- + +lFgEZ5+j3xYJKwYBBAHaRw8BAQdAYzou04dN5/KuKTrM80w2fRGv+656y0Y5e/ST +jNJCq7UAAP44jXmba5En/xZ486kOW+9n/NJ5wPy1asUincFhj7doghLatBpnZ2dn +ZyhnZ2dnZyk8Z2dnZ0BnZ2cuZ2dnPoiTBBMWCgA7FiEE6l89cR32HIl+PWSqGKHw +OeM3f6kFAmefo98CGyMFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQGKHw +OeM3f6kUvgEAz9f89YuVbzftl6mzhaPgRDqxh7Dmxy0o2/SdxiofLdEBAIkc6Vo/ +PLzKYcnA8my05aF1dJ7B/CZssVKYW/c71B0FnF0EZ5+j3xIKKwYBBAGXVQEFAQEH +QIEXHJ39jsYYPeHezXS0u0chlyjZupL2f8FwA+UDgRBWAwEIBwAA/1lbjTXQp2MX +ctRaqik7M0mCJmIGAQjFigTcFNWs0lmwDkiIeAQYFgoAIBYhBOpfPXEd9hyJfj1k +qhih8DnjN3+pBQJnn6PfAhsMAAoJEBih8DnjN3+p4rYA/iKnxqzqJaxWLpxywDOT +2c/wCsje0ZqMQjwfwZJavICTAP900WK3uE9tXfQPQfD+Vb+5SHJrlSLhhLY+niOE +MGJbAg== +=R6Bn +-----END PGP PRIVATE KEY BLOCK----- +)"; + +namespace GpgFrontend::Test { + +TEST_F(GpgCoreTest, CoreAddADSKTestA) { + auto info = GpgKeyImportExporter::GetInstance().ImportKey( + GFBuffer(QString::fromLatin1(test_private_key_data))); + + ASSERT_EQ(info->not_imported, 0); + ASSERT_EQ(info->imported, 2); + + auto key = GpgKeyGetter::GetInstance(kGpgFrontendDefaultChannel) + .GetKey("1D36EBABAAAE4996"); + ASSERT_TRUE(key.IsGood()); + + auto subkeys = key.GetSubKeys(); + + ASSERT_EQ(subkeys->size(), 5); + ASSERT_EQ((*subkeys)[2].GetID(), "2D1F9FC59B568A8C"); + + auto [err, data_objet] = + GpgKeyOpera::GetInstance().AddADSK2KeySync(key, "37D98546C662B088"); + + ASSERT_TRUE(CheckGpgError(err) == GPG_ERR_NO_ERROR); + + GpgKeyGetter::GetInstance().FlushKeyCache(); + key = GpgKeyGetter::GetInstance(kGpgFrontendDefaultChannel) + .GetKey("1D36EBABAAAE4996"); + ASSERT_TRUE(key.IsGood()); + + subkeys = key.GetSubKeys(); + + ASSERT_EQ(subkeys->size(), 3); + ASSERT_EQ((*subkeys)[2].GetID(), "2D1F9FC59B568A8C"); + ASSERT_TRUE((*subkeys)[2].IsADSK()); + + GpgKeyOpera::GetInstance().DeleteKey(key.GetId()); +} + +} // namespace GpgFrontend::Test
\ No newline at end of file diff --git a/src/ui/dialog/key_generate/SubkeyGenerateDialog.h b/src/ui/dialog/key_generate/SubkeyGenerateDialog.h index 96dee49e..1e37d6b5 100644 --- a/src/ui/dialog/key_generate/SubkeyGenerateDialog.h +++ b/src/ui/dialog/key_generate/SubkeyGenerateDialog.h @@ -28,12 +28,9 @@ #pragma once -#include "core/function/gpg/GpgContext.h" #include "core/model/GpgKey.h" #include "core/model/GpgKeyGenerateInfo.h" #include "core/typedef/GpgTypedef.h" -#include "core/utils/MemoryUtils.h" -#include "ui/GpgFrontendUI.h" #include "ui/dialog/GeneralDialog.h" class Ui_SubkeyGenDialog; diff --git a/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp b/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp index 548b3473..88e313c4 100644 --- a/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp +++ b/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp @@ -306,14 +306,14 @@ void KeyPairSubkeyTab::slot_refresh_subkey_detail() { QString buffer; QTextStream usage_steam(&buffer); - if (subkey.IsHasCertCap()) { - usage_steam << tr("Certificate") << " "; - } - if (subkey.IsHasEncrCap()) usage_steam << tr("Encrypt") << " "; - if (subkey.IsHasSignCap()) usage_steam << tr("Sign") << " "; - if (subkey.IsHasAuthCap()) usage_steam << tr("Auth") << " "; - - usage_var_label_->setText(usage_steam.readAll()); + if (subkey.IsHasCertCap()) usage_steam << "C"; + if (subkey.IsHasEncrCap()) usage_steam << "E"; + if (subkey.IsHasSignCap()) usage_steam << "S"; + if (subkey.IsHasAuthCap()) usage_steam << "A"; + if (subkey.IsADSK()) usage_steam << "R"; + + const auto usage = usage_steam.readAll(); + usage_var_label_->setText(usage.isEmpty() ? "/" : usage); // Show the situation that secret key not exists. master_key_exist_var_label_->setText(subkey.IsSecretKey() ? tr("Exists") |