From 1f6cacd70c7309fd38b76a14ec7d58af04debe07 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Mon, 22 Jun 2026 18:09:30 +0200 Subject: aesxx/utils: move helper headers to helpers/ --- aesxx/utils/CMakeLists.txt | 12 +-- aesxx/utils/block_cmd_parser.hpp | 121 ------------------------------- aesxx/utils/block_dumper.hpp | 85 ---------------------- aesxx/utils/block_input.hpp | 24 ------ aesxx/utils/data_parsers.hpp | 55 -------------- aesxx/utils/decrypt_block.cpp | 6 +- aesxx/utils/decrypt_bmp.cpp | 2 +- aesxx/utils/decrypt_file.cpp | 2 +- aesxx/utils/encrypt_block.cpp | 6 +- aesxx/utils/encrypt_bmp.cpp | 2 +- aesxx/utils/encrypt_file.cpp | 2 +- aesxx/utils/file_cmd_parser.hpp | 82 --------------------- aesxx/utils/helpers/block_dumper.hpp | 85 ++++++++++++++++++++++ aesxx/utils/helpers/block_input.hpp | 24 ++++++ aesxx/utils/helpers/cmd_parser.hpp | 76 +++++++++++++++++++ aesxx/utils/helpers/cmd_parser_block.hpp | 121 +++++++++++++++++++++++++++++++ aesxx/utils/helpers/cmd_parser_file.hpp | 82 +++++++++++++++++++++ aesxx/utils/helpers/command_line.hpp | 76 ------------------- aesxx/utils/helpers/data_parsers.hpp | 55 ++++++++++++++ 19 files changed, 459 insertions(+), 459 deletions(-) delete mode 100644 aesxx/utils/block_cmd_parser.hpp delete mode 100644 aesxx/utils/block_dumper.hpp delete mode 100644 aesxx/utils/block_input.hpp delete mode 100644 aesxx/utils/data_parsers.hpp delete mode 100644 aesxx/utils/file_cmd_parser.hpp create mode 100644 aesxx/utils/helpers/block_dumper.hpp create mode 100644 aesxx/utils/helpers/block_input.hpp create mode 100644 aesxx/utils/helpers/cmd_parser.hpp create mode 100644 aesxx/utils/helpers/cmd_parser_block.hpp create mode 100644 aesxx/utils/helpers/cmd_parser_file.hpp delete mode 100644 aesxx/utils/helpers/command_line.hpp create mode 100644 aesxx/utils/helpers/data_parsers.hpp diff --git a/aesxx/utils/CMakeLists.txt b/aesxx/utils/CMakeLists.txt index 470a313..4958bef 100644 --- a/aesxx/utils/CMakeLists.txt +++ b/aesxx/utils/CMakeLists.txt @@ -16,20 +16,20 @@ function(add_util name src) endfunction() set(block_util_headers - block_cmd_parser.hpp block_dumper.hpp block_input.hpp - data_parsers.hpp - helpers/command_line.hpp + helpers/cmd_parser.hpp + helpers/cmd_paresr_block.hpp + helpers/data_parsers.hpp ) add_util(encrypt_block encrypt_block.cpp ${block_util_headers}) add_util(decrypt_block decrypt_block.cpp ${block_util_headers}) set(file_util_headers - data_parsers.hpp - file_cmd_parser.hpp - helpers/command_line.hpp + helpers/cmd_parser.hpp + helpers/cmd_parser_file.hpp + helpers/data_parsers.hpp helpers/file.hpp ) diff --git a/aesxx/utils/block_cmd_parser.hpp b/aesxx/utils/block_cmd_parser.hpp deleted file mode 100644 index a20f4f5..0000000 --- a/aesxx/utils/block_cmd_parser.hpp +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include "block_input.hpp" -#include "data_parsers.hpp" -#include "helpers/command_line.hpp" - -#include - -#include - -#include -#include -#include -#include -#include -#include - -class BlockSettings : public SettingsParser { -public: - aes::Algorithm algorithm = AES_AES128; - aes::Mode mode = AES_ECB; - - bool use_boxes = false; - bool verbose = false; - - std::vector inputs; - - explicit BlockSettings(std::string_view argv0) : SettingsParser{argv0} { - visible.add_options()( - "verbose,v", boost::program_options::bool_switch(&verbose), "enable verbose output" - ); - visible.add_options()( - "algorithm,a", - boost::program_options::value(&algorithm) - ->required() - ->value_name("NAME"), - "set algorithm" - ); - visible.add_options()( - "mode,m", - boost::program_options::value(&mode)->required()->value_name("MODE"), - "set mode of operation" - ); - visible.add_options()( - "use-boxes,b", - boost::program_options::bool_switch(&use_boxes), - "use the \"boxes\" interface" - ); - hidden.add_options()( - "args", - boost::program_options::value>(&args), - "shouldn't be visible" - ); - positional.add("args", -1); - } - - const char* get_short_description() const override { - return "[-h|--help] [-v|--verbose] [-a|--algorithm NAME] [-m|--mode MODE]" - " [-- KEY [IV] [BLOCK]...]..."; - } - - void parse(int argc, char* argv[]) override { - SettingsParser::parse(argc, argv); - parse_inputs( - std::deque{ - std::make_move_iterator(args.begin()), std::make_move_iterator(args.end()) - } - ); - } - -private: - void parse_inputs(std::deque&& src) { - while (!src.empty()) - inputs.emplace_back(parse_input(src)); - } - - Input parse_input(std::deque& src) const { - std::string key{std::move(src.front())}; - src.pop_front(); - - std::string iv; - - if (aes::mode_requires_init_vector(mode)) { - if (src.empty()) { - throw boost::program_options::error{ - "an initialization vector is required for the selected mode of operation" - }; - } - iv = std::move(src.front()); - src.pop_front(); - } - - auto blocks = parse_blocks(src); - - if (aes::mode_requires_init_vector(mode)) - return {key, iv, std::move(blocks)}; - else - return {key, std::move(blocks)}; - } - - static std::vector parse_blocks(std::deque& src) { - std::vector blocks; - - while (!src.empty()) { - std::string block{std::move(src.front())}; - src.pop_front(); - if (block == "--") - break; - blocks.emplace_back(std::move(block)); - } - - return blocks; - } - - std::vector args; -}; diff --git a/aesxx/utils/block_dumper.hpp b/aesxx/utils/block_dumper.hpp deleted file mode 100644 index 8284b67..0000000 --- a/aesxx/utils/block_dumper.hpp +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include - -#include -#include -#include -#include -#include - -template -void dump_block(std::string_view header, const typename aes::Types::Block& block) { - std::cout << std::format("{}: {}\n", header, aes::to_string(block)); - std::cout << std::format("{}\n", aes::to_matrix_string(block)); -} - -template -void dump_plaintext(const typename aes::Types::Block& block) { - dump_block("Plaintext", block); -} - -template -void dump_key(const typename aes::Types::Key& key) { - std::cout << std::format("Key: {}\n\n", aes::to_string(key)); -} - -template -void dump_ciphertext(const typename aes::Types::Block& ciphertext) { - dump_block("Ciphertext", ciphertext); -} - -template -void dump_iv(const typename aes::Types::Block& iv) { - dump_block("Initialization vector", iv); -} - -template -void dump_round_keys( - const char* header, - const typename aes::Types::RoundKeys& round_keys -) { - std::cout << std::format("{}:\n", header); - for (std::size_t i = 0; i < aes::get_number_of_rounds(); ++i) - std::cout << std::format("\t[{}]: {}\n", i, aes::to_string(round_keys.keys[i])); - std::cout << "\n"; -} - -template -void dump_encryption_keys(const typename aes::Types::RoundKeys& round_keys) { - dump_round_keys("Encryption round keys", round_keys); -} - -template -void dump_decryption_keys(const typename aes::Types::RoundKeys& round_keys) { - dump_round_keys("Decryption round keys", round_keys); -} - -template -void dump_wrapper(const aes::EncryptWrapper& wrapper) { - dump_encryption_keys(wrapper.encryption_keys); -} - -template -void dump_wrapper(const aes::DecryptWrapper& wrapper) { - dump_decryption_keys(wrapper.decryption_keys); -} - -template -void dump_next_iv(const aes::EncryptWrapper& wrapper) { - if constexpr (aes::mode_requires_init_vector(mode)) { - dump_block("Next initialization vector", wrapper.iv); - } -} - -template -void dump_next_iv(const aes::DecryptWrapper& wrapper) { - if constexpr (aes::mode_requires_init_vector(mode)) { - dump_block("Next initialization vector", wrapper.iv); - } -} diff --git a/aesxx/utils/block_input.hpp b/aesxx/utils/block_input.hpp deleted file mode 100644 index 042a680..0000000 --- a/aesxx/utils/block_input.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include -#include -#include -#include - -class Input { -public: - Input(std::string_view key, std::string_view iv, std::vector&& blocks) - : key{key}, iv{iv}, blocks{std::move(blocks)} {} - - Input(std::string key, std::vector&& blocks) - : key{key}, blocks{std::move(blocks)} {} - - const std::string key; - const std::string iv; - const std::vector blocks; -}; diff --git a/aesxx/utils/data_parsers.hpp b/aesxx/utils/data_parsers.hpp deleted file mode 100644 index a08f1bf..0000000 --- a/aesxx/utils/data_parsers.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include - -#include -#include - -#include -#include -#include - -inline std::istream& operator>>(std::istream& is, aes::Mode& dest) { - std::string src; - is >> src; - - static const std::unordered_map lookup_table = { - {"ecb", AES_ECB}, - {"cbc", AES_CBC}, - {"cfb", AES_CFB}, - {"ofb", AES_OFB}, - {"ctr", AES_CTR}, - }; - - const auto it = lookup_table.find(boost::algorithm::to_lower_copy(src)); - - if (it == lookup_table.cend()) - throw boost::program_options::invalid_option_value(src); - - dest = it->second; - return is; -} - -inline std::istream& operator>>(std::istream& is, aes::Algorithm& dest) { - std::string src; - is >> src; - - static const std::unordered_map lookup_table = { - {"aes128", AES_AES128}, - {"aes192", AES_AES192}, - {"aes256", AES_AES256}, - }; - - const auto it = lookup_table.find(boost::algorithm::to_lower_copy(src)); - - if (it == lookup_table.cend()) - throw boost::program_options::invalid_option_value(src); - - dest = it->second; - return is; -} diff --git a/aesxx/utils/decrypt_block.cpp b/aesxx/utils/decrypt_block.cpp index 6eeb1d7..bcd3381 100644 --- a/aesxx/utils/decrypt_block.cpp +++ b/aesxx/utils/decrypt_block.cpp @@ -3,9 +3,9 @@ // For details, see https://github.com/egor-tensin/aes-tools. // Distributed under the MIT License. -#include "block_cmd_parser.hpp" -#include "block_dumper.hpp" -#include "block_input.hpp" +#include "helpers/block_dumper.hpp" +#include "helpers/block_input.hpp" +#include "helpers/cmd_parser_block.hpp" #include diff --git a/aesxx/utils/decrypt_bmp.cpp b/aesxx/utils/decrypt_bmp.cpp index 3247d63..d805c62 100644 --- a/aesxx/utils/decrypt_bmp.cpp +++ b/aesxx/utils/decrypt_bmp.cpp @@ -3,8 +3,8 @@ // For details, see https://github.com/egor-tensin/aes-tools. // Distributed under the MIT License. -#include "file_cmd_parser.hpp" #include "helpers/bmp.hpp" +#include "helpers/cmd_parser_file.hpp" #include "helpers/file.hpp" #include diff --git a/aesxx/utils/decrypt_file.cpp b/aesxx/utils/decrypt_file.cpp index 85476a9..42fe3e9 100644 --- a/aesxx/utils/decrypt_file.cpp +++ b/aesxx/utils/decrypt_file.cpp @@ -3,7 +3,7 @@ // For details, see https://github.com/egor-tensin/aes-tools. // Distributed under the MIT License. -#include "file_cmd_parser.hpp" +#include "helpers/cmd_parser_file.hpp" #include "helpers/file.hpp" #include diff --git a/aesxx/utils/encrypt_block.cpp b/aesxx/utils/encrypt_block.cpp index 5c8698d..d6e5534 100644 --- a/aesxx/utils/encrypt_block.cpp +++ b/aesxx/utils/encrypt_block.cpp @@ -3,9 +3,9 @@ // For details, see https://github.com/egor-tensin/aes-tools. // Distributed under the MIT License. -#include "block_cmd_parser.hpp" -#include "block_dumper.hpp" -#include "block_input.hpp" +#include "helpers/block_dumper.hpp" +#include "helpers/block_input.hpp" +#include "helpers/cmd_parser_block.hpp" #include diff --git a/aesxx/utils/encrypt_bmp.cpp b/aesxx/utils/encrypt_bmp.cpp index 2be1e4f..5c9acbf 100644 --- a/aesxx/utils/encrypt_bmp.cpp +++ b/aesxx/utils/encrypt_bmp.cpp @@ -3,8 +3,8 @@ // For details, see https://github.com/egor-tensin/aes-tools. // Distributed under the MIT License. -#include "file_cmd_parser.hpp" #include "helpers/bmp.hpp" +#include "helpers/cmd_parser_file.hpp" #include "helpers/file.hpp" #include diff --git a/aesxx/utils/encrypt_file.cpp b/aesxx/utils/encrypt_file.cpp index 94ed47c..e069ec7 100644 --- a/aesxx/utils/encrypt_file.cpp +++ b/aesxx/utils/encrypt_file.cpp @@ -3,7 +3,7 @@ // For details, see https://github.com/egor-tensin/aes-tools. // Distributed under the MIT License. -#include "file_cmd_parser.hpp" +#include "helpers/cmd_parser_file.hpp" #include "helpers/file.hpp" #include diff --git a/aesxx/utils/file_cmd_parser.hpp b/aesxx/utils/file_cmd_parser.hpp deleted file mode 100644 index 5cb109b..0000000 --- a/aesxx/utils/file_cmd_parser.hpp +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include "data_parsers.hpp" -#include "helpers/command_line.hpp" - -#include - -#include - -#include -#include -#include -#include - -class FileSettings : public SettingsParser { -public: - aes::Algorithm algorithm = AES_AES128; - aes::Mode mode = AES_ECB; - - std::string input_path; - std::string output_path; - std::string key; - std::string iv; - - explicit FileSettings(std::string_view argv0) : SettingsParser{argv0} { - visible.add_options()( - "algorithm,a", - boost::program_options::value(&algorithm) - ->required() - ->value_name("NAME"), - "set algorithm" - ); - visible.add_options()( - "mode,m", - boost::program_options::value(&mode)->required()->value_name("MODE"), - "set mode of operation" - ); - visible.add_options()( - "key,k", - boost::program_options::value(&key)->required()->value_name("KEY"), - "set encryption key" - ); - visible.add_options()( - "iv,v", - boost::program_options::value(&iv)->value_name("BLOCK"), - "set initialization vector" - ); - visible.add_options()( - "input,i", - boost::program_options::value(&input_path)->required()->value_name("PATH"), - "set input file path" - ); - visible.add_options()( - "output,o", - boost::program_options::value(&output_path) - ->required() - ->value_name("PATH"), - "set output file path" - ); - } - - const char* get_short_description() const override { - return "[-h|--help] [-a|--algorithm NAME] [-m|--mode MODE]" - " [-k|--key KEY] [-v|--iv BLOCK]" - " [-i|--input PATH] [-o|--output PATH]"; - } - - void parse(int argc, char** argv) override { - SettingsParser::parse(argc, argv); - - if (aes::mode_requires_init_vector(mode) && iv.empty()) { - throw boost::program_options::error{ - "an initialization vector is required for the selected mode of operation" - }; - } - } -}; diff --git a/aesxx/utils/helpers/block_dumper.hpp b/aesxx/utils/helpers/block_dumper.hpp new file mode 100644 index 0000000..8284b67 --- /dev/null +++ b/aesxx/utils/helpers/block_dumper.hpp @@ -0,0 +1,85 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include + +#include +#include +#include +#include +#include + +template +void dump_block(std::string_view header, const typename aes::Types::Block& block) { + std::cout << std::format("{}: {}\n", header, aes::to_string(block)); + std::cout << std::format("{}\n", aes::to_matrix_string(block)); +} + +template +void dump_plaintext(const typename aes::Types::Block& block) { + dump_block("Plaintext", block); +} + +template +void dump_key(const typename aes::Types::Key& key) { + std::cout << std::format("Key: {}\n\n", aes::to_string(key)); +} + +template +void dump_ciphertext(const typename aes::Types::Block& ciphertext) { + dump_block("Ciphertext", ciphertext); +} + +template +void dump_iv(const typename aes::Types::Block& iv) { + dump_block("Initialization vector", iv); +} + +template +void dump_round_keys( + const char* header, + const typename aes::Types::RoundKeys& round_keys +) { + std::cout << std::format("{}:\n", header); + for (std::size_t i = 0; i < aes::get_number_of_rounds(); ++i) + std::cout << std::format("\t[{}]: {}\n", i, aes::to_string(round_keys.keys[i])); + std::cout << "\n"; +} + +template +void dump_encryption_keys(const typename aes::Types::RoundKeys& round_keys) { + dump_round_keys("Encryption round keys", round_keys); +} + +template +void dump_decryption_keys(const typename aes::Types::RoundKeys& round_keys) { + dump_round_keys("Decryption round keys", round_keys); +} + +template +void dump_wrapper(const aes::EncryptWrapper& wrapper) { + dump_encryption_keys(wrapper.encryption_keys); +} + +template +void dump_wrapper(const aes::DecryptWrapper& wrapper) { + dump_decryption_keys(wrapper.decryption_keys); +} + +template +void dump_next_iv(const aes::EncryptWrapper& wrapper) { + if constexpr (aes::mode_requires_init_vector(mode)) { + dump_block("Next initialization vector", wrapper.iv); + } +} + +template +void dump_next_iv(const aes::DecryptWrapper& wrapper) { + if constexpr (aes::mode_requires_init_vector(mode)) { + dump_block("Next initialization vector", wrapper.iv); + } +} diff --git a/aesxx/utils/helpers/block_input.hpp b/aesxx/utils/helpers/block_input.hpp new file mode 100644 index 0000000..042a680 --- /dev/null +++ b/aesxx/utils/helpers/block_input.hpp @@ -0,0 +1,24 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include +#include +#include +#include + +class Input { +public: + Input(std::string_view key, std::string_view iv, std::vector&& blocks) + : key{key}, iv{iv}, blocks{std::move(blocks)} {} + + Input(std::string key, std::vector&& blocks) + : key{key}, blocks{std::move(blocks)} {} + + const std::string key; + const std::string iv; + const std::vector blocks; +}; diff --git a/aesxx/utils/helpers/cmd_parser.hpp b/aesxx/utils/helpers/cmd_parser.hpp new file mode 100644 index 0000000..607253c --- /dev/null +++ b/aesxx/utils/helpers/cmd_parser.hpp @@ -0,0 +1,76 @@ +// Copyright (c) 2017 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include + +class SettingsParser { +public: + explicit SettingsParser(std::string_view argv0) : prog_name{extract_filename(argv0)} { + visible.add_options()("help,h", "show this message and exit"); + } + + virtual ~SettingsParser() = default; + + virtual const char* get_short_description() const { + return "[--option VALUE]..."; + } + + virtual void parse(int argc, char* argv[]) { + boost::program_options::options_description all; + all.add(hidden).add(visible); + boost::program_options::variables_map vm; + boost::program_options::store( + boost::program_options::command_line_parser{argc, argv} + .options(all) + .positional(positional) + .run(), + vm + ); + if (vm.count("help")) + exit_with_usage = true; + else + boost::program_options::notify(vm); + } + + bool exit_with_usage = false; + + void usage() const { + std::cout << *this; + } + + void usage_error(const std::exception& e) const { + std::cerr << std::format("usage error: {}\n", e.what()); + std::cerr << *this; + } + +protected: + boost::program_options::options_description hidden; + boost::program_options::options_description visible; + boost::program_options::positional_options_description positional; + +private: + static std::string extract_filename(std::string_view path) { + return std::filesystem::path{path}.filename().string(); + } + + const std::string prog_name; + + friend std::ostream& operator<<(std::ostream& os, const SettingsParser& parser) { + const auto short_descr = parser.get_short_description(); + os << std::format("usage: {} {}\n", parser.prog_name, short_descr); + os << parser.visible; + return os; + } +}; diff --git a/aesxx/utils/helpers/cmd_parser_block.hpp b/aesxx/utils/helpers/cmd_parser_block.hpp new file mode 100644 index 0000000..c8db431 --- /dev/null +++ b/aesxx/utils/helpers/cmd_parser_block.hpp @@ -0,0 +1,121 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include "block_input.hpp" +#include "cmd_parser.hpp" +#include "data_parsers.hpp" + +#include + +#include + +#include +#include +#include +#include +#include +#include + +class BlockSettings : public SettingsParser { +public: + aes::Algorithm algorithm = AES_AES128; + aes::Mode mode = AES_ECB; + + bool use_boxes = false; + bool verbose = false; + + std::vector inputs; + + explicit BlockSettings(std::string_view argv0) : SettingsParser{argv0} { + visible.add_options()( + "verbose,v", boost::program_options::bool_switch(&verbose), "enable verbose output" + ); + visible.add_options()( + "algorithm,a", + boost::program_options::value(&algorithm) + ->required() + ->value_name("NAME"), + "set algorithm" + ); + visible.add_options()( + "mode,m", + boost::program_options::value(&mode)->required()->value_name("MODE"), + "set mode of operation" + ); + visible.add_options()( + "use-boxes,b", + boost::program_options::bool_switch(&use_boxes), + "use the \"boxes\" interface" + ); + hidden.add_options()( + "args", + boost::program_options::value>(&args), + "shouldn't be visible" + ); + positional.add("args", -1); + } + + const char* get_short_description() const override { + return "[-h|--help] [-v|--verbose] [-a|--algorithm NAME] [-m|--mode MODE]" + " [-- KEY [IV] [BLOCK]...]..."; + } + + void parse(int argc, char* argv[]) override { + SettingsParser::parse(argc, argv); + parse_inputs( + std::deque{ + std::make_move_iterator(args.begin()), std::make_move_iterator(args.end()) + } + ); + } + +private: + void parse_inputs(std::deque&& src) { + while (!src.empty()) + inputs.emplace_back(parse_input(src)); + } + + Input parse_input(std::deque& src) const { + std::string key{std::move(src.front())}; + src.pop_front(); + + std::string iv; + + if (aes::mode_requires_init_vector(mode)) { + if (src.empty()) { + throw boost::program_options::error{ + "an initialization vector is required for the selected mode of operation" + }; + } + iv = std::move(src.front()); + src.pop_front(); + } + + auto blocks = parse_blocks(src); + + if (aes::mode_requires_init_vector(mode)) + return {key, iv, std::move(blocks)}; + else + return {key, std::move(blocks)}; + } + + static std::vector parse_blocks(std::deque& src) { + std::vector blocks; + + while (!src.empty()) { + std::string block{std::move(src.front())}; + src.pop_front(); + if (block == "--") + break; + blocks.emplace_back(std::move(block)); + } + + return blocks; + } + + std::vector args; +}; diff --git a/aesxx/utils/helpers/cmd_parser_file.hpp b/aesxx/utils/helpers/cmd_parser_file.hpp new file mode 100644 index 0000000..fd6072a --- /dev/null +++ b/aesxx/utils/helpers/cmd_parser_file.hpp @@ -0,0 +1,82 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include "cmd_parser.hpp" +#include "data_parsers.hpp" + +#include + +#include + +#include +#include +#include +#include + +class FileSettings : public SettingsParser { +public: + aes::Algorithm algorithm = AES_AES128; + aes::Mode mode = AES_ECB; + + std::string input_path; + std::string output_path; + std::string key; + std::string iv; + + explicit FileSettings(std::string_view argv0) : SettingsParser{argv0} { + visible.add_options()( + "algorithm,a", + boost::program_options::value(&algorithm) + ->required() + ->value_name("NAME"), + "set algorithm" + ); + visible.add_options()( + "mode,m", + boost::program_options::value(&mode)->required()->value_name("MODE"), + "set mode of operation" + ); + visible.add_options()( + "key,k", + boost::program_options::value(&key)->required()->value_name("KEY"), + "set encryption key" + ); + visible.add_options()( + "iv,v", + boost::program_options::value(&iv)->value_name("BLOCK"), + "set initialization vector" + ); + visible.add_options()( + "input,i", + boost::program_options::value(&input_path)->required()->value_name("PATH"), + "set input file path" + ); + visible.add_options()( + "output,o", + boost::program_options::value(&output_path) + ->required() + ->value_name("PATH"), + "set output file path" + ); + } + + const char* get_short_description() const override { + return "[-h|--help] [-a|--algorithm NAME] [-m|--mode MODE]" + " [-k|--key KEY] [-v|--iv BLOCK]" + " [-i|--input PATH] [-o|--output PATH]"; + } + + void parse(int argc, char** argv) override { + SettingsParser::parse(argc, argv); + + if (aes::mode_requires_init_vector(mode) && iv.empty()) { + throw boost::program_options::error{ + "an initialization vector is required for the selected mode of operation" + }; + } + } +}; diff --git a/aesxx/utils/helpers/command_line.hpp b/aesxx/utils/helpers/command_line.hpp deleted file mode 100644 index 607253c..0000000 --- a/aesxx/utils/helpers/command_line.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2017 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include - -#include -#include -#include -#include -#include -#include -#include - -class SettingsParser { -public: - explicit SettingsParser(std::string_view argv0) : prog_name{extract_filename(argv0)} { - visible.add_options()("help,h", "show this message and exit"); - } - - virtual ~SettingsParser() = default; - - virtual const char* get_short_description() const { - return "[--option VALUE]..."; - } - - virtual void parse(int argc, char* argv[]) { - boost::program_options::options_description all; - all.add(hidden).add(visible); - boost::program_options::variables_map vm; - boost::program_options::store( - boost::program_options::command_line_parser{argc, argv} - .options(all) - .positional(positional) - .run(), - vm - ); - if (vm.count("help")) - exit_with_usage = true; - else - boost::program_options::notify(vm); - } - - bool exit_with_usage = false; - - void usage() const { - std::cout << *this; - } - - void usage_error(const std::exception& e) const { - std::cerr << std::format("usage error: {}\n", e.what()); - std::cerr << *this; - } - -protected: - boost::program_options::options_description hidden; - boost::program_options::options_description visible; - boost::program_options::positional_options_description positional; - -private: - static std::string extract_filename(std::string_view path) { - return std::filesystem::path{path}.filename().string(); - } - - const std::string prog_name; - - friend std::ostream& operator<<(std::ostream& os, const SettingsParser& parser) { - const auto short_descr = parser.get_short_description(); - os << std::format("usage: {} {}\n", parser.prog_name, short_descr); - os << parser.visible; - return os; - } -}; diff --git a/aesxx/utils/helpers/data_parsers.hpp b/aesxx/utils/helpers/data_parsers.hpp new file mode 100644 index 0000000..a08f1bf --- /dev/null +++ b/aesxx/utils/helpers/data_parsers.hpp @@ -0,0 +1,55 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include + +#include +#include + +#include +#include +#include + +inline std::istream& operator>>(std::istream& is, aes::Mode& dest) { + std::string src; + is >> src; + + static const std::unordered_map lookup_table = { + {"ecb", AES_ECB}, + {"cbc", AES_CBC}, + {"cfb", AES_CFB}, + {"ofb", AES_OFB}, + {"ctr", AES_CTR}, + }; + + const auto it = lookup_table.find(boost::algorithm::to_lower_copy(src)); + + if (it == lookup_table.cend()) + throw boost::program_options::invalid_option_value(src); + + dest = it->second; + return is; +} + +inline std::istream& operator>>(std::istream& is, aes::Algorithm& dest) { + std::string src; + is >> src; + + static const std::unordered_map lookup_table = { + {"aes128", AES_AES128}, + {"aes192", AES_AES192}, + {"aes256", AES_AES256}, + }; + + const auto it = lookup_table.find(boost::algorithm::to_lower_copy(src)); + + if (it == lookup_table.cend()) + throw boost::program_options::invalid_option_value(src); + + dest = it->second; + return is; +} -- cgit v1.3