updated build system
This commit is contained in:
		| @@ -34,32 +34,177 @@ inline constexpr std::uint32_t encryption_header_size{ | ||||
|         crypto_aead_xchacha20poly1305_IETF_ABYTES, | ||||
| }; | ||||
|  | ||||
| #if defined(PROJECT_ENABLE_BOOST) | ||||
| enum class kdf_version : std::uint8_t { v1 }; | ||||
|  | ||||
| enum class kdf_type : std::uint8_t { argon2id }; | ||||
|  | ||||
| enum class memlimit_level : std::uint8_t { | ||||
|   level1, // 64MiB | ||||
|   level2, // 256MiB | ||||
|   level3, // 512MiB | ||||
|   level4, // 1GiB | ||||
| }; | ||||
|  | ||||
| enum class opslimit_level : std::uint8_t { | ||||
|   level1, // interactive | ||||
|   level2, // moderate | ||||
|   level3, // sensitive | ||||
| }; | ||||
|  | ||||
| [[nodiscard]] inline auto get_memlimit(memlimit_level memlimit) -> size_t { | ||||
|   constexpr const auto mib512{512ULL * 1024ULL * 1024ULL}; | ||||
|  | ||||
|   switch (memlimit) { | ||||
|   case memlimit_level::level1: | ||||
|     return crypto_pwhash_MEMLIMIT_INTERACTIVE; | ||||
|  | ||||
|   case memlimit_level::level2: | ||||
|     return crypto_pwhash_MEMLIMIT_MODERATE; | ||||
|  | ||||
|   case memlimit_level::level3: | ||||
|     return mib512; | ||||
|  | ||||
|   case memlimit_level::level4: | ||||
|     return crypto_pwhash_MEMLIMIT_SENSITIVE; | ||||
|   } | ||||
|  | ||||
|   return mib512; | ||||
| } | ||||
|  | ||||
| [[nodiscard]] inline auto get_opslimit(opslimit_level opslimit) | ||||
|     -> unsigned long long { | ||||
|   switch (opslimit) { | ||||
|   case opslimit_level::level1: | ||||
|     return crypto_pwhash_OPSLIMIT_INTERACTIVE; | ||||
|  | ||||
|   case opslimit_level::level2: | ||||
|     return crypto_pwhash_OPSLIMIT_MODERATE; | ||||
|  | ||||
|   case opslimit_level::level3: | ||||
|     return crypto_pwhash_OPSLIMIT_SENSITIVE; | ||||
|   } | ||||
|  | ||||
|   return crypto_pwhash_OPSLIMIT_MODERATE; | ||||
| } | ||||
|  | ||||
| #pragma pack(push, 1) | ||||
| struct kdf_config final { | ||||
|   static constexpr std::uint32_t repertory_magic{0x52505432}; | ||||
|   using salt_t = std::array<std::uint8_t, crypto_pwhash_SALTBYTES>; | ||||
|  | ||||
|   std::uint32_t magic{repertory_magic}; | ||||
|   kdf_version version{kdf_version::v1}; | ||||
|   kdf_type kdf{kdf_type::argon2id}; | ||||
|   memlimit_level memlimit{memlimit_level::level3}; | ||||
|   opslimit_level opslimit{opslimit_level::level2}; | ||||
|   salt_t salt{}; | ||||
|   std::uint64_t checksum{}; | ||||
|  | ||||
|   [[nodiscard]] static constexpr auto size() -> std::size_t { | ||||
|     return sizeof(kdf_config); | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto generate_checksum() const -> std::uint64_t; | ||||
|  | ||||
|   void generate_salt(); | ||||
|  | ||||
|   [[nodiscard]] static auto from_header(std::span<const unsigned char> data, | ||||
|                                         kdf_config &cfg) -> bool; | ||||
|  | ||||
|   [[nodiscard]] auto to_header() -> auto { | ||||
|     kdf_config tmp{*this}; | ||||
|     tmp.checksum = boost::endian::native_to_big(tmp.checksum); | ||||
|     tmp.magic = boost::endian::native_to_big(tmp.magic); | ||||
|  | ||||
|     std::array<std::uint8_t, size()> ret{}; | ||||
|     std::memcpy(ret.data(), &tmp, size()); | ||||
|     return ret; | ||||
|   } | ||||
|  | ||||
|   [[nodiscard]] auto operator==(const kdf_config &) const -> bool = default; | ||||
|   [[nodiscard]] auto operator!=(const kdf_config &) const -> bool = default; | ||||
| }; | ||||
| #pragma pack(pop) | ||||
| #endif // defined(PROJECT_ENABLE_BOOST) | ||||
|  | ||||
| template <typename hash_t> | ||||
| inline auto generate_key( | ||||
| [[nodiscard]] inline auto generate_key( | ||||
|     std::string_view password, | ||||
|     std::function<hash_t(const unsigned char *data, std::size_t size)> hasher = | ||||
|         default_create_hash<hash_t>()) -> hash_t; | ||||
|         utils::hash::default_create_hash<hash_t>()) -> hash_t; | ||||
|  | ||||
| template <typename hash_t> | ||||
| inline auto generate_key( | ||||
| [[nodiscard]] inline auto generate_key( | ||||
|     std::wstring_view password, | ||||
|     std::function<hash_t(const unsigned char *data, std::size_t size)> hasher = | ||||
|         default_create_hash<hash_t>()) -> hash_t; | ||||
|         utils::hash::default_create_hash<hash_t>()) -> hash_t; | ||||
|  | ||||
| #if defined(PROJECT_ENABLE_BOOST) | ||||
| template <typename hash_t> | ||||
| [[nodiscard]] inline auto generate_key(std::string_view password, | ||||
|                                        kdf_config &cfg) -> hash_t; | ||||
|  | ||||
| template <typename hash_t> | ||||
| [[nodiscard]] inline auto generate_key(std::wstring_view password, | ||||
|                                        kdf_config &cfg) -> hash_t; | ||||
|  | ||||
| template <typename hash_t> | ||||
| [[nodiscard]] inline auto recreate_key(std::string_view password, | ||||
|                                        const kdf_config &cfg) -> hash_t; | ||||
|  | ||||
| template <typename hash_t> | ||||
| [[nodiscard]] inline auto recreate_key(std::wstring_view password, | ||||
|                                        const kdf_config &cfg) -> hash_t; | ||||
|  | ||||
| template <typename string_t> | ||||
| [[nodiscard]] auto create_key_argon2id(string_t password, kdf_config &cfg, | ||||
|                                        utils::hash::hash_256_t &key) -> bool; | ||||
|  | ||||
| template <typename string_t> | ||||
| [[nodiscard]] auto recreate_key_argon2id(string_t password, | ||||
|                                          const kdf_config &cfg, | ||||
|                                          utils::hash::hash_256_t &key) -> bool; | ||||
|  | ||||
| template <typename hash_t, typename string_t> | ||||
| [[nodiscard]] inline bool | ||||
| detect_and_recreate_key(string_t password, | ||||
|                         std::span<const unsigned char> header, hash_t &key, | ||||
|                         std::optional<kdf_config> &cfg); | ||||
|  | ||||
| template <typename hash_t> | ||||
| [[nodiscard]] inline bool | ||||
| detect_and_recreate_key(std::string_view password, | ||||
|                         std::span<const unsigned char> header, hash_t &key, | ||||
|                         std::optional<kdf_config> &cfg); | ||||
|  | ||||
| template <typename hash_t> | ||||
| [[nodiscard]] inline bool | ||||
| detect_and_recreate_key(std::wstring_view password, | ||||
|                         std::span<const unsigned char> header, hash_t &key, | ||||
|                         std::optional<kdf_config> &cfg); | ||||
|  | ||||
| [[nodiscard]] auto decrypt_file_name(std::string_view encryption_token, | ||||
|                                      std::string &file_name) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto decrypt_file_path(std::string_view encryption_token, | ||||
|                                      std::string &file_path) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto decrypt_file_name(std::string_view encryption_token, | ||||
|                                      const kdf_config &cfg, | ||||
|                                      std::string &file_name) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto decrypt_file_path(std::string_view encryption_token, | ||||
|                                      const kdf_config &cfg, | ||||
|                                      std::string &file_path) -> bool; | ||||
|  | ||||
| template <typename result_t, typename arr_t, std::size_t arr_size> | ||||
| [[nodiscard]] inline auto decrypt_data(const std::array<arr_t, arr_size> &key, | ||||
|                                        const unsigned char *buffer, | ||||
|                                        std::size_t buffer_size, | ||||
|                                        result_t &res) -> bool { | ||||
|                                        std::size_t buffer_size, result_t &res) | ||||
|     -> bool { | ||||
|   if (buffer_size > encryption_header_size) { | ||||
|     const std::uint32_t size = | ||||
|     std::uint32_t size = | ||||
|         boost::endian::native_to_big(static_cast<std::uint32_t>(buffer_size)); | ||||
|     res.resize(buffer_size - encryption_header_size); | ||||
|     return crypto_aead_xchacha20poly1305_ietf_decrypt_detached( | ||||
| @@ -76,32 +221,53 @@ template <typename result_t, typename arr_t, std::size_t arr_size> | ||||
| template <typename buffer_t, typename result_t, typename arr_t, | ||||
|           std::size_t arr_size> | ||||
| [[nodiscard]] inline auto decrypt_data(const std::array<arr_t, arr_size> &key, | ||||
|                                        const buffer_t &buf, | ||||
|                                        result_t &res) -> bool { | ||||
|                                        const buffer_t &buf, result_t &res) | ||||
|     -> bool { | ||||
|   return decrypt_data<result_t>( | ||||
|       key, reinterpret_cast<const unsigned char *>(buf.data()), buf.size(), | ||||
|       res); | ||||
| } | ||||
|  | ||||
| template <typename buffer_t, typename result_t, typename hash_t = hash_256_t> | ||||
| template <typename buffer_t, typename result_t, | ||||
|           typename hash_t = utils::hash::hash_256_t> | ||||
| [[nodiscard]] inline auto decrypt_data( | ||||
|     std::string_view password, const buffer_t &buf, result_t &res, | ||||
|     std::function<hash_t(const unsigned char *data, std::size_t size)> hasher = | ||||
|         default_create_hash<hash_t>()) -> bool { | ||||
|         utils::hash::default_create_hash<hash_t>()) -> bool { | ||||
|   return decrypt_data<buffer_t, result_t>(generate_key(password, hasher), buf, | ||||
|                                           res); | ||||
| } | ||||
|  | ||||
| template <typename result_t, typename hash_t = hash_256_t> | ||||
| template <typename buffer_t, typename result_t, | ||||
|           typename hash_t = utils::hash::hash_256_t> | ||||
| [[nodiscard]] inline auto decrypt_data(std::string_view password, | ||||
|                                        const kdf_config &cfg, | ||||
|                                        const buffer_t &buf, result_t &res) | ||||
|     -> bool { | ||||
|   return decrypt_data<buffer_t, result_t>(recreate_key<hash_t>(password, cfg), | ||||
|                                           buf, res); | ||||
| } | ||||
|  | ||||
| template <typename result_t, typename hash_t = utils::hash::hash_256_t> | ||||
| [[nodiscard]] inline auto decrypt_data( | ||||
|     std::string_view password, const unsigned char *buffer, | ||||
|     std::size_t buffer_size, result_t &res, | ||||
|     std::function<hash_t(const unsigned char *data, std::size_t size)> hasher = | ||||
|         default_create_hash<hash_t>()) -> bool { | ||||
|         utils::hash::default_create_hash<hash_t>()) -> bool { | ||||
|   return decrypt_data<result_t>(generate_key(password, hasher), buffer, | ||||
|                                 buffer_size, res); | ||||
| } | ||||
|  | ||||
| template <typename result_t, typename hash_t = utils::hash::hash_256_t> | ||||
| [[nodiscard]] inline auto decrypt_data(std::string_view password, | ||||
|                                        const kdf_config &cfg, | ||||
|                                        const unsigned char *buffer, | ||||
|                                        std::size_t buffer_size, result_t &res) | ||||
|     -> bool { | ||||
|   return decrypt_data<result_t>(recreate_key<hash_t>(password, cfg), buffer, | ||||
|                                 buffer_size, res); | ||||
| } | ||||
|  | ||||
| template <typename result_t, typename arr_t, std::size_t arr_size> | ||||
| inline void | ||||
| encrypt_data(const std::array<unsigned char, | ||||
| @@ -144,26 +310,44 @@ inline void encrypt_data(const std::array<arr_t, arr_size> &key, | ||||
|   encrypt_data<result_t>(iv, key, buffer, buffer_size, res); | ||||
| } | ||||
|  | ||||
| template <typename result_t, typename hash_t = hash_256_t> | ||||
| template <typename result_t, typename hash_t = utils::hash::hash_256_t> | ||||
| inline void encrypt_data( | ||||
|     std::string_view password, const unsigned char *buffer, | ||||
|     std::size_t buffer_size, result_t &res, | ||||
|     std::function<hash_t(const unsigned char *data, std::size_t size)> hasher = | ||||
|         default_create_hash<hash_t>()) { | ||||
|         utils::hash::default_create_hash<hash_t>()) { | ||||
|   encrypt_data<result_t>(generate_key(password, hasher), buffer, buffer_size, | ||||
|                          res); | ||||
| } | ||||
|  | ||||
| template <typename buffer_t, typename result_t, typename hash_t = hash_256_t> | ||||
| template <typename result_t, typename hash_t = utils::hash::hash_256_t> | ||||
| inline void encrypt_data(std::string_view password, kdf_config &cfg, | ||||
|                          const unsigned char *buffer, std::size_t buffer_size, | ||||
|                          result_t &res) { | ||||
|   encrypt_data<result_t>(generate_key<hash_t>(password, cfg), buffer, | ||||
|                          buffer_size, res); | ||||
| } | ||||
|  | ||||
| template <typename buffer_t, typename result_t, | ||||
|           typename hash_t = utils::hash::hash_256_t> | ||||
| inline void encrypt_data( | ||||
|     std::string_view password, const buffer_t &buf, result_t &res, | ||||
|     std::function<hash_t(const unsigned char *data, std::size_t size)> hasher = | ||||
|         default_create_hash<hash_t>()) { | ||||
|         utils::hash::default_create_hash<hash_t>()) { | ||||
|   encrypt_data<result_t>(generate_key(password, hasher), | ||||
|                          reinterpret_cast<const unsigned char *>(buf.data()), | ||||
|                          buf.size(), res); | ||||
| } | ||||
|  | ||||
| template <typename buffer_t, typename result_t, | ||||
|           typename hash_t = utils::hash::hash_256_t> | ||||
| inline void encrypt_data(std::string_view password, kdf_config &cfg, | ||||
|                          const buffer_t &buf, result_t &res) { | ||||
|   encrypt_data<result_t>(generate_key<hash_t>(password, cfg), | ||||
|                          reinterpret_cast<const unsigned char *>(buf.data()), | ||||
|                          buf.size(), res); | ||||
| } | ||||
|  | ||||
| template <typename buffer_t, typename result_t, typename arr_t, | ||||
|           std::size_t arr_size> | ||||
| inline void encrypt_data(const std::array<arr_t, arr_size> &key, | ||||
| @@ -189,16 +373,52 @@ using reader_func_t = | ||||
|     std::function<bool(data_buffer &cypher_text, std::uint64_t start_offset, | ||||
|                        std::uint64_t end_offset)>; | ||||
|  | ||||
| [[nodiscard]] 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, | ||||
|                      data_buffer &data) -> bool; | ||||
| [[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, | ||||
|                                         data_buffer &data) -> bool; | ||||
|  | ||||
| [[nodiscard]] auto read_encrypted_range( | ||||
|     const http_range &range, const utils::encryption::hash_256_t &key, | ||||
|     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; | ||||
|  | ||||
| [[nodiscard]] inline auto | ||||
| read_encrypted_range(const http_range &range, | ||||
|                      const utils::hash::hash_256_t &key, | ||||
|                      reader_func_t reader_func, std::uint64_t total_size, | ||||
|                      data_buffer &data) -> bool { | ||||
|   return read_encrypted_range(range, key, false, reader_func, total_size, data); | ||||
| } | ||||
|  | ||||
| [[nodiscard]] inline auto read_encrypted_range( | ||||
|     const http_range &range, const utils::hash::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 { | ||||
|   return read_encrypted_range(range, key, false, reader_func, total_size, data, | ||||
|                               size, bytes_read); | ||||
| } | ||||
|  | ||||
| template <typename string_t> | ||||
| auto create_key_argon2id(string_t password, kdf_config &cfg, | ||||
|                          utils::hash::hash_256_t &key) -> bool { | ||||
|   cfg.generate_salt(); | ||||
|  | ||||
|   return recreate_key_argon2id(password, cfg, key); | ||||
| } | ||||
|  | ||||
| template <typename string_t> | ||||
| auto recreate_key_argon2id(string_t password, const kdf_config &cfg, | ||||
|                            utils::hash::hash_256_t &key) -> bool { | ||||
|   return crypto_pwhash( | ||||
|              reinterpret_cast<unsigned char *>(key.data()), key.size(), | ||||
|              reinterpret_cast<const char *>(password.data()), | ||||
|              password.size() * sizeof(typename string_t::value_type), | ||||
|              cfg.salt.data(), get_opslimit(cfg.opslimit), | ||||
|              get_memlimit(cfg.memlimit), crypto_pwhash_ALG_ARGON2ID13) == 0; | ||||
| } | ||||
| #endif // defined(PROJECT_ENABLE_BOOST) | ||||
|  | ||||
| template <typename hash_t> | ||||
| @@ -218,6 +438,142 @@ inline auto generate_key( | ||||
|   return hasher(reinterpret_cast<const unsigned char *>(password.data()), | ||||
|                 password.size() * sizeof(wchar_t)); | ||||
| } | ||||
|  | ||||
| #if defined(PROJECT_ENABLE_BOOST) | ||||
| template <typename hash_t, typename string_t> | ||||
| inline auto generate_key_impl(string_t password, kdf_config &cfg) -> hash_t { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   switch (cfg.version) { | ||||
|   case kdf_version::v1: | ||||
|     switch (cfg.kdf) { | ||||
|     case kdf_type::argon2id: { | ||||
|       hash_t key{}; | ||||
|       if (not create_key_argon2id(password, cfg, key)) { | ||||
|         throw utils::error::create_exception( | ||||
|             function_name, { | ||||
|                                "failed to generate argon2id key", | ||||
|                            }); | ||||
|       } | ||||
|  | ||||
|       return key; | ||||
|     } | ||||
|  | ||||
|     default: | ||||
|       throw utils::error::create_exception( | ||||
|           function_name, { | ||||
|                              "unsupported kdf type", | ||||
|                              std::to_string(static_cast<std::uint8_t>(cfg.kdf)), | ||||
|                          }); | ||||
|     } | ||||
|  | ||||
|   default: | ||||
|     throw utils::error::create_exception( | ||||
|         function_name, | ||||
|         { | ||||
|             "unsupported kdf version", | ||||
|             std::to_string(static_cast<std::uint8_t>(cfg.version)), | ||||
|         }); | ||||
|   } | ||||
| } | ||||
|  | ||||
| template <typename hash_t, typename string_t> | ||||
| inline auto recreate_key_impl(string_t password, const kdf_config &cfg) | ||||
|     -> hash_t { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   switch (cfg.version) { | ||||
|   case kdf_version::v1: | ||||
|     switch (cfg.kdf) { | ||||
|     case kdf_type::argon2id: { | ||||
|       hash_t key{}; | ||||
|       if (not recreate_key_argon2id(password, cfg, key)) { | ||||
|         throw utils::error::create_exception( | ||||
|             function_name, { | ||||
|                                "failed to generate argon2id key", | ||||
|                            }); | ||||
|       } | ||||
|  | ||||
|       return key; | ||||
|     } | ||||
|  | ||||
|     default: | ||||
|       throw utils::error::create_exception( | ||||
|           function_name, { | ||||
|                              "unsupported kdf type", | ||||
|                              std::to_string(static_cast<std::uint8_t>(cfg.kdf)), | ||||
|                          }); | ||||
|     } | ||||
|  | ||||
|   default: | ||||
|     throw utils::error::create_exception( | ||||
|         function_name, | ||||
|         { | ||||
|             "unsupported kdf version", | ||||
|             std::to_string(static_cast<std::uint8_t>(cfg.version)), | ||||
|         }); | ||||
|   } | ||||
| } | ||||
|  | ||||
| template <typename hash_t> | ||||
| inline auto generate_key(std::string_view password, kdf_config &cfg) -> hash_t { | ||||
|   return generate_key_impl<hash_t, std::string_view>(password, cfg); | ||||
| } | ||||
|  | ||||
| template <typename hash_t> | ||||
| inline auto generate_key(std::wstring_view password, kdf_config &cfg) | ||||
|     -> hash_t { | ||||
|   return generate_key_impl<hash_t, std::wstring_view>(password, cfg); | ||||
| } | ||||
|  | ||||
| template <typename hash_t> | ||||
| inline auto recreate_key(std::string_view password, const kdf_config &cfg) | ||||
|     -> hash_t { | ||||
|   return recreate_key_impl<hash_t, std::string_view>(password, cfg); | ||||
| } | ||||
|  | ||||
| template <typename hash_t> | ||||
| inline auto recreate_key(std::wstring_view password, const kdf_config &cfg) | ||||
|     -> hash_t { | ||||
|   return recreate_key_impl<hash_t, std::wstring_view>(password, cfg); | ||||
| } | ||||
|  | ||||
| template <typename hash_t, typename string_t> | ||||
| inline bool detect_and_recreate_key(string_t password, | ||||
|                                     std::span<const unsigned char> header, | ||||
|                                     hash_t &key, | ||||
|                                     std::optional<kdf_config> &cfg) { | ||||
|   if (header.size() >= kdf_config::size()) { | ||||
|     kdf_config tmp{}; | ||||
|     if (kdf_config::from_header(header.first(kdf_config::size()), tmp)) { | ||||
|       cfg = tmp; | ||||
|       key = recreate_key<hash_t>(password, *cfg); | ||||
|       return true; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   key = generate_key<hash_t>(password); | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| template <typename hash_t> | ||||
| inline bool detect_and_recreate_key(std::string_view password, | ||||
|                                     std::span<const unsigned char> header, | ||||
|                                     hash_t &key, | ||||
|                                     std::optional<kdf_config> &cfg) { | ||||
|   return detect_and_recreate_key<hash_t, std::string_view>(password, header, | ||||
|                                                            key, cfg); | ||||
| } | ||||
|  | ||||
| template <typename hash_t> | ||||
| inline bool detect_and_recreate_key(std::wstring_view password, | ||||
|                                     std::span<const unsigned char> header, | ||||
|                                     hash_t &key, | ||||
|                                     std::optional<kdf_config> &cfg) { | ||||
|   return detect_and_recreate_key<hash_t, std::wstring_view>(password, header, | ||||
|                                                             key, cfg); | ||||
| } | ||||
| #endif // defined(PROJECT_ENABLE_BOOST) | ||||
| } // namespace repertory::utils::encryption | ||||
|  | ||||
| #endif // defined(PROJECT_ENABLE_LIBSODIUM) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user