Implement secure key via KDF for transparent data encryption/decryption #60

This commit is contained in:
2025-08-31 13:49:38 -05:00
parent e542aa64ad
commit 9442d4f6ee
3 changed files with 40 additions and 72 deletions

View File

@@ -183,10 +183,11 @@ void rdb_file_db::enumerate_item_list(
auto iter = create_iterator(directory_family_);
for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid();
iter->Next()) {
auto json_data = nlohmann::json::parse(iter->value().ToString());
list.emplace_back(i_file_db::file_info{
iter->key().ToString(),
true,
iter->value().ToString(),
json_data.at("source_path").get<std::string>(),
});
if (list.size() < 100U) {
@@ -259,7 +260,8 @@ auto rdb_file_db::get_directory_data(const std::string &api_path,
return res;
});
return result;
return result == api_error::item_not_found ? api_error::directory_not_found
: result;
}
auto rdb_file_db::get_directory_source_path(const std::string &api_path,
@@ -360,10 +362,11 @@ auto rdb_file_db::get_item_list(stop_type_callback stop_requested_cb) const
auto iter = create_iterator(directory_family_);
for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid();
iter->Next()) {
auto json_data = json::parse(iter->value().ToString());
ret.emplace_back(i_file_db::file_info{
iter->key().ToString(),
true,
iter->value().ToString(),
json_data.at("source_path").get<std::string>(),
});
}
}

View File

