updated build system
This commit is contained in:
		| @@ -25,6 +25,7 @@ | ||||
|  | ||||
| #include "utils/collection.hpp" | ||||
| #include "utils/common.hpp" | ||||
| #include "utils/config.hpp" | ||||
| #include "utils/encryption.hpp" | ||||
| #include "utils/error.hpp" | ||||
| #include "utils/file.hpp" | ||||
| @@ -119,7 +120,7 @@ protected: | ||||
|     reader_.set_read_position(reinterpret_cast<std::uintptr_t>(gptr())); | ||||
|  | ||||
|     char c{}; | ||||
|     const auto res = encrypting_reader::reader_function(&c, 1U, 1U, &reader_); | ||||
|     auto res = encrypting_reader::reader_function(&c, 1U, 1U, &reader_); | ||||
|     if (res != 1) { | ||||
|       return traits_type::eof(); | ||||
|     } | ||||
| @@ -180,60 +181,12 @@ encrypting_reader::encrypting_reader( | ||||
|     std::string_view file_name, std::string_view source_path, | ||||
|     stop_type_callback stop_requested_cb, std::string_view token, | ||||
|     std::optional<std::string> relative_parent_path, std::size_t error_return) | ||||
|     : key_(utils::encryption::generate_key<utils::encryption::hash_256_t>( | ||||
|           token)), | ||||
|     : key_(utils::encryption::generate_key<utils::hash::hash_256_t>(token)), | ||||
|       stop_requested_cb_(std::move(stop_requested_cb)), | ||||
|       error_return_(error_return), | ||||
|       source_file_(utils::file::file::open_or_create_file(source_path, true)) { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   if (not*source_file_) { | ||||
|     throw utils::error::create_exception(function_name, { | ||||
|                                                             "file open failed", | ||||
|                                                             source_path, | ||||
|                                                         }); | ||||
|   } | ||||
|  | ||||
|   data_buffer result; | ||||
|   utils::encryption::encrypt_data( | ||||
|       key_, reinterpret_cast<const unsigned char *>(file_name.data()), | ||||
|       file_name.size(), result); | ||||
|   encrypted_file_name_ = utils::collection::to_hex_string(result); | ||||
|  | ||||
|   if (relative_parent_path.has_value()) { | ||||
|     for (auto &&part : | ||||
|          utils::string::split(relative_parent_path.value(), | ||||
|                               utils::path::directory_seperator, false)) { | ||||
|       utils::encryption::encrypt_data( | ||||
|           key_, reinterpret_cast<const unsigned char *>(part.c_str()), | ||||
|           strnlen(part.c_str(), part.size()), result); | ||||
|       encrypted_file_path_ += '/' + utils::collection::to_hex_string(result); | ||||
|     } | ||||
|     encrypted_file_path_ += '/' + encrypted_file_name_; | ||||
|   } | ||||
|  | ||||
|   auto opt_size = source_file_->size(); | ||||
|   if (not opt_size.has_value()) { | ||||
|     throw utils::error::create_exception(function_name, | ||||
|                                          { | ||||
|                                              "failed to get file size", | ||||
|                                              source_file_->get_path(), | ||||
|                                          }); | ||||
|   } | ||||
|   auto file_size = opt_size.value(); | ||||
|  | ||||
|   const auto total_chunks = utils::divide_with_ceiling( | ||||
|       file_size, static_cast<std::uint64_t>(data_chunk_size_)); | ||||
|   total_size_ = file_size + (total_chunks * encryption_header_size); | ||||
|   last_data_chunk_ = total_chunks - 1U; | ||||
|   last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size | ||||
|                           : (file_size % data_chunk_size_) == 0U | ||||
|                               ? data_chunk_size_ | ||||
|                               : file_size % data_chunk_size_; | ||||
|   iv_list_.resize(total_chunks); | ||||
|   for (auto &iv : iv_list_) { | ||||
|     randombytes_buf(iv.data(), iv.size()); | ||||
|   } | ||||
|   common_initialize(true); | ||||
|   create_encrypted_paths(file_name, relative_parent_path); | ||||
| } | ||||
|  | ||||
| encrypting_reader::encrypting_reader(std::string_view encrypted_file_path, | ||||
| @@ -241,45 +194,14 @@ encrypting_reader::encrypting_reader(std::string_view encrypted_file_path, | ||||
|                                      stop_type_callback stop_requested_cb, | ||||
|                                      std::string_view token, | ||||
|                                      std::size_t error_return) | ||||
|     : key_(utils::encryption::generate_key<utils::encryption::hash_256_t>( | ||||
|           token)), | ||||
|     : key_(utils::encryption::generate_key<utils::hash::hash_256_t>(token)), | ||||
|       stop_requested_cb_(std::move(stop_requested_cb)), | ||||
|       error_return_(error_return), | ||||
|       source_file_(utils::file::file::open_or_create_file(source_path, true)) { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   if (not*source_file_) { | ||||
|     throw utils::error::create_exception(function_name, { | ||||
|                                                             "file open failed", | ||||
|                                                             source_path, | ||||
|                                                         }); | ||||
|   } | ||||
|  | ||||
|   encrypted_file_path_ = encrypted_file_path; | ||||
|   encrypted_file_name_ = utils::path::strip_to_file_name(encrypted_file_path_); | ||||
|  | ||||
|   auto opt_size = source_file_->size(); | ||||
|   if (not opt_size.has_value()) { | ||||
|     throw utils::error::create_exception(function_name, | ||||
|                                          { | ||||
|                                              "failed to get file size", | ||||
|                                              source_file_->get_path(), | ||||
|                                          }); | ||||
|   } | ||||
|   auto file_size = opt_size.value(); | ||||
|  | ||||
|   const auto total_chunks = utils::divide_with_ceiling( | ||||
|       file_size, static_cast<std::uint64_t>(data_chunk_size_)); | ||||
|   total_size_ = file_size + (total_chunks * encryption_header_size); | ||||
|   last_data_chunk_ = total_chunks - 1U; | ||||
|   last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size | ||||
|                           : (file_size % data_chunk_size_) == 0U | ||||
|                               ? data_chunk_size_ | ||||
|                               : file_size % data_chunk_size_; | ||||
|   iv_list_.resize(total_chunks); | ||||
|   for (auto &iv : iv_list_) { | ||||
|     randombytes_buf(iv.data(), iv.size()); | ||||
|   } | ||||
|       source_file_(utils::file::file::open_or_create_file(source_path, true)), | ||||
|       encrypted_file_name_( | ||||
|           utils::path::strip_to_file_name(std::string{encrypted_file_path})), | ||||
|       encrypted_file_path_(encrypted_file_path) { | ||||
|   common_initialize(true); | ||||
| } | ||||
|  | ||||
| encrypting_reader::encrypting_reader( | ||||
| @@ -289,43 +211,73 @@ encrypting_reader::encrypting_reader( | ||||
|         std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>> | ||||
|         iv_list, | ||||
|     std::size_t error_return) | ||||
|     : key_(utils::encryption::generate_key<utils::encryption::hash_256_t>( | ||||
|           token)), | ||||
|     : key_(utils::encryption::generate_key<utils::hash::hash_256_t>(token)), | ||||
|       stop_requested_cb_(std::move(stop_requested_cb)), | ||||
|       error_return_(error_return), | ||||
|       source_file_(utils::file::file::open_or_create_file(source_path, true)), | ||||
|       encrypted_file_name_( | ||||
|           utils::path::strip_to_file_name(std::string{encrypted_file_path})), | ||||
|       encrypted_file_path_(encrypted_file_path), | ||||
|       iv_list_(std::move(iv_list)) { | ||||
|   common_initialize(false); | ||||
| } | ||||
|  | ||||
| encrypting_reader::encrypting_reader( | ||||
|     std::string_view file_name, std::string_view source_path, | ||||
|     stop_type_callback stop_requested_cb, std::string_view token, | ||||
|     kdf_config cfg, std::optional<std::string> relative_parent_path, | ||||
|     std::size_t error_return) | ||||
|     : key_( | ||||
|           utils::encryption::generate_key<utils::hash::hash_256_t>(token, cfg)), | ||||
|       stop_requested_cb_(std::move(stop_requested_cb)), | ||||
|       error_return_(error_return), | ||||
|       source_file_(utils::file::file::open_or_create_file(source_path, true)) { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|   kdf_header_ = cfg.to_header(); | ||||
|  | ||||
|   if (not*source_file_) { | ||||
|     throw utils::error::create_exception(function_name, { | ||||
|                                                             "file open failed", | ||||
|                                                             source_path, | ||||
|                                                         }); | ||||
|   } | ||||
|   data_buffer result; | ||||
|   utils::encryption::encrypt_data( | ||||
|       key_, reinterpret_cast<const unsigned char *>(file_name.data()), | ||||
|       file_name.size(), result); | ||||
|   common_initialize(true); | ||||
|   create_encrypted_paths(file_name, relative_parent_path); | ||||
| } | ||||
|  | ||||
|   encrypted_file_path_ = encrypted_file_path; | ||||
|   encrypted_file_name_ = utils::path::strip_to_file_name(encrypted_file_path_); | ||||
| encrypting_reader::encrypting_reader(std::string_view encrypted_file_path, | ||||
|                                      std::string_view source_path, | ||||
|                                      stop_type_callback stop_requested_cb, | ||||
|                                      std::string_view token, kdf_config cfg, | ||||
|                                      std::size_t error_return) | ||||
|     : key_( | ||||
|           utils::encryption::generate_key<utils::hash::hash_256_t>(token, cfg)), | ||||
|       stop_requested_cb_(std::move(stop_requested_cb)), | ||||
|       error_return_(error_return), | ||||
|       source_file_(utils::file::file::open_or_create_file(source_path, true)), | ||||
|       encrypted_file_name_( | ||||
|           utils::path::strip_to_file_name(std::string{encrypted_file_path})), | ||||
|       encrypted_file_path_(encrypted_file_path) { | ||||
|   kdf_header_ = cfg.to_header(); | ||||
|   common_initialize(true); | ||||
| } | ||||
|  | ||||
|   auto opt_size = source_file_->size(); | ||||
|   if (not opt_size.has_value()) { | ||||
|     throw utils::error::create_exception( | ||||
|         function_name, { | ||||
|                            "get file size failed", | ||||
|                            std::to_string(utils::get_last_error_code()), | ||||
|                            source_file_->get_path(), | ||||
|                        }); | ||||
|   } | ||||
|   auto file_size{opt_size.value()}; | ||||
|  | ||||
|   const auto total_chunks = utils::divide_with_ceiling( | ||||
|       file_size, static_cast<std::uint64_t>(data_chunk_size_)); | ||||
|   total_size_ = file_size + (total_chunks * encryption_header_size); | ||||
|   last_data_chunk_ = total_chunks - 1U; | ||||
|   last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size | ||||
|                           : (file_size % data_chunk_size_) == 0U | ||||
|                               ? data_chunk_size_ | ||||
|                               : file_size % data_chunk_size_; | ||||
|   iv_list_ = std::move(iv_list); | ||||
| encrypting_reader::encrypting_reader( | ||||
|     std::string_view encrypted_file_path, std::string_view source_path, | ||||
|     stop_type_callback stop_requested_cb, std::string_view token, | ||||
|     kdf_config cfg, | ||||
|     std::vector< | ||||
|         std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>> | ||||
|         iv_list, | ||||
|     std::size_t error_return) | ||||
|     : key_( | ||||
|           utils::encryption::generate_key<utils::hash::hash_256_t>(token, cfg)), | ||||
|       stop_requested_cb_(std::move(stop_requested_cb)), | ||||
|       error_return_(error_return), | ||||
|       source_file_(utils::file::file::open_or_create_file(source_path, true)), | ||||
|       encrypted_file_name_( | ||||
|           utils::path::strip_to_file_name(std::string{encrypted_file_path})), | ||||
|       encrypted_file_path_(encrypted_file_path), | ||||
|       iv_list_(std::move(iv_list)) { | ||||
|   kdf_header_ = cfg.to_header(); | ||||
|   common_initialize(false); | ||||
| } | ||||
|  | ||||
| encrypting_reader::encrypting_reader(const encrypting_reader &reader) | ||||
| @@ -334,17 +286,18 @@ encrypting_reader::encrypting_reader(const encrypting_reader &reader) | ||||
|       error_return_(reader.error_return_), | ||||
|       source_file_( | ||||
|           utils::file::file::open_file(reader.source_file_->get_path(), true)), | ||||
|       chunk_buffers_(reader.chunk_buffers_), | ||||
|       encrypted_file_name_(reader.encrypted_file_name_), | ||||
|       encrypted_file_path_(reader.encrypted_file_path_), | ||||
|       iv_list_(reader.iv_list_), | ||||
|       chunk_buffers_(reader.chunk_buffers_), | ||||
|       kdf_header_(reader.kdf_header_), | ||||
|       last_data_chunk_(reader.last_data_chunk_), | ||||
|       last_data_chunk_size_(reader.last_data_chunk_size_), | ||||
|       read_offset_(reader.read_offset_), | ||||
|       total_size_(reader.total_size_) { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   if (not*source_file_) { | ||||
|   if (not *source_file_) { | ||||
|     throw utils::error::create_exception( | ||||
|         function_name, { | ||||
|                            "file open failed", | ||||
| @@ -354,15 +307,61 @@ encrypting_reader::encrypting_reader(const encrypting_reader &reader) | ||||
|   } | ||||
| } | ||||
|  | ||||
| auto encrypting_reader::calculate_decrypted_size(std::uint64_t total_size) | ||||
| void encrypting_reader::common_initialize(bool procces_iv_list) { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   if (not *source_file_) { | ||||
|     throw utils::error::create_exception(function_name, | ||||
|                                          { | ||||
|                                              "file open failed", | ||||
|                                              source_file_->get_path(), | ||||
|                                          }); | ||||
|   } | ||||
|  | ||||
|   auto opt_size = source_file_->size(); | ||||
|   if (not opt_size.has_value()) { | ||||
|     throw utils::error::create_exception(function_name, | ||||
|                                          { | ||||
|                                              "failed to get file size", | ||||
|                                              source_file_->get_path(), | ||||
|                                          }); | ||||
|   } | ||||
|   auto file_size = opt_size.value(); | ||||
|  | ||||
|   auto total_chunks = utils::divide_with_ceiling( | ||||
|       file_size, static_cast<std::uint64_t>(data_chunk_size_)); | ||||
|   total_size_ = file_size + (total_chunks * encryption_header_size) + | ||||
|                 (kdf_header_.has_value() ? kdf_header_->size() : 0U); | ||||
|   last_data_chunk_ = total_chunks - 1U; | ||||
|   last_data_chunk_size_ = (file_size <= data_chunk_size_) ? file_size | ||||
|                           : (file_size % data_chunk_size_) == 0U | ||||
|                               ? data_chunk_size_ | ||||
|                               : file_size % data_chunk_size_; | ||||
|   if (not procces_iv_list) { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   iv_list_.resize(total_chunks); | ||||
|   for (auto &data : iv_list_) { | ||||
|     randombytes_buf(data.data(), data.size()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| auto encrypting_reader::calculate_decrypted_size(std::uint64_t total_size, | ||||
|                                                  bool uses_kdf) | ||||
|     -> std::uint64_t { | ||||
|   if (uses_kdf) { | ||||
|     total_size -= kdf_config::size(); | ||||
|   } | ||||
|  | ||||
|   return total_size - (utils::divide_with_ceiling( | ||||
|                            total_size, static_cast<std::uint64_t>( | ||||
|                                            get_encrypted_chunk_size())) * | ||||
|                        encryption_header_size); | ||||
| } | ||||
|  | ||||
| auto encrypting_reader::calculate_encrypted_size(std::string_view source_path) | ||||
| auto encrypting_reader::calculate_encrypted_size(std::string_view source_path, | ||||
|                                                  bool uses_kdf) | ||||
|     -> std::uint64_t { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
| @@ -377,9 +376,43 @@ auto encrypting_reader::calculate_encrypted_size(std::string_view source_path) | ||||
|   } | ||||
|   auto file_size{opt_size.value()}; | ||||
|  | ||||
|   const auto total_chunks = utils::divide_with_ceiling( | ||||
|   auto total_chunks = utils::divide_with_ceiling( | ||||
|       file_size, static_cast<std::uint64_t>(data_chunk_size_)); | ||||
|   return file_size + (total_chunks * encryption_header_size); | ||||
|   return file_size + (total_chunks * encryption_header_size) + | ||||
|          (uses_kdf ? kdf_config::size() : 0U); | ||||
| } | ||||
|  | ||||
| void encrypting_reader::create_encrypted_paths( | ||||
|     std::string_view file_name, | ||||
|     std::optional<std::string> relative_parent_path) { | ||||
|   data_buffer result; | ||||
|   utils::encryption::encrypt_data( | ||||
|       key_, reinterpret_cast<const unsigned char *>(file_name.data()), | ||||
|       file_name.size(), result); | ||||
|   if (kdf_header_.has_value()) { | ||||
|     result.insert(result.begin(), kdf_header_->begin(), kdf_header_->end()); | ||||
|   } | ||||
|  | ||||
|   encrypted_file_name_ = utils::collection::to_hex_string(result); | ||||
|  | ||||
|   if (not relative_parent_path.has_value()) { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   for (const auto &part : | ||||
|        utils::string::split(relative_parent_path.value(), | ||||
|                             utils::path::directory_seperator, false)) { | ||||
|     utils::encryption::encrypt_data( | ||||
|         key_, reinterpret_cast<const unsigned char *>(part.c_str()), | ||||
|         strnlen(part.c_str(), part.size()), result); | ||||
|     if (kdf_header_.has_value()) { | ||||
|       result.insert(result.begin(), kdf_header_->begin(), kdf_header_->end()); | ||||
|     } | ||||
|  | ||||
|     encrypted_file_path_ += '/' + utils::collection::to_hex_string(result); | ||||
|   } | ||||
|  | ||||
|   encrypted_file_path_ += '/' + encrypted_file_name_; | ||||
| } | ||||
|  | ||||
| auto encrypting_reader::create_iostream() const | ||||
| @@ -388,24 +421,73 @@ auto encrypting_reader::create_iostream() const | ||||
|       std::make_unique<encrypting_streambuf>(*this)); | ||||
| } | ||||
|  | ||||
| auto encrypting_reader::get_kdf_config() const -> std::optional<kdf_config> { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   if (not kdf_header_.has_value()) { | ||||
|     return std::nullopt; | ||||
|   } | ||||
|  | ||||
|   kdf_config cfg; | ||||
|   if (not kdf_config::from_header(kdf_header_.value(), cfg)) { | ||||
|     throw utils::error::create_exception(function_name, | ||||
|                                          { | ||||
|                                              "invalid kdf header", | ||||
|                                          }); | ||||
|   } | ||||
|  | ||||
|   return cfg; | ||||
| } | ||||
|  | ||||
| auto encrypting_reader::reader_function(char *buffer, size_t size, | ||||
|                                         size_t nitems) -> size_t { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   const auto read_size = static_cast<std::size_t>(std::min( | ||||
|       static_cast<std::uint64_t>(size * nitems), total_size_ - read_offset_)); | ||||
|   auto read_size = | ||||
|       static_cast<std::uint64_t>(size) * static_cast<std::uint64_t>(nitems); | ||||
|   if (read_size == 0U) { | ||||
|     return 0U; | ||||
|   } | ||||
|  | ||||
|   auto chunk = read_offset_ / encrypted_chunk_size_; | ||||
|   auto chunk_offset = read_offset_ % encrypted_chunk_size_; | ||||
|   auto read_offset{read_offset_}; | ||||
|   std::size_t total_read{}; | ||||
|   auto total_size{total_size_}; | ||||
|  | ||||
|   auto ret = false; | ||||
|   if (read_offset_ < total_size_) { | ||||
|   if (kdf_header_.has_value()) { | ||||
|     total_size -= kdf_header_->size(); | ||||
|  | ||||
|     if (read_offset < kdf_header_->size()) { | ||||
|       auto to_read{ | ||||
|           utils::calculate_read_size(kdf_header_->size(), read_size, | ||||
|                                      read_offset), | ||||
|       }; | ||||
|       read_offset_ += to_read; | ||||
|  | ||||
|       std::memcpy(buffer, &kdf_header_->data()[read_offset], to_read); | ||||
|       if (read_size - to_read == 0) { | ||||
|         return to_read; | ||||
|       } | ||||
|  | ||||
|       read_offset = 0U; | ||||
|       read_size -= to_read; | ||||
|       total_read += to_read; | ||||
|       buffer += to_read; | ||||
|     } else { | ||||
|       read_offset -= kdf_header_->size(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   auto chunk = static_cast<std::size_t>(read_offset / encrypted_chunk_size_); | ||||
|   auto chunk_offset = | ||||
|       static_cast<std::size_t>(read_offset % encrypted_chunk_size_); | ||||
|   auto remain = utils::calculate_read_size(total_size, read_size, read_offset); | ||||
|  | ||||
|   auto ret{false}; | ||||
|   if (read_offset < total_size) { | ||||
|     try { | ||||
|       ret = true; | ||||
|       auto remain = read_size; | ||||
|       while (not get_stop_requested() && ret && (remain != 0U)) { | ||||
|         if (chunk_buffers_.find(chunk) == chunk_buffers_.end()) { | ||||
|         if (not chunk_buffers_.contains(chunk)) { | ||||
|           auto &chunk_buffer = chunk_buffers_[chunk]; | ||||
|           data_buffer file_data(chunk == last_data_chunk_ | ||||
|                                     ? last_data_chunk_size_ | ||||
| @@ -413,24 +495,26 @@ auto encrypting_reader::reader_function(char *buffer, size_t size, | ||||
|           chunk_buffer.resize(file_data.size() + encryption_header_size); | ||||
|  | ||||
|           std::size_t bytes_read{}; | ||||
|           if ((ret = source_file_->read(file_data, chunk * data_chunk_size_, | ||||
|                                         &bytes_read))) { | ||||
|           ret = source_file_->read( | ||||
|               file_data, | ||||
|               static_cast<std::uint64_t>(chunk) * | ||||
|                   static_cast<std::uint64_t>(data_chunk_size_), | ||||
|               &bytes_read); | ||||
|           if (ret) { | ||||
|             utils::encryption::encrypt_data(iv_list_.at(chunk), key_, file_data, | ||||
|                                             chunk_buffer); | ||||
|           } | ||||
|         } else if (chunk) { | ||||
|           chunk_buffers_.erase(chunk - 1u); | ||||
|         } else if (chunk != 0U) { | ||||
|           chunk_buffers_.erase(chunk - 1U); | ||||
|         } | ||||
|  | ||||
|         auto &chunk_buffer = chunk_buffers_[chunk]; | ||||
|         const auto to_read = std::min( | ||||
|             static_cast<std::size_t>(chunk_buffer.size() - chunk_offset), | ||||
|             remain); | ||||
|         auto to_read = std::min(chunk_buffer.size() - chunk_offset, remain); | ||||
|         std::memcpy(buffer + total_read, &chunk_buffer[chunk_offset], to_read); | ||||
|         total_read += to_read; | ||||
|         remain -= to_read; | ||||
|         chunk_offset = 0u; | ||||
|         chunk++; | ||||
|         chunk_offset = 0U; | ||||
|         ++chunk; | ||||
|         read_offset_ += to_read; | ||||
|       } | ||||
|     } catch (const std::exception &e) { | ||||
|   | ||||
| @@ -28,6 +28,53 @@ | ||||
| #include "utils/path.hpp" | ||||
|  | ||||
| namespace repertory::utils::encryption { | ||||
|  | ||||
| auto kdf_config::generate_checksum() const -> std::uint64_t { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   kdf_config tmp = *this; | ||||
|   tmp.checksum = 0; | ||||
|  | ||||
|   auto hdr = tmp.to_header(); | ||||
|  | ||||
|   std::uint64_t ret{0}; | ||||
|   if (crypto_generichash(reinterpret_cast<unsigned char *>(&ret), sizeof(ret), | ||||
|                          hdr.data(), hdr.size(), nullptr, 0) != 0) { | ||||
|     throw utils::error::create_exception(function_name, | ||||
|                                          { | ||||
|                                              "failed to calculate checksum", | ||||
|                                          }); | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| void kdf_config::generate_salt() { | ||||
|   randombytes_buf(salt.data(), salt.size()); | ||||
|   checksum = generate_checksum(); | ||||
| } | ||||
|  | ||||
| auto kdf_config::from_header(std::span<const unsigned char> data, | ||||
|                              kdf_config &cfg) -> bool { | ||||
|   if (data.size() < kdf_config::size()) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   std::memcpy(&cfg, data.data(), kdf_config::size()); | ||||
|   cfg.magic = boost::endian::big_to_native(cfg.magic); | ||||
|   if (cfg.magic != repertory_magic) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   cfg.checksum = boost::endian::big_to_native(cfg.checksum); | ||||
|   return cfg.version == kdf_version::v1 && cfg.kdf == kdf_type::argon2id && | ||||
|          cfg.memlimit >= memlimit_level::level1 && | ||||
|          cfg.memlimit <= memlimit_level::level4 && | ||||
|          cfg.opslimit >= opslimit_level::level1 && | ||||
|          cfg.opslimit <= opslimit_level::level3 && | ||||
|          cfg.checksum == cfg.generate_checksum(); | ||||
| } | ||||
|  | ||||
| auto decrypt_file_path(std::string_view encryption_token, | ||||
|                        std::string &file_path) -> bool { | ||||
|   std::vector<std::string> decrypted_parts; | ||||
| @@ -49,6 +96,27 @@ auto decrypt_file_path(std::string_view encryption_token, | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| auto decrypt_file_path(std::string_view encryption_token, const kdf_config &cfg, | ||||
|                        std::string &file_path) -> bool { | ||||
|   std::vector<std::string> decrypted_parts; | ||||
|   for (const auto &part : std::filesystem::path(file_path)) { | ||||
|     auto file_name = part.string(); | ||||
|     if (file_name == "/") { | ||||
|       continue; | ||||
|     } | ||||
|  | ||||
|     if (not decrypt_file_name(encryption_token, cfg, file_name)) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     decrypted_parts.push_back(file_name); | ||||
|   } | ||||
|  | ||||
|   file_path = | ||||
|       utils::path::create_api_path(utils::string::join(decrypted_parts, '/')); | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| auto decrypt_file_name(std::string_view encryption_token, | ||||
|                        std::string &file_name) -> bool { | ||||
|   data_buffer buffer; | ||||
| @@ -60,10 +128,26 @@ auto decrypt_file_name(std::string_view encryption_token, | ||||
|   return utils::encryption::decrypt_data(encryption_token, buffer, file_name); | ||||
| } | ||||
|  | ||||
| auto decrypt_file_name(std::string_view encryption_token, const kdf_config &cfg, | ||||
|                        std::string &file_name) -> bool { | ||||
|   data_buffer buffer; | ||||
|   if (not utils::collection::from_hex_string(file_name, buffer)) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   file_name.clear(); | ||||
|   return utils::encryption::decrypt_data(encryption_token, cfg, buffer, | ||||
|                                          file_name); | ||||
| } | ||||
|  | ||||
| template <typename data_t> | ||||
| auto read_encrypted_range(const http_range &range, | ||||
|                           const utils::encryption::hash_256_t &key, | ||||
|                           const utils::hash::hash_256_t &key, | ||||
|                           reader_func_t reader_func, std::uint64_t total_size, | ||||
|                           data_buffer &data) -> bool { | ||||
|                           data_t &data, std::uint8_t file_header_size, | ||||
|                           std::size_t &bytes_read) -> bool { | ||||
|   bytes_read = 0U; | ||||
|  | ||||
|   auto encrypted_chunk_size = | ||||
|       utils::encryption::encrypting_reader::get_encrypted_chunk_size(); | ||||
|   auto data_chunk_size = | ||||
| @@ -76,7 +160,7 @@ auto read_encrypted_range(const http_range &range, | ||||
|  | ||||
|   for (std::size_t chunk = start_chunk; chunk <= end_chunk; chunk++) { | ||||
|     data_buffer cypher; | ||||
|     auto start_offset = chunk * encrypted_chunk_size; | ||||
|     auto start_offset = (chunk * encrypted_chunk_size) + file_header_size; | ||||
|     auto end_offset = std::min( | ||||
|         start_offset + (total_size - (chunk * data_chunk_size)) + | ||||
|             encryption_header_size - 1U, | ||||
| @@ -98,58 +182,7 @@ auto read_encrypted_range(const http_range &range, | ||||
|                         static_cast<std::int64_t>(source_offset)), | ||||
|               std::next(source_buffer.begin(), | ||||
|                         static_cast<std::int64_t>(source_offset + data_size)), | ||||
|               std::back_inserter(data)); | ||||
|     remain -= data_size; | ||||
|     source_offset = 0U; | ||||
|   } | ||||
|  | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| auto read_encrypted_range(const http_range &range, | ||||
|                           const utils::encryption::hash_256_t &key, | ||||
|                           reader_func_t reader_func, std::uint64_t total_size, | ||||
|                           unsigned char *data, std::size_t size, | ||||
|                           std::size_t &bytes_read) -> bool { | ||||
|   bytes_read = 0U; | ||||
|  | ||||
|   auto encrypted_chunk_size = | ||||
|       utils::encryption::encrypting_reader::get_encrypted_chunk_size(); | ||||
|   auto data_chunk_size = | ||||
|       utils::encryption::encrypting_reader::get_data_chunk_size(); | ||||
|  | ||||
|   auto start_chunk = static_cast<std::size_t>(range.begin / data_chunk_size); | ||||
|   auto end_chunk = static_cast<std::size_t>(range.end / data_chunk_size); | ||||
|   auto remain = range.end - range.begin + 1U; | ||||
|   auto source_offset = static_cast<std::size_t>(range.begin % data_chunk_size); | ||||
|  | ||||
|   std::span dest_buffer(data, size); | ||||
|   for (std::size_t chunk = start_chunk; chunk <= end_chunk; chunk++) { | ||||
|     data_buffer cypher; | ||||
|     auto start_offset = chunk * encrypted_chunk_size; | ||||
|     auto end_offset = std::min( | ||||
|         start_offset + (total_size - (chunk * data_chunk_size)) + | ||||
|             encryption_header_size - 1U, | ||||
|         static_cast<std::uint64_t>(start_offset + encrypted_chunk_size - 1U)); | ||||
|  | ||||
|     if (not reader_func(cypher, start_offset, end_offset)) { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     data_buffer source_buffer; | ||||
|     if (not utils::encryption::decrypt_data(key, cypher, source_buffer)) { | ||||
|       return false; | ||||
|     } | ||||
|     cypher.clear(); | ||||
|  | ||||
|     auto data_size = static_cast<std::size_t>(std::min( | ||||
|         remain, static_cast<std::uint64_t>(data_chunk_size - source_offset))); | ||||
|     std::copy( | ||||
|         std::next(source_buffer.begin(), | ||||
|                   static_cast<std::int64_t>(source_offset)), | ||||
|         std::next(source_buffer.begin(), | ||||
|                   static_cast<std::int64_t>(source_offset + data_size)), | ||||
|         std::next(dest_buffer.begin(), static_cast<std::int64_t>(bytes_read))); | ||||
|               std::next(data.begin(), static_cast<std::int64_t>(bytes_read))); | ||||
|     remain -= data_size; | ||||
|     bytes_read += data_size; | ||||
|     source_offset = 0U; | ||||
| @@ -157,6 +190,26 @@ auto read_encrypted_range(const http_range &range, | ||||
|  | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| auto read_encrypted_range(const http_range &range, | ||||
|                           const utils::hash::hash_256_t &key, bool uses_kdf, | ||||
|                           reader_func_t reader_func, std::uint64_t total_size, | ||||
|                           data_buffer &data) -> bool { | ||||
|   std::size_t bytes_read{}; | ||||
|   return read_encrypted_range<data_buffer>( | ||||
|       range, key, reader_func, total_size, data, | ||||
|       uses_kdf ? kdf_config::size() : 0U, bytes_read); | ||||
| } | ||||
|  | ||||
| [[nodiscard]] auto read_encrypted_range( | ||||
|     const http_range &range, const utils::hash::hash_256_t &key, bool uses_kdf, | ||||
|     reader_func_t reader_func, std::uint64_t total_size, unsigned char *data, | ||||
|     std::size_t size, std::size_t &bytes_read) -> bool { | ||||
|   std::span dest_buffer(data, size); | ||||
|   return read_encrypted_range<std::span<unsigned char>>( | ||||
|       range, key, reader_func, total_size, dest_buffer, | ||||
|       uses_kdf ? kdf_config::size() : 0U, bytes_read); | ||||
| } | ||||
| } // namespace repertory::utils::encryption | ||||
|  | ||||
| #endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined (PROJECT_ENABLE_BOOST) | ||||
|   | ||||
| @@ -43,7 +43,7 @@ auto enc_file::copy_to(std::string_view new_path, bool overwrite) const | ||||
|   return file_->copy_to(new_path, overwrite); | ||||
| } | ||||
|  | ||||
| void enc_file::flush() const { return file_->flush(); } | ||||
| void enc_file::flush() const { file_->flush(); } | ||||
|  | ||||
| auto enc_file::move_to(std::string_view path) -> bool { | ||||
|   return file_->move_to(path); | ||||
| @@ -68,8 +68,8 @@ auto enc_file::read(unsigned char *data, std::size_t to_read, | ||||
|   std::size_t bytes_read{}; | ||||
|   auto ret{ | ||||
|       utils::encryption::read_encrypted_range( | ||||
|           {offset, offset + to_read - 1U}, | ||||
|           utils::encryption::generate_key<utils::encryption::hash_256_t>( | ||||
|           {.begin = offset, .end = offset + to_read - 1U}, | ||||
|           utils::encryption::generate_key<utils::hash::hash_256_t>( | ||||
|               encryption_token_), | ||||
|           [&](auto &&ct_buffer, auto &&start_offset, | ||||
|               auto &&end_offset) -> bool { | ||||
| @@ -145,7 +145,7 @@ auto enc_file::truncate(std::size_t size) -> bool { | ||||
|     return i_file::write(data, offset); | ||||
|   } | ||||
|  | ||||
|   auto begin_chunk{ | ||||
|   /* auto begin_chunk{ | ||||
|       file_size.value() / | ||||
|           utils::encryption::encrypting_reader::get_data_chunk_size(), | ||||
|   }; | ||||
| @@ -153,13 +153,14 @@ auto enc_file::truncate(std::size_t size) -> bool { | ||||
|       utils::divide_with_ceiling( | ||||
|           file_size.value(), | ||||
|           utils::encryption::encrypting_reader::get_data_chunk_size()), | ||||
|   }; | ||||
|   }; */ | ||||
|  | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| auto enc_file::write(const unsigned char *data, std::size_t to_write, | ||||
|                      std::size_t offset, std::size_t *total_written) -> bool { | ||||
| auto enc_file::write(const unsigned char * /* data */, std::size_t to_write, | ||||
|                      std::size_t offset, std::size_t * /* total_written */) | ||||
|     -> bool { | ||||
|   auto file_size{size()}; | ||||
|   if (not file_size.has_value()) { | ||||
|     return false; | ||||
| @@ -181,7 +182,7 @@ auto enc_file::size() const -> std::optional<std::uint64_t> { | ||||
|   } | ||||
|  | ||||
|   return utils::encryption::encrypting_reader::calculate_decrypted_size( | ||||
|       file_size.value()); | ||||
|       file_size.value(), false); | ||||
| } | ||||
| } // namespace repertory::utils::file | ||||
|  | ||||
|   | ||||
| @@ -25,7 +25,7 @@ | ||||
|  | ||||
| #include "utils/error.hpp" | ||||
|  | ||||
| namespace repertory::utils::encryption { | ||||
| namespace repertory::utils::hash { | ||||
| auto create_hash_blake2b_256(std::string_view data) -> hash_256_t { | ||||
|   return create_hash_blake2b_t<hash_256_t>( | ||||
|       reinterpret_cast<const unsigned char *>(data.data()), data.size()); | ||||
| @@ -111,8 +111,8 @@ auto create_hash_sha512(const data_buffer &data) -> hash_512_t { | ||||
|       data.size() * sizeof(data_buffer::value_type)); | ||||
| } | ||||
|  | ||||
| auto create_hash_sha512(const unsigned char *data, | ||||
|                         std::size_t data_size) -> hash_512_t { | ||||
| auto create_hash_sha512(const unsigned char *data, std::size_t data_size) | ||||
|     -> hash_512_t { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   hash_512_t hash{}; | ||||
| @@ -148,8 +148,8 @@ auto create_hash_sha512(const unsigned char *data, | ||||
|   return hash; | ||||
| } | ||||
|  | ||||
| auto create_hash_sha256(const unsigned char *data, | ||||
|                         std::size_t data_size) -> hash_256_t { | ||||
| auto create_hash_sha256(const unsigned char *data, std::size_t data_size) | ||||
|     -> hash_256_t { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   hash_256_t hash{}; | ||||
| @@ -184,6 +184,6 @@ auto create_hash_sha256(const unsigned char *data, | ||||
|  | ||||
|   return hash; | ||||
| } | ||||
| } // namespace repertory::utils::encryption | ||||
| } // namespace repertory::utils::hash | ||||
|  | ||||
| #endif // defined(PROJECT_ENABLE_LIBSODIUM) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user