From 1db94ae5d2201edb5f9421c2c30be049efc678f6 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Sun, 27 Dec 2015 12:56:13 +0300 Subject: utils: refactor command line parsing --- utils/block_cmd_parser.hpp | 143 ++++++++++++++++++++++++++++++++++++++++----- utils/decrypt_block.cpp | 118 +++++++++++++------------------------ utils/decrypt_bmp.cpp | 78 ++++++++++--------------- utils/decrypt_file.cpp | 62 ++++++++------------ utils/encrypt_block.cpp | 118 +++++++++++++------------------------ utils/encrypt_bmp.cpp | 78 ++++++++++--------------- utils/encrypt_file.cpp | 70 +++++++++------------- utils/file_cmd_parser.hpp | 96 +++++++++++++++--------------- 8 files changed, 371 insertions(+), 392 deletions(-) (limited to 'utils') diff --git a/utils/block_cmd_parser.hpp b/utils/block_cmd_parser.hpp index 3468d58..988ef52 100644 --- a/utils/block_cmd_parser.hpp +++ b/utils/block_cmd_parser.hpp @@ -16,8 +16,11 @@ #include #include +#include +#include #include #include +#include #include namespace @@ -40,26 +43,87 @@ namespace "the selected mode of operation is not implemented"); } + class CommandLineParser; + + class Input + { + public: + Input( + std::string&& key_string, + std::string&& iv_string, + std::vector&& input_block_strings) + : key_string(std::move(key_string)) + , iv_string(std::make_pair(true, std::move(iv_string))) + , input_block_strings(input_block_strings) + { } + + Input( + std::string&& key_string, + std::vector&& input_block_strings) + : key_string(std::move(key_string)) + , iv_string(std::make_pair(false, std::string())) + , input_block_strings(std::move(input_block_strings)) + { } + + const std::string& get_key_string() const { return key_string; } + + const std::string& get_iv_string() const + { + if (!iv_string.first) + throw_iv_required(); + return iv_string.second; + } + + const std::vector& get_input_block_strings() const + { + return input_block_strings; + } + + private: + const std::string key_string; + const std::pair iv_string; + const std::vector input_block_strings; + }; + + class Settings + { + public: + aesni::Algorithm get_algorithm() const { return algorithm; } + aesni::Mode get_mode() const { return mode; } + + bool use_boxes() const { return use_boxes_flag; } + bool verbose() const { return verbose_flag; } + + private: + aesni::Algorithm algorithm; + aesni::Mode mode; + + bool use_boxes_flag = false; + bool verbose_flag = false; + + friend class CommandLineParser; + }; + class CommandLineParser { public: CommandLineParser(const std::string& argv0) : prog_name(boost::filesystem::path(argv0).filename().string()) , options("Options") + { } + + void parse(Settings& settings, int argc, char** argv, std::vector& inputs) { namespace po = boost::program_options; options.add_options() ("help,h", "show this message and exit") - ("box,b", po::bool_switch(&use_boxes)->default_value(false), "use the \"boxes\" interface") - ("mode,m", po::value(&mode)->required(), "set mode of operation") - ("algorithm,a", po::value(&algorithm)->required(), "set algorithm") - ("verbose,v", po::bool_switch(&verbose)->default_value(false), "enable verbose output"); - } + ("box,b", po::bool_switch(&settings.use_boxes_flag)->default_value(false), "use the \"boxes\" interface") + ("mode,m", po::value(&settings.mode)->required(), "set mode of operation") + ("algorithm,a", po::value(&settings.algorithm)->required(), "set algorithm") + ("verbose,v", po::bool_switch(&settings.verbose_flag)->default_value(false), "enable verbose output"); - void parse(int argc, char** argv) - { - namespace po = boost::program_options; + std::vector args; po::options_description hidden_options; hidden_options.add_options() @@ -84,17 +148,66 @@ namespace } po::notify(vm); + + parse_inputs(settings, inputs, std::deque( + std::make_move_iterator(args.begin()), + std::make_move_iterator(args.end()) + )); } - bool requested_help() const { return help_flag; } - - aesni::Mode mode; - aesni::Algorithm algorithm; - bool use_boxes; - std::vector args; - bool verbose; + bool exit_with_usage() const { return help_flag; } private: + static void parse_inputs( + const Settings& settings, + std::vector& inputs, + std::deque&& args) + { + while (!args.empty()) + { + auto key_string = std::move(args.front()); + args.pop_front(); + + std::string iv_string; + + if (aesni::mode_requires_initialization_vector(settings.get_mode())) + { + if (args.empty()) + throw_iv_required(); + iv_string = std::move(args.front()); + args.pop_front(); + } + + std::vector input_block_strings; + + while (!args.empty()) + { + if (args.front() == "--") + { + args.pop_front(); + break; + } + + input_block_strings.emplace_back(std::move(args.front())); + args.pop_front(); + } + + if (aesni::mode_requires_initialization_vector(settings.get_mode())) + { + inputs.emplace_back( + std::move(key_string), + std::move(iv_string), + std::move(input_block_strings)); + } + else + { + inputs.emplace_back( + std::move(key_string), + std::move(input_block_strings)); + } + } + } + const std::string prog_name; boost::program_options::options_description options; diff --git a/utils/decrypt_block.cpp b/utils/decrypt_block.cpp index 30409e0..a8c9625 100644 --- a/utils/decrypt_block.cpp +++ b/utils/decrypt_block.cpp @@ -13,7 +13,6 @@ #include -#include #include #include #include @@ -23,40 +22,31 @@ namespace { template void decrypt_with_mode( - const std::string& key_str, - std::deque& ciphertexts, + const Input& input, bool verbose = false) { typename aesni::Types::Block iv; if (aesni::ModeRequiresInitializationVector()) { - if (ciphertexts.empty()) - throw_iv_required(); - - aesni::from_string(iv, ciphertexts.front()); - ciphertexts.pop_front(); - + aesni::from_string(iv, input.get_iv_string()); if (verbose) dump_iv(iv); } typename aesni::Types::Key key; - aesni::from_string(key, key_str); - + aesni::from_string(key, input.get_key_string()); if (verbose) dump_key(key); aesni::DecryptWrapper decrypt(key, iv); - if (verbose) dump_wrapper(decrypt); - while (!ciphertexts.empty()) + for (const auto& input_block_string : input.get_input_block_strings()) { typename aesni::Types::Block ciphertext, plaintext; - aesni::from_string(ciphertext, ciphertexts.front()); - ciphertexts.pop_front(); + aesni::from_string(ciphertext, input_block_string); decrypt.decrypt_block(ciphertext, plaintext); @@ -68,7 +58,7 @@ namespace } else { - std::cout << aesni::to_string(plaintext) << "\n"; + std::cout << aesni::to_string(plaintext) << '\n'; } } } @@ -76,30 +66,29 @@ namespace template void decrypt_with_algorithm( aesni::Mode mode, - const std::string& key_str, - std::deque& ciphertexts, + const Input& input, bool verbose = false) { switch (mode) { case AESNI_ECB: - decrypt_with_mode(key_str, ciphertexts, verbose); + decrypt_with_mode(input, verbose); break; case AESNI_CBC: - decrypt_with_mode(key_str, ciphertexts, verbose); + decrypt_with_mode(input, verbose); break; case AESNI_CFB: - decrypt_with_mode(key_str, ciphertexts, verbose); + decrypt_with_mode(input, verbose); break; case AESNI_OFB: - decrypt_with_mode(key_str, ciphertexts, verbose); + decrypt_with_mode(input, verbose); break; case AESNI_CTR: - decrypt_with_mode(key_str, ciphertexts, verbose); + decrypt_with_mode(input, verbose); break; default: @@ -111,22 +100,21 @@ namespace void decrypt_using_cxx_api( aesni::Algorithm algorithm, aesni::Mode mode, - const std::string& key_str, - std::deque& ciphertexts, + const Input& input, bool verbose = false) { switch (algorithm) { case AESNI_AES128: - decrypt_with_algorithm(mode, key_str, ciphertexts, verbose); + decrypt_with_algorithm(mode, input, verbose); break; case AESNI_AES192: - decrypt_with_algorithm(mode, key_str, ciphertexts, verbose); + decrypt_with_algorithm(mode, input, verbose); break; case AESNI_AES256: - decrypt_with_algorithm(mode, key_str, ciphertexts, verbose); + decrypt_with_algorithm(mode, input, verbose); break; default: @@ -137,46 +125,41 @@ namespace void decrypt_using_particular_box( aesni::Box& box, - std::deque& ciphertexts) + const std::vector& input_block_strings) { - while (!ciphertexts.empty()) + for (const auto& input_block_string : input_block_strings) { aesni::Box::Block ciphertext; - box.parse_block(ciphertext, ciphertexts.front()); - ciphertexts.pop_front(); + box.parse_block(ciphertext, input_block_string); aesni::Box::Block plaintext; box.decrypt_block(ciphertext, plaintext); - - std::cout << box.format_block(plaintext) << "\n"; + std::cout << box.format_block(plaintext) << '\n'; } } void decrypt_using_boxes( aesni::Algorithm algorithm, aesni::Mode mode, - const std::string& key_str, - std::deque& ciphertexts) + const Input& input) { aesni::Box::Key key; - aesni::Box::parse_key(key, algorithm, key_str); + aesni::Box::parse_key(key, algorithm, input.get_key_string()); if (aesni::mode_requires_initialization_vector(mode)) { - if (ciphertexts.empty()) - throw_iv_required(); - aesni::Box::Block iv; - aesni::Box::parse_block(iv, algorithm, ciphertexts.front()); - ciphertexts.pop_front(); + aesni::Box::parse_block(iv, algorithm, input.get_iv_string()); decrypt_using_particular_box( - aesni::Box(algorithm, key, mode, iv), ciphertexts); + aesni::Box(algorithm, key, mode, iv), + input.get_input_block_strings()); } else { decrypt_using_particular_box( - aesni::Box(algorithm, key), ciphertexts); + aesni::Box(algorithm, key), + input.get_input_block_strings()); } } } @@ -188,53 +171,32 @@ int main(int argc, char** argv) CommandLineParser cmd_parser(argv[0]); try { - cmd_parser.parse(argc, argv); + Settings settings; + std::vector inputs; + cmd_parser.parse(settings, argc, argv, inputs); - if (cmd_parser.requested_help()) + if (cmd_parser.exit_with_usage()) { std::cout << cmd_parser; return 0; } - std::deque args( - std::make_move_iterator(cmd_parser.args.begin()), - std::make_move_iterator(cmd_parser.args.end())); - - while (!args.empty()) + for (const auto& input : inputs) { - const auto key = args.front(); - args.pop_front(); - - std::deque ciphertexts; - - while (!args.empty()) - { - if (args.front() == "--") - { - args.pop_front(); - break; - } - - ciphertexts.push_back(args.front()); - args.pop_front(); - } - - if (cmd_parser.use_boxes) + if (settings.use_boxes()) { decrypt_using_boxes( - cmd_parser.algorithm, - cmd_parser.mode, - key, - ciphertexts); + settings.get_algorithm(), + settings.get_mode(), + input); } else { decrypt_using_cxx_api( - cmd_parser.algorithm, - cmd_parser.mode, - key, - ciphertexts, - cmd_parser.verbose); + settings.get_algorithm(), + settings.get_mode(), + input, + settings.verbose()); } } diff --git a/utils/decrypt_bmp.cpp b/utils/decrypt_bmp.cpp index a326828..e63155d 100644 --- a/utils/decrypt_bmp.cpp +++ b/utils/decrypt_bmp.cpp @@ -15,7 +15,6 @@ #include #include -#include #include #include #include @@ -43,12 +42,12 @@ namespace ifs.exceptions(std::ifstream::badbit | std::ifstream::failbit); ifs.open(path, std::ifstream::binary); - std::vector src_buf; - src_buf.reserve(size); - src_buf.assign( + std::vector ciphertext_buf; + ciphertext_buf.reserve(size); + ciphertext_buf.assign( std::istreambuf_iterator(ifs), std::istreambuf_iterator()); - return src_buf; + return ciphertext_buf; } void write_file( @@ -63,64 +62,54 @@ namespace void decrypt_bmp( aesni::Box& box, - std::deque& args) + const std::string& ciphertext_path, + const std::string& plaintext_path) { - if (args.empty()) - throw_src_path_required(); - const auto src_path = args.front(); - args.pop_front(); + const auto ciphertext_buf = read_file(ciphertext_path); - if (args.empty()) - throw_dest_path_required(); - const auto dest_path = args.front(); - args.pop_front(); - - const auto src_buf = read_file(src_path); - - const auto bmp_header = reinterpret_cast(src_buf.data()); + const auto bmp_header = reinterpret_cast(ciphertext_buf.data()); const auto header_size = bmp_header->bfOffBits; - const auto cipherpixels = src_buf.data() + header_size; - const auto cipherpixels_size = src_buf.size() - header_size; + const auto cipherpixels = ciphertext_buf.data() + header_size; + const auto cipherpixels_size = ciphertext_buf.size() - header_size; const auto pixels = box.decrypt_buffer( cipherpixels, cipherpixels_size); - std::vector dest_buf(header_size + pixels.size()); - std::memcpy(&dest_buf[0], bmp_header, header_size); - std::memcpy(&dest_buf[0] + header_size, pixels.data(), pixels.size()); + std::vector plaintext_buf(header_size + pixels.size()); + std::memcpy(plaintext_buf.data(), bmp_header, header_size); + std::memcpy(plaintext_buf.data() + header_size, pixels.data(), pixels.size()); - write_file(dest_path, dest_buf); + write_file(plaintext_path, plaintext_buf); } - void decrypt_bmp( - aesni::Algorithm algorithm, - aesni::Mode mode, - std::deque& args) + void decrypt_bmp(const Settings& settings) { - if (args.empty()) - throw_key_required(); + const auto algorithm = settings.get_algorithm(); + const auto mode = settings.get_mode(); + + const auto ciphertext_path = settings.get_input_path(); + const auto plaintext_path = settings.get_output_path(); aesni::Box::Key key; - aesni::Box::parse_key(key, algorithm, args.front()); - args.pop_front(); + aesni::Box::parse_key(key, algorithm, settings.get_key_string()); if (aesni::mode_requires_initialization_vector(mode)) { - if (args.empty()) - throw_iv_required(); - aesni::Box::Block iv; - aesni::Box::parse_block(iv, algorithm, args.front()); - args.pop_front(); + aesni::Box::parse_block(iv, algorithm, settings.get_iv_string()); decrypt_bmp( - aesni::Box(algorithm, key, mode, iv), args); + aesni::Box(algorithm, key, mode, iv), + ciphertext_path, + plaintext_path); } else { decrypt_bmp( - aesni::Box(algorithm, key), args); + aesni::Box(algorithm, key), + ciphertext_path, + plaintext_path); } } } @@ -132,19 +121,16 @@ int main(int argc, char** argv) CommandLineParser cmd_parser(argv[0]); try { - cmd_parser.parse(argc, argv); + Settings settings; + cmd_parser.parse(settings, argc, argv); - if (cmd_parser.requested_help()) + if (cmd_parser.exit_with_usage()) { std::cout << cmd_parser; return 0; } - std::deque args( - std::make_move_iterator(cmd_parser.args.begin()), - std::make_move_iterator(cmd_parser.args.end())); - - decrypt_bmp(cmd_parser.algorithm, cmd_parser.mode, args); + decrypt_bmp(settings); } catch (const boost::program_options::error& e) { diff --git a/utils/decrypt_file.cpp b/utils/decrypt_file.cpp index 96aec62..2264926 100644 --- a/utils/decrypt_file.cpp +++ b/utils/decrypt_file.cpp @@ -14,7 +14,6 @@ #include -#include #include #include #include @@ -60,52 +59,42 @@ namespace void decrypt_file( aesni::Box& box, - std::deque& args) + const std::string& ciphertext_path, + const std::string& plaintext_path) { - if (args.empty()) - throw_src_path_required(); - const auto src_path = args.front(); - args.pop_front(); - - if (args.empty()) - throw_dest_path_required(); - const auto dest_path = args.front(); - args.pop_front(); - - const auto src_buf = read_file(src_path); - const auto dest_buf = box.decrypt_buffer( - src_buf.data(), src_buf.size()); - write_file(dest_path, dest_buf); + const auto ciphertext_buf = read_file(ciphertext_path); + const auto plaintext_buf = box.decrypt_buffer( + ciphertext_buf.data(), ciphertext_buf.size()); + write_file(plaintext_path, plaintext_buf); } - void decrypt_file( - aesni::Algorithm algorithm, - aesni::Mode mode, - std::deque& args) + void decrypt_file(const Settings& settings) { - if (args.empty()) - throw_key_required(); + const auto algorithm = settings.get_algorithm(); + const auto mode = settings.get_mode(); + + const auto ciphertext_path = settings.get_input_path(); + const auto plaintext_path = settings.get_output_path(); aesni::Box::Key key; - aesni::Box::parse_key(key, algorithm, args.front()); - args.pop_front(); + aesni::Box::parse_key(key, algorithm, settings.get_key_string()); if (aesni::mode_requires_initialization_vector(mode)) { - if (args.empty()) - throw_iv_required(); - aesni::Box::Block iv; - aesni::Box::parse_block(iv, algorithm, args.front()); - args.pop_front(); + aesni::Box::parse_block(iv, algorithm, settings.get_iv_string()); decrypt_file( - aesni::Box(algorithm, key, mode, iv), args); + aesni::Box(algorithm, key, mode, iv), + ciphertext_path, + plaintext_path); } else { decrypt_file( - aesni::Box(algorithm, key), args); + aesni::Box(algorithm, key), + ciphertext_path, + plaintext_path); } } } @@ -117,19 +106,16 @@ int main(int argc, char** argv) CommandLineParser cmd_parser(argv[0]); try { - cmd_parser.parse(argc, argv); + Settings settings; + cmd_parser.parse(settings, argc, argv); - if (cmd_parser.requested_help()) + if (cmd_parser.exit_with_usage()) { std::cout << cmd_parser; return 0; } - std::deque args( - std::make_move_iterator(cmd_parser.args.begin()), - std::make_move_iterator(cmd_parser.args.end())); - - decrypt_file(cmd_parser.algorithm, cmd_parser.mode, args); + decrypt_file(settings); } catch (const boost::program_options::error& e) { diff --git a/utils/encrypt_block.cpp b/utils/encrypt_block.cpp index 022c237..724e8c1 100644 --- a/utils/encrypt_block.cpp +++ b/utils/encrypt_block.cpp @@ -13,7 +13,6 @@ #include -#include #include #include #include @@ -23,40 +22,32 @@ namespace { template void encrypt_with_mode( - const std::string& key_str, - std::deque& plaintexts, + const Input& input, bool verbose = false) { typename aesni::Types::Block iv; if (aesni::ModeRequiresInitializationVector::value) { - if (plaintexts.empty()) - throw_iv_required(); - - aesni::from_string(iv, plaintexts.front()); - plaintexts.pop_front(); - + aesni::from_string(iv, input.get_iv_string()); if (verbose) dump_iv(iv); } typename aesni::Types::Key key; - aesni::from_string(key, key_str); - + aesni::from_string(key, input.get_key_string()); if (verbose) dump_key(key); aesni::EncryptWrapper encrypt(key, iv); - if (verbose) dump_wrapper(encrypt); - while (!plaintexts.empty()) + for (const auto& input_block_string : input.get_input_block_strings()) { typename aesni::Types::Block plaintext, ciphertext; - aesni::from_string(plaintext, plaintexts.front()); - plaintexts.pop_front(); + aesni::from_string(plaintext, input_block_string); + encrypt.encrypt_block(plaintext, ciphertext); if (verbose) @@ -67,7 +58,7 @@ namespace } else { - std::cout << aesni::to_string(ciphertext) << "\n"; + std::cout << aesni::to_string(ciphertext) << '\n'; } } } @@ -75,30 +66,29 @@ namespace template void encrypt_with_algorithm( aesni::Mode mode, - const std::string& key_str, - std::deque& plaintexts, + const Input& input, bool verbose = false) { switch (mode) { case AESNI_ECB: - encrypt_with_mode(key_str, plaintexts, verbose); + encrypt_with_mode(input, verbose); break; case AESNI_CBC: - encrypt_with_mode(key_str, plaintexts, verbose); + encrypt_with_mode(input, verbose); break; case AESNI_CFB: - encrypt_with_mode(key_str, plaintexts, verbose); + encrypt_with_mode(input, verbose); break; case AESNI_OFB: - encrypt_with_mode(key_str, plaintexts, verbose); + encrypt_with_mode(input, verbose); break; case AESNI_CTR: - encrypt_with_mode(key_str, plaintexts, verbose); + encrypt_with_mode(input, verbose); break; default: @@ -110,22 +100,21 @@ namespace void encrypt_using_cxx_api( aesni::Algorithm algorithm, aesni::Mode mode, - const std::string& key_str, - std::deque& plaintexts, + const Input& input, bool verbose = false) { switch (algorithm) { case AESNI_AES128: - encrypt_with_algorithm(mode, key_str, plaintexts, verbose); + encrypt_with_algorithm(mode, input, verbose); break; case AESNI_AES192: - encrypt_with_algorithm(mode, key_str, plaintexts, verbose); + encrypt_with_algorithm(mode, input, verbose); break; case AESNI_AES256: - encrypt_with_algorithm(mode, key_str, plaintexts, verbose); + encrypt_with_algorithm(mode, input, verbose); break; default: @@ -136,47 +125,39 @@ namespace void encrypt_using_particular_box( aesni::Box& box, - std::deque& plaintexts) + const std::vector& input_block_strings) { - while (!plaintexts.empty()) + for (const auto& input_block_string : input_block_strings) { aesni::Box::Block plaintext; - box.parse_block( - plaintext, plaintexts.front()); - plaintexts.pop_front(); + box.parse_block(plaintext, input_block_string); aesni::Box::Block ciphertext; box.encrypt_block(plaintext, ciphertext); - - std::cout << box.format_block(ciphertext) << "\n"; + std::cout << box.format_block(ciphertext) << '\n'; } } void encrypt_using_boxes( aesni::Algorithm algorithm, aesni::Mode mode, - const std::string& key_str, - std::deque& plaintexts) + const Input& input) { aesni::Box::Key key; - aesni::Box::parse_key(key, algorithm, key_str); + aesni::Box::parse_key(key, algorithm, input.get_key_string()); if (aesni::mode_requires_initialization_vector(mode)) { - if (plaintexts.empty()) - throw_iv_required(); - aesni::Box::Block iv; - aesni::Box::parse_block(iv, algorithm, plaintexts.front()); - plaintexts.pop_front(); + aesni::Box::parse_block(iv, algorithm, input.get_iv_string()); encrypt_using_particular_box( - aesni::Box(algorithm, key, mode, iv), plaintexts); + aesni::Box(algorithm, key, mode, iv), input.get_input_block_strings()); } else { encrypt_using_particular_box( - aesni::Box(algorithm, key), plaintexts); + aesni::Box(algorithm, key), input.get_input_block_strings()); } } } @@ -188,53 +169,32 @@ int main(int argc, char** argv) CommandLineParser cmd_parser(argv[0]); try { - cmd_parser.parse(argc, argv); + std::vector inputs; + Settings settings; + cmd_parser.parse(settings, argc, argv, inputs); - if (cmd_parser.requested_help()) + if (cmd_parser.exit_with_usage()) { std::cout << cmd_parser; return 0; } - std::deque args( - std::make_move_iterator(cmd_parser.args.begin()), - std::make_move_iterator(cmd_parser.args.end())); - - while (!args.empty()) + for (const auto& input : inputs) { - const auto key = args.front(); - args.pop_front(); - - std::deque plaintexts; - - while (!args.empty()) - { - if (args.front() == "--") - { - args.pop_front(); - break; - } - - plaintexts.push_back(args.front()); - args.pop_front(); - } - - if (cmd_parser.use_boxes) + if (settings.use_boxes()) { encrypt_using_boxes( - cmd_parser.algorithm, - cmd_parser.mode, - key, - plaintexts); + settings.get_algorithm(), + settings.get_mode(), + input); } else { encrypt_using_cxx_api( - cmd_parser.algorithm, - cmd_parser.mode, - key, - plaintexts, - cmd_parser.verbose); + settings.get_algorithm(), + settings.get_mode(), + input, + settings.verbose()); } } diff --git a/utils/encrypt_bmp.cpp b/utils/encrypt_bmp.cpp index 2f019d8..3ac5906 100644 --- a/utils/encrypt_bmp.cpp +++ b/utils/encrypt_bmp.cpp @@ -15,7 +15,6 @@ #include #include -#include #include #include #include @@ -43,12 +42,12 @@ namespace ifs.exceptions(std::ifstream::badbit | std::ifstream::failbit); ifs.open(path, std::ifstream::binary); - std::vector src_buf; - src_buf.reserve(size); - src_buf.assign( + std::vector plaintext_buf; + plaintext_buf.reserve(size); + plaintext_buf.assign( std::istreambuf_iterator(ifs), std::istreambuf_iterator()); - return src_buf; + return plaintext_buf; } void write_file( @@ -63,64 +62,54 @@ namespace void encrypt_bmp( aesni::Box& box, - std::deque& args) + const std::string& plaintext_path, + const std::string& ciphertext_path) { - if (args.empty()) - throw_src_path_required(); - const auto src_path = args.front(); - args.pop_front(); + const auto plaintext_buf = read_file(plaintext_path); - if (args.empty()) - throw_dest_path_required(); - const auto dest_path = args.front(); - args.pop_front(); - - const auto src_buf = read_file(src_path); - - const auto bmp_header = reinterpret_cast(src_buf.data()); + const auto bmp_header = reinterpret_cast(plaintext_buf.data()); const auto header_size = bmp_header->bfOffBits; - const auto pixels = src_buf.data() + header_size; - const auto pixels_size = src_buf.size() - header_size; + const auto pixels = plaintext_buf.data() + header_size; + const auto pixels_size = plaintext_buf.size() - header_size; const auto cipherpixels = box.encrypt_buffer( pixels, pixels_size); - std::vector dest_buf(header_size + cipherpixels.size()); - std::memcpy(&dest_buf[0], bmp_header, header_size); - std::memcpy(&dest_buf[0] + header_size, cipherpixels.data(), cipherpixels.size()); + std::vector ciphertext_buf(header_size + cipherpixels.size()); + std::memcpy(ciphertext_buf.data(), bmp_header, header_size); + std::memcpy(ciphertext_buf.data() + header_size, cipherpixels.data(), cipherpixels.size()); - write_file(dest_path, dest_buf); + write_file(ciphertext_path, ciphertext_buf); } - void encrypt_bmp( - aesni::Algorithm algorithm, - aesni::Mode mode, - std::deque& args) + void encrypt_bmp(const Settings& settings) { - if (args.empty()) - throw_key_required(); + const auto algorithm = settings.get_algorithm(); + const auto mode = settings.get_mode(); + + const auto plaintext_path = settings.get_input_path(); + const auto ciphertext_path = settings.get_output_path(); aesni::Box::Key key; - aesni::Box::parse_key(key, algorithm, args.front()); - args.pop_front(); + aesni::Box::parse_key(key, algorithm, settings.get_key_string()); if (aesni::mode_requires_initialization_vector(mode)) { - if (args.empty()) - throw_iv_required(); - aesni::Box::Block iv; - aesni::Box::parse_block(iv, algorithm, args.front()); - args.pop_front(); + aesni::Box::parse_block(iv, algorithm, settings.get_iv_string()); encrypt_bmp( - aesni::Box(algorithm, key, mode, iv), args); + aesni::Box(algorithm, key, mode, iv), + plaintext_path, + ciphertext_path); } else { encrypt_bmp( - aesni::Box(algorithm, key), args); + aesni::Box(algorithm, key), + plaintext_path, + ciphertext_path); } } } @@ -132,19 +121,16 @@ int main(int argc, char** argv) CommandLineParser cmd_parser(argv[0]); try { - cmd_parser.parse(argc, argv); + Settings settings; + cmd_parser.parse(settings, argc, argv); - if (cmd_parser.requested_help()) + if (cmd_parser.exit_with_usage()) { std::cout << cmd_parser; return 0; } - std::deque args( - std::make_move_iterator(cmd_parser.args.begin()), - std::make_move_iterator(cmd_parser.args.end())); - - encrypt_bmp(cmd_parser.algorithm, cmd_parser.mode, args); + encrypt_bmp(settings); } catch (const boost::program_options::error& e) { diff --git a/utils/encrypt_file.cpp b/utils/encrypt_file.cpp index d1dd5e8..4651928 100644 --- a/utils/encrypt_file.cpp +++ b/utils/encrypt_file.cpp @@ -14,7 +14,6 @@ #include -#include #include #include #include @@ -40,12 +39,12 @@ namespace ifs.exceptions(std::ifstream::badbit | std::ifstream::failbit); ifs.open(path, std::ifstream::binary); - std::vector src_buf; - src_buf.reserve(size); - src_buf.assign( + std::vector plaintext_buf; + plaintext_buf.reserve(size); + plaintext_buf.assign( std::istreambuf_iterator(ifs), std::istreambuf_iterator()); - return src_buf; + return plaintext_buf; } void write_file( @@ -60,52 +59,42 @@ namespace void encrypt_file( aesni::Box& box, - std::deque& args) + const std::string& plaintext_path, + const std::string& ciphertext_path) { - if (args.empty()) - throw_src_path_required(); - const auto src_path = args.front(); - args.pop_front(); - - if (args.empty()) - throw_dest_path_required(); - const auto dest_path = args.front(); - args.pop_front(); - - const auto src_buf = read_file(src_path); - const auto dest_buf = box.encrypt_buffer( - src_buf.data(), src_buf.size()); - write_file(dest_path, dest_buf); + const auto plaintext_buf = read_file(plaintext_path); + const auto ciphertext_buf = box.encrypt_buffer( + plaintext_buf.data(), plaintext_buf.size()); + write_file(ciphertext_path, ciphertext_buf); } - void encrypt_file( - aesni::Algorithm algorithm, - aesni::Mode mode, - std::deque& args) + void encrypt_file(const Settings& settings) { - if (args.empty()) - throw_key_required(); + const auto algorithm = settings.get_algorithm(); + const auto mode = settings.get_mode(); + + const auto plaintext_path = settings.get_input_path(); + const auto ciphertext_path = settings.get_output_path(); aesni::Box::Key key; - aesni::Box::parse_key(key, algorithm, args.front()); - args.pop_front(); + aesni::Box::parse_key(key, algorithm, settings.get_key_string()); if (aesni::mode_requires_initialization_vector(mode)) { - if (args.empty()) - throw_iv_required(); - aesni::Box::Block iv; - aesni::Box::parse_block(iv, algorithm, args.front()); - args.pop_front(); + aesni::Box::parse_block(iv, algorithm, settings.get_iv_string()); encrypt_file( - aesni::Box(algorithm, key, mode, iv), args); + aesni::Box(algorithm, key, mode, iv), + plaintext_path, + ciphertext_path); } else { encrypt_file( - aesni::Box(algorithm, key), args); + aesni::Box(algorithm, key), + plaintext_path, + ciphertext_path); } } } @@ -117,19 +106,16 @@ int main(int argc, char** argv) CommandLineParser cmd_parser(argv[0]); try { - cmd_parser.parse(argc, argv); + Settings settings; + cmd_parser.parse(settings, argc, argv); - if (cmd_parser.requested_help()) + if (cmd_parser.exit_with_usage()) { std::cout << cmd_parser; return 0; } - std::deque args( - std::make_move_iterator(cmd_parser.args.begin()), - std::make_move_iterator(cmd_parser.args.end())); - - encrypt_file(cmd_parser.algorithm, cmd_parser.mode, args); + encrypt_file(settings); } catch (const boost::program_options::error& e) { diff --git a/utils/file_cmd_parser.hpp b/utils/file_cmd_parser.hpp index cf5d188..7d1470d 100644 --- a/utils/file_cmd_parser.hpp +++ b/utils/file_cmd_parser.hpp @@ -12,39 +12,51 @@ #include -#include #include #include #include #include -#include +#include namespace { - BOOST_NORETURN inline void throw_key_required() - { - throw boost::program_options::error( - "a key is required but not specified"); - } + class CommandLineParser; - BOOST_NORETURN inline void throw_iv_required() + class Settings { - throw boost::program_options::error( - "initialization vector is required for the selected mode of operation"); - } + public: + Settings() + : iv(false, std::string()) + { } - BOOST_NORETURN inline void throw_src_path_required() - { - throw boost::program_options::error( - "please, specify source file path"); - } + aesni::Mode get_mode() const { return mode; } + aesni::Algorithm get_algorithm() const { return algorithm; } - BOOST_NORETURN inline void throw_dest_path_required() - { - throw boost::program_options::error( - "please, specify destination file path"); - } + std::string get_input_path() const { return input_path; } + std::string get_output_path() const { return output_path; } + + std::string get_key_string() const { return key; } + + std::string get_iv_string() const + { + if (!iv.first) + throw boost::program_options::error("initialization vector is required for the selected mode of operation"); + return iv.second; + } + + private: + aesni::Mode mode; + aesni::Algorithm algorithm; + + std::string input_path; + std::string output_path; + std::string key; + + std::pair iv; + + friend class CommandLineParser; + }; class CommandLineParser { @@ -52,34 +64,23 @@ namespace CommandLineParser(const std::string& argv0) : prog_name(boost::filesystem::path(argv0).filename().string()) , options("Options") + { } + + void parse(Settings& settings, int argc, char** argv) { namespace po = boost::program_options; options.add_options() ("help,h", "show this message and exit") - ("mode,m", po::value(&mode)->required(), "set mode of operation") - ("algorithm,a", po::value(&algorithm)->required(), "set algorithm"); - } - - void parse(int argc, char** argv) - { - namespace po = boost::program_options; - - po::options_description hidden_options; - hidden_options.add_options() - ("positional", po::value>(&args)); - - po::options_description all_options; - all_options.add(options).add(hidden_options); - - po::positional_options_description positional_options; - positional_options.add("positional", -1); + ("mode,m", po::value(&settings.mode)->required(), "set mode of operation") + ("algorithm,a", po::value(&settings.algorithm)->required(), "set algorithm") + ("input-path,i", po::value(&settings.input_path)->required(), "set input file") + ("output-path,o", po::value(&settings.output_path)->required(), "set output file") + ("key,k", po::value(&settings.key)->required(), "set encryption key") + ("iv,v", po::value(&settings.iv.second), "set initialization vector"); po::variables_map vm; - po::store(po::command_line_parser(argc, argv) - .options(all_options) - .positional(positional_options) - .run(), vm); + po::store(po::parse_command_line(argc, argv, options), vm); if (vm.count("help")) { @@ -87,14 +88,13 @@ namespace return; } + if (vm.count("iv")) + settings.iv.first = true; + po::notify(vm); } - bool requested_help() const { return help_flag; } - - aesni::Mode mode; - aesni::Algorithm algorithm; - std::vector args; + bool exit_with_usage() const { return help_flag; } private: const std::string prog_name; @@ -107,7 +107,7 @@ namespace std::ostream& operator<<(std::ostream& os, const CommandLineParser& cmd_parser) { - return os << "Usage: " << cmd_parser.prog_name << " [OPTIONS...] KEY [IV] SRC_PATH DEST_PATH\n" + return os << "Usage: " << cmd_parser.prog_name << " [OPTION...]\n" << cmd_parser.options << "\n"; } } -- cgit v1.2.3