diff --git a/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp b/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp index 990bfcd5..18fe0e7c 100644 --- a/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp +++ b/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp @@ -740,9 +740,13 @@ auto encrypt_provider::process_directory_entry( utils::path::get_relative_path(dir_entry.get_path(), cfg.path), }; - i_file_db::file_data file_data{}; - auto file_res{file_db_->get_file_data(api_path, file_data)}; - if (file_res != api_error::success) { + auto file_res{ + file_db_->get_file_api_path(dir_entry.get_path(), api_path)}; + if (file_res == api_error::success) { + return true; + } + + if (file_res != api_error::item_not_found) { // TODO raise error return false; } @@ -763,38 +767,34 @@ auto encrypt_provider::process_directory_entry( do_add_directory(utils::path::get_parent_path(relative_path)); } - if (file_res == api_error::item_not_found) { - utils::encryption::encrypting_reader reader( - utils::path::strip_to_file_name(relative_path), - dir_entry.get_path(), - []() -> bool { return app_config::get_stop_requested(); }, - master_key_, file_data.kdf_configs, - utils::path::get_parent_path(relative_path)); - api_path = utils::path::create_api_path( - api_parent + "/" + reader.get_encrypted_file_name()); + utils::encryption::encrypting_reader reader( + utils::path::strip_to_file_name(relative_path), dir_entry.get_path(), + []() -> bool { return app_config::get_stop_requested(); }, + master_key_, get_encrypt_config().kdf_cfg, std::nullopt); + api_path = utils::path::create_api_path(api_parent + "/" + + reader.get_encrypted_file_name()); - file_res = file_db_->add_or_update_file(i_file_db::file_data{ - .api_path = api_path, - .file_size = dynamic_cast(&dir_entry) - ->size() - .value_or(0U), - .iv_list = reader.get_iv_list(), - .kdf_configs = - { - *reader.get_kdf_config_for_data(), - *reader.get_kdf_config_for_path(), - }, - .source_path = dir_entry.get_path(), - }); - if (file_res != api_error::success) { - // TODO raise error - return false; - } - - event_system::instance().raise( - api_parent, api_path, false, function_name); + file_res = file_db_->add_or_update_file(i_file_db::file_data{ + .api_path = api_path, + .file_size = dynamic_cast(&dir_entry) + ->size() + .value_or(0U), + .iv_list = reader.get_iv_list(), + .kdf_configs = + { + *reader.get_kdf_config_for_data(), + *reader.get_kdf_config_for_path(), + }, + .source_path = dir_entry.get_path(), + }); + if (file_res != api_error::success) { + // TODO raise error + return false; } + event_system::instance().raise( + api_parent, api_path, false, function_name); + return true; } } catch (const std::exception &ex) { @@ -966,12 +966,25 @@ auto encrypt_provider::start(api_item_added_callback /*api_item_added*/, if (encrypt_config_.kdf_cfg.checksum == 0U) { i_file_db::directory_data data{}; if (file_db_->get_directory_data("/", data) == api_error::success) { - encrypt_config_.kdf_cfg = data.kdf_configs.first; + if (data.kdf_configs.first.checksum == 0U) { + encrypt_config_.kdf_cfg.seal(); + } else { + encrypt_config_.kdf_cfg = data.kdf_configs.first; + } } else { encrypt_config_.kdf_cfg.seal(); } config_.set_encrypt_config(encrypt_config_); + data.kdf_configs = { + encrypt_config_.kdf_cfg, + encrypt_config_.kdf_cfg, + }; + auto res = file_db_->add_or_update_directory(data); + if (res != api_error::success) { + throw startup_exception(fmt::format("failed to update existing kdf|{}", + api_error_to_string(res))); + } } if (encrypt_config_.kdf_cfg.checksum != diff --git a/repertory/repertory_test/src/providers_test.cpp b/repertory/repertory_test/src/providers_test.cpp index 98241927..7c516e12 100644 --- a/repertory/repertory_test/src/providers_test.cpp +++ b/repertory/repertory_test/src/providers_test.cpp @@ -158,14 +158,17 @@ const auto create_file = [](repertory::i_provider &provider, const auto decrypt_parts = [](const repertory::app_config &cfg, std::string &path) { if (path != "/" && path != "." && path != "..") { + repertory::utils::hash::hash_256_t key{}; + EXPECT_TRUE(repertory::utils::encryption::recreate_key_argon2id( + cfg.get_encrypt_config().encryption_token, + cfg.get_encrypt_config().kdf_cfg, key)); auto parts = repertory::utils::string::split(path, '/', false); for (auto &part : parts) { if (part.empty()) { continue; } - EXPECT_EQ(true, repertory::utils::encryption::decrypt_file_name( - cfg.get_encrypt_config().encryption_token, part)); + EXPECT_TRUE(repertory::utils::encryption::decrypt_file_name(key, part)); } path = repertory::utils::string::join(parts, '/'); } @@ -492,9 +495,9 @@ static void get_directory_items(const app_config &cfg, i_provider &provider) { EXPECT_STREQ("/test.txt", file->api_path.c_str()); EXPECT_STREQ("/", file->api_parent.c_str()); #if defined(_WIN32) - EXPECT_EQ(std::size_t(47U), file->size); + EXPECT_EQ(std::size_t(83U), file->size); #else - EXPECT_EQ(std::size_t(46U), file->size); + EXPECT_EQ(std::size_t(82U), file->size); #endif auto source_path = @@ -522,9 +525,9 @@ static void get_directory_items(const app_config &cfg, i_provider &provider) { EXPECT_STREQ("/sub10/moose.txt", file2->api_path.c_str()); EXPECT_STREQ("/sub10", file2->api_parent.c_str()); #if defined(_WIN32) - EXPECT_EQ(std::size_t(46U), file2->size); + EXPECT_EQ(std::size_t(82U), file2->size); #else - EXPECT_EQ(std::size_t(45U), file2->size); + EXPECT_EQ(std::size_t(81U), file2->size); #endif return; } @@ -633,9 +636,9 @@ static void get_file(const app_config &cfg, i_provider &provider) { EXPECT_STREQ("/test.txt", file.api_path.c_str()); EXPECT_STREQ("/", file.api_parent.c_str()); #if defined(_WIN32) - EXPECT_EQ(std::size_t(47U), file.file_size); + EXPECT_EQ(std::size_t(83U), file.file_size); #else - EXPECT_EQ(std::size_t(46U), file.file_size); + EXPECT_EQ(std::size_t(82U), file.file_size); #endif EXPECT_STREQ(source_path.c_str(), file.source_path.c_str()); return; diff --git a/support/src/utils/encrypting_reader.cpp b/support/src/utils/encrypting_reader.cpp index e2021063..26d1e0d3 100644 --- a/support/src/utils/encrypting_reader.cpp +++ b/support/src/utils/encrypting_reader.cpp @@ -281,6 +281,11 @@ encrypting_reader::encrypting_reader( error_return_(error_return), source_file_(utils::file::file::open_or_create_file(source_path, true)) { common_initialize_kdf_data(cfg, master_key); + auto [path_key, path_cfg] = cfg.create_subkey( + kdf_context::path, utils::generate_secure_random(), + master_key); + keys_.second = std::move(path_key); + kdf_headers_->second = path_cfg.to_header(); common_initialize(true); create_encrypted_paths(file_name, relative_parent_path); } diff --git a/support/src/utils/encryption.cpp b/support/src/utils/encryption.cpp index c3f65a90..33f0a91e 100644 --- a/support/src/utils/encryption.cpp +++ b/support/src/utils/encryption.cpp @@ -25,6 +25,7 @@ #include "utils/base64.hpp" #include "utils/collection.hpp" +#include "utils/config.hpp" #include "utils/encrypting_reader.hpp" #include "utils/hash.hpp" #include "utils/path.hpp" @@ -99,29 +100,49 @@ auto decrypt_file_name(std::string_view encryption_token, auto decrypt_file_name(std::string_view encryption_token, const kdf_config &cfg, std::string &file_name) -> bool { - auto buffer = macaron::Base64::Decode(file_name); + REPERTORY_USES_FUNCTION_NAME(); - file_name.clear(); - return utils::encryption::decrypt_data(encryption_token, cfg, buffer, - file_name); + try { + auto buffer = macaron::Base64::Decode(file_name); + + file_name.clear(); + return utils::encryption::decrypt_data(encryption_token, cfg, buffer, + file_name); + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } catch (...) { + utils::error::handle_exception(function_name); + } + + return false; } auto decrypt_file_name(const utils::hash::hash_256_t &master_key, std::string &file_name) -> bool { - auto buffer = macaron::Base64::Decode(file_name); + REPERTORY_USES_FUNCTION_NAME(); - utils::encryption::kdf_config path_cfg; - if (not utils::encryption::kdf_config::from_header(buffer, path_cfg)) { - return false; + try { + auto buffer = macaron::Base64::Decode(file_name); + + utils::encryption::kdf_config path_cfg; + if (not utils::encryption::kdf_config::from_header(buffer, path_cfg)) { + return false; + } + + auto path_key = path_cfg.recreate_subkey( + utils::encryption::kdf_context::path, master_key); + + file_name.clear(); + return utils::encryption::decrypt_data( + path_key, &buffer[utils::encryption::kdf_config::size()], + buffer.size() - utils::encryption::kdf_config::size(), file_name); + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } catch (...) { + utils::error::handle_exception(function_name); } - auto path_key = path_cfg.recreate_subkey(utils::encryption::kdf_context::path, - master_key); - - file_name.clear(); - return utils::encryption::decrypt_data( - path_key, &buffer[utils::encryption::kdf_config::size()], - buffer.size() - utils::encryption::kdf_config::size(), file_name); + return false; } auto decrypt_file_path(std::string_view encryption_token, diff --git a/support/src/utils/file_file.cpp b/support/src/utils/file_file.cpp index 9fa9d408..f550a1ab 100644 --- a/support/src/utils/file_file.cpp +++ b/support/src/utils/file_file.cpp @@ -266,7 +266,7 @@ auto file::move_to(std::string_view path) -> bool { #if defined(_WIN32) success = ::MoveFileExA(path_.c_str(), abs_path.c_str(), MOVEFILE_REPLACE_EXISTING) != 0; -#else // !// defined(_WIN32) +#else // !defined(_WIN32) std::error_code ec{}; std::filesystem::rename(path_, abs_path, ec); success = ec.value() == 0;