/** * Tests for keyring management methods on PackageManagerImpl. */ #include #include "package_manager_impl.h" #include #include #include #include #include #include /** * Helper: read DID from a .did file. */ static std::string readDid(const QString& keysDir, const QString& keyName) { QFile f(keysDir + "/" + keyName + ".did"); if (!f.open(QIODevice::ReadOnly)) return {}; return QString::fromUtf8(f.readAll()).trimmed().toStdString(); } /** * Helper: generate a keypair and return the DID. */ static std::string generateKeyAndGetDid(const QString& keysDir, const QString& keyName) { lgx_result_t res = lgx_keygen(keyName.toStdString().c_str(), keysDir.toStdString().c_str()); if (!res.success) return {}; return readDid(keysDir, keyName); } // ============================================================================= // Add trusted key // ============================================================================= LOGOS_TEST(add_trusted_key_success) { PackageManagerImpl impl; QTemporaryDir tmpDir; LOGOS_ASSERT_TRUE(tmpDir.isValid()); QString keysDir = tmpDir.path() + "/keys"; QString keyringDir = tmpDir.path() + "/keyring"; QDir().mkpath(keysDir); QDir().mkpath(keyringDir); impl.setKeyringDirectory(keyringDir.toStdString()); std::string did = generateKeyAndGetDid(keysDir, "addkey"); LOGOS_ASSERT_FALSE(did.empty()); LogosMap result = impl.addTrustedKey("publisher", did, "Test Publisher", "https://test.com"); LOGOS_ASSERT_TRUE(result["success"].get()); } LOGOS_TEST(add_trusted_key_invalid_did) { PackageManagerImpl impl; QTemporaryDir tmpDir; LOGOS_ASSERT_TRUE(tmpDir.isValid()); QString keyringDir = tmpDir.path() + "/keyring"; QDir().mkpath(keyringDir); impl.setKeyringDirectory(keyringDir.toStdString()); LogosMap result = impl.addTrustedKey("bad", "not-a-did", "", ""); LOGOS_ASSERT_FALSE(result["success"].get()); LOGOS_ASSERT_TRUE(result.contains("error")); } // ============================================================================= // Remove trusted key // ============================================================================= LOGOS_TEST(remove_trusted_key_success) { PackageManagerImpl impl; QTemporaryDir tmpDir; LOGOS_ASSERT_TRUE(tmpDir.isValid()); QString keysDir = tmpDir.path() + "/keys"; QString keyringDir = tmpDir.path() + "/keyring"; QDir().mkpath(keysDir); QDir().mkpath(keyringDir); impl.setKeyringDirectory(keyringDir.toStdString()); std::string did = generateKeyAndGetDid(keysDir, "rmkey"); LOGOS_ASSERT_FALSE(did.empty()); // Add then remove LogosMap addResult = impl.addTrustedKey("to-remove", did, "", ""); LOGOS_ASSERT_TRUE(addResult["success"].get()); LogosMap rmResult = impl.removeTrustedKey("to-remove"); LOGOS_ASSERT_TRUE(rmResult["success"].get()); } LOGOS_TEST(remove_nonexistent_key) { PackageManagerImpl impl; QTemporaryDir tmpDir; LOGOS_ASSERT_TRUE(tmpDir.isValid()); QString keyringDir = tmpDir.path() + "/keyring"; QDir().mkpath(keyringDir); impl.setKeyringDirectory(keyringDir.toStdString()); LogosMap result = impl.removeTrustedKey("does-not-exist"); LOGOS_ASSERT_FALSE(result["success"].get()); } // ============================================================================= // List trusted keys // ============================================================================= LOGOS_TEST(list_trusted_keys_empty) { PackageManagerImpl impl; QTemporaryDir tmpDir; LOGOS_ASSERT_TRUE(tmpDir.isValid()); QString keyringDir = tmpDir.path() + "/keyring"; QDir().mkpath(keyringDir); impl.setKeyringDirectory(keyringDir.toStdString()); LogosList keys = impl.listTrustedKeys(); LOGOS_ASSERT_EQ(keys.size(), static_cast(0)); } LOGOS_TEST(list_trusted_keys_after_add) { PackageManagerImpl impl; QTemporaryDir tmpDir; LOGOS_ASSERT_TRUE(tmpDir.isValid()); QString keysDir = tmpDir.path() + "/keys"; QString keyringDir = tmpDir.path() + "/keyring"; QDir().mkpath(keysDir); QDir().mkpath(keyringDir); impl.setKeyringDirectory(keyringDir.toStdString()); std::string did1 = generateKeyAndGetDid(keysDir, "listkey1"); std::string did2 = generateKeyAndGetDid(keysDir, "listkey2"); LOGOS_ASSERT_FALSE(did1.empty()); LOGOS_ASSERT_FALSE(did2.empty()); impl.addTrustedKey("key-one", did1, "Publisher One", "https://one.com"); impl.addTrustedKey("key-two", did2, "Publisher Two", ""); LogosList keys = impl.listTrustedKeys(); LOGOS_ASSERT_EQ(keys.size(), static_cast(2)); // Collect names std::vector names; for (const auto& key : keys) { names.push_back(key["name"].get()); } LOGOS_ASSERT_TRUE(std::find(names.begin(), names.end(), "key-one") != names.end()); LOGOS_ASSERT_TRUE(std::find(names.begin(), names.end(), "key-two") != names.end()); } LOGOS_TEST(list_trusted_keys_contains_metadata) { PackageManagerImpl impl; QTemporaryDir tmpDir; LOGOS_ASSERT_TRUE(tmpDir.isValid()); QString keysDir = tmpDir.path() + "/keys"; QString keyringDir = tmpDir.path() + "/keyring"; QDir().mkpath(keysDir); QDir().mkpath(keyringDir); impl.setKeyringDirectory(keyringDir.toStdString()); std::string did = generateKeyAndGetDid(keysDir, "metakey"); LOGOS_ASSERT_FALSE(did.empty()); impl.addTrustedKey("meta-publisher", did, "Test Name", "https://test.com"); LogosList keys = impl.listTrustedKeys(); LOGOS_ASSERT_EQ(keys.size(), static_cast(1)); LogosMap key = keys[0]; LOGOS_ASSERT_EQ(key["name"].get(), std::string("meta-publisher")); LOGOS_ASSERT_EQ(key["did"].get(), did); LOGOS_ASSERT_EQ(key["displayName"].get(), std::string("Test Name")); LOGOS_ASSERT_EQ(key["url"].get(), std::string("https://test.com")); LOGOS_ASSERT_FALSE(key["addedAt"].get().empty()); } // ============================================================================= // Add + verify round-trip // ============================================================================= LOGOS_TEST(keyring_add_then_verify_trusted) { PackageManagerImpl impl; QTemporaryDir tmpDir; LOGOS_ASSERT_TRUE(tmpDir.isValid()); QString keysDir = tmpDir.path() + "/keys"; QString keyringDir = tmpDir.path() + "/keyring"; QDir().mkpath(keysDir); QDir().mkpath(keyringDir); impl.setKeyringDirectory(keyringDir.toStdString()); // Create and sign a package QString lgxPath = tmpDir.path() + "/rt_test.lgx"; QString contentDir = tmpDir.path() + "/rt_content"; QDir().mkpath(contentDir); #if defined(__APPLE__) QString libName = "rt_test_plugin.dylib"; #else QString libName = "rt_test_plugin.so"; #endif { QFile f(contentDir + "/" + libName); f.open(QIODevice::WriteOnly); f.write("fake"); } lgx_create(lgxPath.toStdString().c_str(), "rt_test"); lgx_package_t pkg = lgx_load(lgxPath.toStdString().c_str()); lgx_set_version(pkg, "1.0.0"); std::string variant = [] { auto v = PackageManagerLib::platformVariantsToTry(); return v.empty() ? std::string("unknown") : v.front(); }(); lgx_add_variant(pkg, variant.c_str(), contentDir.toStdString().c_str(), libName.toStdString().c_str()); lgx_save(pkg, lgxPath.toStdString().c_str()); lgx_free_package(pkg); // Generate key and sign QString keyPath = keysDir + "/rtkey.jwk"; lgx_keygen("rtkey", keysDir.toStdString().c_str()); lgx_sign(lgxPath.toStdString().c_str(), keyPath.toStdString().c_str(), nullptr, nullptr); // Verify: not yet trusted LogosMap r1 = impl.verifyPackage(lgxPath.toStdString()); LOGOS_ASSERT_TRUE(r1["isSigned"].get()); LOGOS_ASSERT_TRUE(r1["signatureValid"].get()); LOGOS_ASSERT_TRUE(r1["trustedAs"].get().empty()); // Trust the key std::string did = readDid(keysDir, "rtkey"); impl.addTrustedKey("rt-publisher", did, "", ""); // Verify: now trusted LogosMap r2 = impl.verifyPackage(lgxPath.toStdString()); LOGOS_ASSERT_TRUE(r2["isSigned"].get()); LOGOS_ASSERT_EQ(r2["trustedAs"].get(), std::string("rt-publisher")); }