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,30 +685,25 @@ 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_); | ||||
|         data_buffer encrypted_data; | ||||
|         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()), | ||||
|             encrypted_data); | ||||
|           auto path_key = dir_data.kdf_configs.second.recreate_subkey( | ||||
|               utils::encryption::kdf_context::path, master_key_); | ||||
|           data_buffer encrypted_data; | ||||
|           utils::encryption::encrypt_data( | ||||
|               path_key, | ||||
|               reinterpret_cast<const unsigned char *>( | ||||
|                   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()); | ||||
|           auto hdr = dir_data.kdf_configs.second.to_header(); | ||||
|           encrypted_data.insert(encrypted_data.begin(), hdr.begin(), hdr.end()); | ||||
|  | ||||
|         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