Implement secure key via KDF for transparent data encryption/decryption #60
This commit is contained in:
@@ -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>(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user