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_);
|
auto iter = create_iterator(directory_family_);
|
||||||
for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid();
|
for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid();
|
||||||
iter->Next()) {
|
iter->Next()) {
|
||||||
|
auto json_data = nlohmann::json::parse(iter->value().ToString());
|
||||||
list.emplace_back(i_file_db::file_info{
|
list.emplace_back(i_file_db::file_info{
|
||||||
iter->key().ToString(),
|
iter->key().ToString(),
|
||||||
true,
|
true,
|
||||||
iter->value().ToString(),
|
json_data.at("source_path").get<std::string>(),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (list.size() < 100U) {
|
if (list.size() < 100U) {
|
||||||
@@ -259,7 +260,8 @@ auto rdb_file_db::get_directory_data(const std::string &api_path,
|
|||||||
return res;
|
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,
|
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_);
|
auto iter = create_iterator(directory_family_);
|
||||||
for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid();
|
for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid();
|
||||||
iter->Next()) {
|
iter->Next()) {
|
||||||
|
auto json_data = json::parse(iter->value().ToString());
|
||||||
ret.emplace_back(i_file_db::file_info{
|
ret.emplace_back(i_file_db::file_info{
|
||||||
iter->key().ToString(),
|
iter->key().ToString(),
|
||||||
true,
|
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 =
|
auto result =
|
||||||
utils::db::sqlite::db_insert{*db_, file_table}
|
utils::db::sqlite::db_insert{*db_, file_table}
|
||||||
|
.or_replace()
|
||||||
.column_value("api_path", data.api_path)
|
.column_value("api_path", data.api_path)
|
||||||
.column_value("directory", 1)
|
.column_value("directory", 1)
|
||||||
.column_value("kdf_configs", nlohmann::json(data.kdf_configs).dump())
|
.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::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,
|
auto sqlite_file_db::get_directory_source_path(const std::string &api_path,
|
||||||
std::string &source_path) const
|
std::string &source_path) const
|
||||||
-> api_error {
|
-> api_error {
|
||||||
|
@@ -125,8 +125,8 @@ auto encrypt_provider::do_fs_operation(
|
|||||||
const auto &cfg{get_encrypt_config()};
|
const auto &cfg{get_encrypt_config()};
|
||||||
|
|
||||||
std::string source_path{api_path};
|
std::string source_path{api_path};
|
||||||
if (api_path != "/" && not utils::encryption::decrypt_file_path(
|
if (api_path != "/" &&
|
||||||
cfg.encryption_token, source_path)) {
|
not utils::encryption::decrypt_file_path(master_key_, source_path)) {
|
||||||
return directory ? api_error::directory_not_found
|
return directory ? api_error::directory_not_found
|
||||||
: api_error::item_not_found;
|
: api_error::item_not_found;
|
||||||
}
|
}
|
||||||
@@ -658,30 +658,25 @@ auto encrypt_provider::process_directory_entry(
|
|||||||
try {
|
try {
|
||||||
const auto do_add_directory =
|
const auto do_add_directory =
|
||||||
[this, &cfg](std::string_view dir_path) -> std::string {
|
[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), '/',
|
utils::string::split(utils::path::create_api_path(dir_path), '/',
|
||||||
false),
|
false),
|
||||||
};
|
};
|
||||||
|
|
||||||
auto current_source_path{cfg.path};
|
auto current_source_path{cfg.path};
|
||||||
std::string current_api_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) {
|
++part_idx) {
|
||||||
current_source_path = utils::path::combine(
|
current_source_path = utils::path::combine(current_source_path,
|
||||||
current_source_path, {encrypted_parts.at(part_idx)});
|
{path_parts.at(part_idx)});
|
||||||
|
|
||||||
i_file_db::directory_data dir_data{};
|
|
||||||
std::string dir_api_path;
|
std::string dir_api_path;
|
||||||
auto res =
|
auto res =
|
||||||
file_db_->get_directory_api_path(current_source_path, dir_api_path);
|
file_db_->get_directory_api_path(current_source_path, dir_api_path);
|
||||||
if (res == api_error::success) {
|
if (res == api_error::success) {
|
||||||
res = file_db_->get_directory_data(dir_api_path, dir_data);
|
current_api_path = dir_api_path;
|
||||||
if (res != api_error::success) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
fmt::format("failed to get directory file data|{}",
|
|
||||||
api_error_to_string(res)));
|
|
||||||
}
|
|
||||||
} else if (res == api_error::directory_not_found) {
|
} 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 =
|
dir_data.kdf_configs.first = dir_data.kdf_configs.second =
|
||||||
cfg.kdf_cfg;
|
cfg.kdf_cfg;
|
||||||
dir_data.kdf_configs.first.unique_id =
|
dir_data.kdf_configs.first.unique_id =
|
||||||
@@ -690,30 +685,25 @@ auto encrypt_provider::process_directory_entry(
|
|||||||
utils::generate_secure_random<std::uint64_t>();
|
utils::generate_secure_random<std::uint64_t>();
|
||||||
dir_data.kdf_configs.first.seal();
|
dir_data.kdf_configs.first.seal();
|
||||||
dir_data.kdf_configs.second.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(
|
auto path_key = dir_data.kdf_configs.second.recreate_subkey(
|
||||||
utils::encryption::kdf_context::path, master_key_);
|
utils::encryption::kdf_context::path, master_key_);
|
||||||
data_buffer encrypted_data;
|
data_buffer encrypted_data;
|
||||||
utils::encryption::encrypt_data(
|
utils::encryption::encrypt_data(
|
||||||
path_key,
|
path_key,
|
||||||
reinterpret_cast<const unsigned char *>(
|
reinterpret_cast<const unsigned char *>(
|
||||||
encrypted_parts.at(part_idx).c_str()),
|
path_parts.at(part_idx).c_str()),
|
||||||
strnlen(encrypted_parts.at(part_idx).c_str(),
|
strnlen(path_parts.at(part_idx).c_str(),
|
||||||
encrypted_parts.at(part_idx).size()),
|
path_parts.at(part_idx).size()),
|
||||||
encrypted_data);
|
encrypted_data);
|
||||||
|
|
||||||
auto hdr = dir_data.kdf_configs.second.to_header();
|
auto hdr = dir_data.kdf_configs.second.to_header();
|
||||||
encrypted_data.insert(encrypted_data.begin(), hdr.begin(), hdr.end());
|
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 = 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.api_path = current_api_path;
|
||||||
dir_data.source_path = current_source_path;
|
dir_data.source_path = current_source_path;
|
||||||
res = file_db_->add_or_update_directory(dir_data);
|
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>(
|
event_system::instance().raise<filesystem_item_added>(
|
||||||
utils::path::get_parent_api_path(dir_api_path), dir_api_path,
|
utils::path::get_parent_api_path(current_api_path),
|
||||||
true, function_name);
|
current_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];
|
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error(fmt::format(
|
throw std::runtime_error(fmt::format(
|
||||||
"failed to get directory api path|{}", api_error_to_string(res)));
|
"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()) {
|
if (dir_entry.is_directory_item()) {
|
||||||
@@ -1042,7 +1001,11 @@ auto encrypt_provider::start(api_item_added_callback /*api_item_added*/,
|
|||||||
} else {
|
} else {
|
||||||
i_file_db::directory_data dir_data{
|
i_file_db::directory_data dir_data{
|
||||||
.api_path = "/",
|
.api_path = "/",
|
||||||
.kdf_configs = {},
|
.kdf_configs =
|
||||||
|
{
|
||||||
|
get_encrypt_config().kdf_cfg,
|
||||||
|
get_encrypt_config().kdf_cfg,
|
||||||
|
},
|
||||||
.source_path = cfg_path,
|
.source_path = cfg_path,
|
||||||
};
|
};
|
||||||
res = file_db_->add_or_update_directory(dir_data);
|
res = file_db_->add_or_update_directory(dir_data);
|
||||||
|
Reference in New Issue
Block a user