@@ -72,6 +72,7 @@ auto sqlite_file_db::add_or_update_directory(
auto result =
utils::db::sqlite::db_insert{*db_, file_table}
.or_replace()
.column_value("api_path", data.api_path)
.column_value("directory", 1)
.column_value("kdf_configs", nlohmann::json(data.kdf_configs).dump())
@@ -237,8 +238,9 @@ auto sqlite_file_db::get_directory_data(const std::string &api_path,
return api_error::success;
}
return api_error::item_not_found;
return api_error::directory_not_found;
}
auto sqlite_file_db::get_directory_source_path(const std::string &api_path,
std::string &source_path) const
-> api_error {

View File

@@ -125,8 +125,8 @@ auto encrypt_provider::do_fs_operation(
const auto &cfg{get_encrypt_config()};
std::string source_path{api_path};
if (api_path != "/" && not utils::encryption::decrypt_file_path(
cfg.encryption_token, source_path)) {
if (api_path != "/" &&
not utils::encryption::decrypt_file_path(master_key_, source_path)) {
return directory ? api_error::directory_not_found
: api_error::item_not_found;
}
@@ -658,30 +658,25 @@ auto encrypt_provider::process_directory_entry(
try {
const auto do_add_directory =
[this, &cfg](std::string_view dir_path) -> std::string {
auto encrypted_parts{
auto path_parts{
utils::string::split(utils::path::create_api_path(dir_path), '/',
false),
};
auto current_source_path{cfg.path};
std::string current_api_path;
for (std::size_t part_idx = 1U; part_idx < encrypted_parts.size();
for (std::size_t part_idx = 1U; part_idx < path_parts.size();
++part_idx) {
current_source_path = utils::path::combine(
current_source_path, {encrypted_parts.at(part_idx)});
current_source_path = utils::path::combine(current_source_path,
{path_parts.at(part_idx)});
i_file_db::directory_data dir_data{};
std::string dir_api_path;
auto res =
file_db_->get_directory_api_path(current_source_path, dir_api_path);
if (res == api_error::success) {
res = file_db_->get_directory_data(dir_api_path, dir_data);
if (res != api_error::success) {
throw std::runtime_error(
fmt::format("failed to get directory file data|{}",
api_error_to_string(res)));
}
current_api_path = dir_api_path;
} else if (res == api_error::directory_not_found) {
i_file_db::directory_data dir_data{};
dir_data.kdf_configs.first = dir_data.kdf_configs.second =
cfg.kdf_cfg;
dir_data.kdf_configs.first.unique_id =
@@ -690,10 +685,6 @@ auto encrypt_provider::process_directory_entry(
utils::generate_secure_random<std::uint64_t>();
dir_data.kdf_configs.first.seal();
dir_data.kdf_configs.second.seal();
} else {
throw std::runtime_error(fmt::format(
"failed to get directory api path|{}", api_error_to_string(res)));
}
auto path_key = dir_data.kdf_configs.second.recreate_subkey(
utils::encryption::kdf_context::path, master_key_);
@@ -701,19 +692,18 @@ auto encrypt_provider::process_directory_entry(
utils::encryption::encrypt_data(
path_key,
reinterpret_cast<const unsigned char *>(
encrypted_parts.at(part_idx).c_str()),
strnlen(encrypted_parts.at(part_idx).c_str(),
encrypted_parts.at(part_idx).size()),
path_parts.at(part_idx).c_str()),
strnlen(path_parts.at(part_idx).c_str(),
path_parts.at(part_idx).size()),
encrypted_data);
auto hdr = dir_data.kdf_configs.second.to_header();
encrypted_data.insert(encrypted_data.begin(), hdr.begin(), hdr.end());
encrypted_parts[part_idx] = macaron::Base64::EncodeUrlSafe(
encrypted_data.data(), encrypted_data.size());
if (dir_api_path.empty()) {
current_api_path = utils::path::create_api_path(
current_api_path + '/' + encrypted_parts.at(part_idx));
current_api_path + '/' +
macaron::Base64::EncodeUrlSafe(encrypted_data.data(),
encrypted_data.size()));
dir_data.api_path = current_api_path;
dir_data.source_path = current_source_path;
res = file_db_->add_or_update_directory(dir_data);
@@ -724,46 +714,15 @@ auto encrypt_provider::process_directory_entry(
}
event_system::instance().raise<filesystem_item_added>(
utils::path::get_parent_api_path(dir_api_path), dir_api_path,
true, function_name);
}
}
std::size_t current_idx{1U};
std::string current_encrypted_path{};
current_source_path = cfg.path;
for (const auto &part : utils::path::get_parts(dir_path)) {
current_source_path = utils::path::combine(current_source_path, {part});
auto dir_api_path = utils::path::create_api_path(
current_encrypted_path + '/' + encrypted_parts.at(current_idx));
i_file_db::directory_data dir_data;
auto res = file_db_->get_directory_data(dir_api_path, dir_data);
if (res == api_error::directory_not_found) {
dir_data.source_path = current_api_path;
res = file_db_->add_or_update_directory(dir_data);
if (res != api_error::success) {
throw std::runtime_error(
fmt::format("failed to get directory api path|{}",
api_error_to_string(res)));
}
event_system::instance().raise<filesystem_item_added>(
utils::path::get_parent_api_path(dir_api_path), dir_api_path,
true, function_name);
} else if (res == api_error::success) {
encrypted_parts[current_idx] =
utils::string::split(dir_api_path, '/', false)[current_idx];
utils::path::get_parent_api_path(current_api_path),
current_api_path, true, function_name);
} else {
throw std::runtime_error(fmt::format(
"failed to get directory api path|{}", api_error_to_string(res)));
}
current_encrypted_path = utils::path::create_api_path(
current_encrypted_path + '/' + encrypted_parts.at(current_idx++));
}
return current_encrypted_path;
return current_api_path;
};
if (dir_entry.is_directory_item()) {
@@ -1042,7 +1001,11 @@ auto encrypt_provider::start(api_item_added_callback /*api_item_added*/,
} else {
i_file_db::directory_data dir_data{
.api_path = "/",
.kdf_configs = {},
.kdf_configs =
{
get_encrypt_config().kdf_cfg,
get_encrypt_config().kdf_cfg,
},
.source_path = cfg_path,
};
res = file_db_->add_or_update_directory(dir_data);