aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2025-02-03 14:42:38 +0000
committersaturneric <[email protected]>2025-02-03 14:42:38 +0000
commita6f82a3cbdbdd269796fecfb857440fda4e6ac6d (patch)
treed87609a7c8f50079ae648213ca979cb83923bd6d
parentfeat: upgrade gpgme to v1.24.1 (diff)
downloadGpgFrontend-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.cpp36
-rw-r--r--src/core/function/gpg/GpgKeyOpera.h25
-rw-r--r--src/core/model/GpgSubKey.cpp2
-rw-r--r--src/core/model/GpgSubKey.h10
-rw-r--r--src/test/core/GpgCoreTestCache.cpp6
-rw-r--r--src/test/core/GpgCoreTestKeyOpera.cpp134
-rw-r--r--src/ui/dialog/key_generate/SubkeyGenerateDialog.h3
-rw-r--r--src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp16
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")