diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aa42c45..d303fcf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,10 @@ -set(SOURCES main.cpp crypto.cpp io.cpp utils.cpp) +set(SOURCES + main.cpp + horcrux.cpp + crypto.cpp + io.cpp + utils.cpp +) add_executable(horcrux ${SOURCES}) add_library(${CMAKE_PROJECT_NAME}_lib STATIC ${SOURCES}) diff --git a/src/crypto.cpp b/src/crypto.cpp index 6d5798b..081b0cf 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -32,17 +32,7 @@ public: }; -AES256_CBC::AES256_CBC(){ - encryption_key = utils::generate_random(kKeySize); -} -AES256_CBC::AES256_CBC(const std::vector& key){ - encryption_key = key; -} -AES256_CBC::AES256_CBC(std::vector&& key){ - encryption_key = key; -} - -EvpCipherCtx AES256_CBC::init(Cipher::Mode mode, +EvpCipherCtx AES256_CBC::init(Mode mode, const std::vector& key, const std::vector& iv){ if (key.size() != kKeySize){ throw std::runtime_error("Wrong key size"); @@ -52,12 +42,12 @@ EvpCipherCtx AES256_CBC::init(Cipher::Mode mode, } EvpCipherCtx ctx; - if (mode == Cipher::Mode::kEncrypt){ + if (mode == Mode::kEncrypt){ if (EVP_EncryptInit(ctx.get(), EVP_aes_256_cbc(), (key.data()), (iv.data())) == 0){ throw std::runtime_error("EVP_EncryptInit"); } - } else if (mode == Cipher::Mode::kDecrypt){ + } else if (mode == Mode::kDecrypt){ if (EVP_DecryptInit(ctx.get(), EVP_aes_256_cbc(), (key.data()), (iv.data())) == 0){ throw std::runtime_error("EVP_DecryptInit"); @@ -66,7 +56,7 @@ EvpCipherCtx AES256_CBC::init(Cipher::Mode mode, return ctx; } -size_t AES256_CBC::process_chunk(Cipher::Mode mode, EvpCipherCtx& ctx, +size_t AES256_CBC::process_chunk(Mode mode, EvpCipherCtx& ctx, std::vector::const_iterator begin, std::vector::const_iterator end, std::vector& output, size_t output_offset, @@ -78,7 +68,7 @@ size_t AES256_CBC::process_chunk(Cipher::Mode mode, EvpCipherCtx& ctx, // Make sure ouput is large enough to add encrypted data + padding output.resize(output_offset + chunk_size + kIvSize); } - if (mode == Cipher::Mode::kEncrypt) { + if (mode == Mode::kEncrypt) { if (1 != EVP_EncryptUpdate(ctx.get(), output.data() + output_offset, &len, &*begin, chunk_size)){ throw std::runtime_error("EVP_EncryptUpdate"); @@ -94,7 +84,7 @@ size_t AES256_CBC::process_chunk(Cipher::Mode mode, EvpCipherCtx& ctx, return len; } -size_t AES256_CBC::process_final(Cipher::Mode mode, EvpCipherCtx& ctx, +size_t AES256_CBC::process_final(Mode mode, EvpCipherCtx& ctx, std::vector& output, size_t output_offset, bool resize_in, bool resize_out) { @@ -103,7 +93,7 @@ size_t AES256_CBC::process_final(Cipher::Mode mode, EvpCipherCtx& ctx, // Make sure output is large enough to add the last block output.resize(output_offset + kIvSize); } - if (mode == Cipher::Mode::kEncrypt) { + if (mode == Mode::kEncrypt) { if (1 != EVP_EncryptFinal_ex(ctx.get(), output.data() + output_offset, &len)){ throw std::runtime_error("EVP_EncryptFinal"); } @@ -117,7 +107,7 @@ size_t AES256_CBC::process_final(Cipher::Mode mode, EvpCipherCtx& ctx, return len; } -size_t AES256_CBC::process_all(Cipher::Mode mode, EvpCipherCtx& ctx, +size_t AES256_CBC::process_all(Mode mode, EvpCipherCtx& ctx, std::vector::const_iterator begin, std::vector::const_iterator end, std::vector& output, size_t output_offset, @@ -130,9 +120,15 @@ size_t AES256_CBC::process_all(Cipher::Mode mode, EvpCipherCtx& ctx, return len; } +std::vector AES256_CBC::process(const std::vector& inputdata) { + if (mode == Mode::kEncrypt) + return encrypt(inputdata); + else + return decrypt(inputdata); +} std::vector AES256_CBC::encrypt(const std::vector& plaintext) { - return encrypt(encryption_key, utils::generate_random(kIvSize), plaintext); + return encrypt(encryption_key, horcrux::generate_random(kIvSize), plaintext); } std::vector AES256_CBC::decrypt(const std::vector& ciphertext) { return decrypt(encryption_key, ciphertext); @@ -141,12 +137,12 @@ std::vector AES256_CBC::decrypt(const std::vector& std::vector AES256_CBC::encrypt(const std::vector& key, const std::vector& iv, const std::vector& input) { - auto ctx = init(Cipher::Mode::kEncrypt, key, iv); + auto ctx = init(Mode::kEncrypt, key, iv); // Make sure ouput is large enough to contain IV + encrypted data + padding std::vector output(input.size() + (2 * kIvSize)); std::copy(iv.begin(), iv.end(), output.begin()); - process_all(Cipher::Mode::kEncrypt, ctx, input.begin(), input.end(), output, kIvSize); + process_all(Mode::kEncrypt, ctx, input.begin(), input.end(), output, kIvSize); return output; } @@ -154,8 +150,8 @@ std::vector AES256_CBC::encrypt(const std::vector& int AES256_CBC::encrypt(const std::vector& key, const std::vector& iv, const std::vector& input, std::vector& output) { - auto ctx = init(Cipher::Mode::kEncrypt, key, iv); - process_all(Cipher::Mode::kEncrypt, ctx, input.begin(), input.end(), output, 0); + auto ctx = init(Mode::kEncrypt, key, iv); + process_all(Mode::kEncrypt, ctx, input.begin(), input.end(), output, 0); return 0; } @@ -177,8 +173,8 @@ int AES256_CBC::encrypt(const std::vector& key, const std::vector int AES256_CBC::decrypt(const std::vector& key, const std::vector& iv, const std::vector& input, std::vector& output) { - auto ctx = init(Cipher::Mode::kDecrypt, key, iv); - process_all(Cipher::Mode::kDecrypt, ctx, input.begin(), input.end(), output, 0); + auto ctx = init(Mode::kDecrypt, key, iv); + process_all(Mode::kDecrypt, ctx, input.begin(), input.end(), output, 0); return 0; } std::vector AES256_CBC::decrypt(const std::vector& key, @@ -190,9 +186,9 @@ std::vector AES256_CBC::decrypt( const std::vector& key, const std::vector& iv, std::vector::const_iterator begin, std::vector::const_iterator end) { - auto ctx = init(Cipher::Mode::kDecrypt, key, iv); + auto ctx = init(Mode::kDecrypt, key, iv); std::vector output; - process_all(Cipher::Mode::kDecrypt, ctx, begin, end, output, 0); + process_all(Mode::kDecrypt, ctx, begin, end, output, 0); return output; } }; //namespace diff --git a/src/crypto.h b/src/crypto.h index 3bd98f9..4c440fb 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -4,44 +4,30 @@ #include #include +#include "utils.h" + namespace horcrux { -enum class CipherType {AES256_CBC}; + +enum class Mode {kEncrypt, kDecrypt}; class Cipher { protected: + Cipher() = delete; + Cipher(Mode m) : mode(m) { } + Cipher(Mode m, const std::vector& key) : + mode(m), encryption_key(key) {} + + Cipher(Mode m, std::vector&& key) : + mode(m), encryption_key(key) {} + std::vector encryption_key; - public: - enum Mode { - kEncrypt, - kDecrypt - }; + const Mode mode; + const std::vector& get_encryption_key() {return encryption_key;} + virtual std::vector process(const std::vector& inputdata) = 0; virtual std::vector encrypt(const std::vector& plaintext) = 0; virtual std::vector decrypt(const std::vector& ciphertext) = 0; -/* - virtual std::pair, std::vector> - encrypt_all(std::vector& plaintext) = 0; - - virtual std::vector - encrypt_all(std::vector& plaintext, - std::ostream); - - virtual std::vector - decrypt_all(std::vector& ciphertext, std::vector& key) = 0; - - virtual void encrypt_init(std::vector& key, std::vector& iv) = 0; - - virtual void encrypt_chunk() = 0; - - virtual void encrypt_fini() = 0; - - virtual void decrypt_init(std::vector& key, std::vector& iv) = 0; - - virtual void decrypt_chunk() = 0; - - virtual void decrypt_fini() = 0; -*/ }; class EvpCipherCtx; @@ -51,19 +37,27 @@ class AES256_CBC : public Cipher { const size_t kIvSize = 16; public: - AES256_CBC(); - AES256_CBC(const std::vector& key); - AES256_CBC(std::vector&& key); + AES256_CBC() : Cipher(Mode::kEncrypt) { + encryption_key = horcrux::generate_random(kKeySize); + } + AES256_CBC(const std::vector& key) : Cipher(Mode::kDecrypt, key) + { + if (key.size() != kKeySize) + throw std::invalid_argument("Invalid key size"); + } + AES256_CBC(std::vector&& key) : Cipher(Mode::kDecrypt, key) + { + if (key.size() != kKeySize) + throw std::invalid_argument("Invalid key size"); + } + std::vector process(const std::vector& inputdata) override; std::vector encrypt(const std::vector& plaintext) override; std::vector decrypt(const std::vector& ciphertext) override; std::vector encrypt(const std::vector& key, const std::vector& iv, const std::vector& input); - //int encrypt(const std::vector& key, - // const std::vector& input, std::vector& output); - int encrypt(const std::vector& key, const std::vector& iv, const std::vector& input, std::vector& output); @@ -82,34 +76,25 @@ public: std::vector::const_iterator begin, std::vector::const_iterator end); private: - EvpCipherCtx init(Cipher::Mode mode, + EvpCipherCtx init(Mode mode, const std::vector& key, const std::vector& iv); - size_t process_chunk(Cipher::Mode mode, EvpCipherCtx& ctx, + size_t process_chunk(Mode mode, EvpCipherCtx& ctx, std::vector::const_iterator begin, std::vector::const_iterator end, std::vector& output, size_t output_offset, bool resize_in = true, bool resize_out = true); - size_t process_final(Cipher::Mode mode, EvpCipherCtx& ctx, + size_t process_final(Mode mode, EvpCipherCtx& ctx, std::vector& output, size_t output_offset, bool resize_in = true, bool resize_out = true); - size_t process_all(Cipher::Mode mode, EvpCipherCtx& ctx, + size_t process_all(Mode mode, EvpCipherCtx& ctx, std::vector::const_iterator begin, std::vector::const_iterator end, std::vector& output, size_t output_offset, bool resize_in = true, bool resize_out = true); }; -static std::unique_ptr createCipher(CipherType type){ - switch(type){ - case CipherType::AES256_CBC: - return std::make_unique(); - default: - throw std::runtime_error("Unknown cipher"); - } -} - -}; +}; //namespace #endif //HORCRUX_SRC_CRYPTO_H diff --git a/src/horcrux.cpp b/src/horcrux.cpp new file mode 100644 index 0000000..6cd6012 --- /dev/null +++ b/src/horcrux.cpp @@ -0,0 +1,82 @@ +#include +#include +#include "horcrux.h" +#include "utils.h" + +namespace horcrux { + +Horcrux::Horcrux(HorcruxOptions&& opt) : options(opt){ init(); } +Horcrux::Horcrux(const HorcruxOptions& opt) : options(opt){ init(); } +void Horcrux::init(){ + if (options.count <= 0){ + throw std::invalid_argument("Invalid horcrux count"); + } + switch (options.mode){ + case Mode::kEncrypt: + cipher = std::make_unique(); + input = std::make_unique(options.input[0]); + output = std::make_unique(options.output, options.count, + std::filesystem::path(options.input[0]).filename().string()); + options.base64_key = to_base64(cipher->get_encryption_key()); + break; + case Mode::kDecrypt: + if (options.count != options.input.size()) + throw std::invalid_argument("Invalid horcrux count"); + cipher = std::make_unique(from_base64(options.base64_key)); + input = std::make_unique(options.input); + output = std::make_unique(options.output); + break; + default: + throw std::invalid_argument("Invalid horcrux mode"); + } +} + +void Horcrux::execute(){ + if (options.mode == Mode::kEncrypt) + output->write(cipher->encrypt(input->read())); + else + output->write(cipher->decrypt(input->read())); +} + +static void print_usage(const std::string& program){ + std::cout << "Usage:" << std::endl << + "\t\t" << program << " create -n " << std::endl << + "\t\t" << program << " load -k " << std::endl; +} + +static void parse_error(const std::string& program, const std::string& error){ + print_usage(program); + throw std::invalid_argument(error); +} + +HorcruxOptions parse_arguments(std::vector&& arguments){ + if (arguments.size() < 6){ + parse_error(std::string(arguments[0]), "Wrong argument number"); + } + HorcruxOptions opt; + if (arguments[1] == "create") { + if (arguments.size() != 6){ + parse_error(std::string(arguments[0]), "Wrong argument number"); + } + opt.mode = Mode::kEncrypt; + if (arguments[2] != "-n") + parse_error(arguments[0], "create: unknown option " + arguments[2]); + opt.count = std::stoi(arguments[3]); + opt.input.emplace_back(arguments[4]); + opt.output = arguments[5]; + } else if (arguments[1] == "load"){ + opt.mode = Mode::kDecrypt; + if (arguments[2] != "-k") + parse_error(arguments[0], "load: unknown option " + arguments[2]); + opt.base64_key = arguments[3]; + opt.input.insert(opt.input.begin(), arguments.begin() + 4, arguments.end() - 1); + opt.count = opt.input.size(); + opt.output = arguments.back(); + } else { + parse_error(arguments[0], "unknown mode: " + arguments[1]); + } + return opt; +} + + +}; //namespace diff --git a/src/horcrux.h b/src/horcrux.h new file mode 100644 index 0000000..4250d8c --- /dev/null +++ b/src/horcrux.h @@ -0,0 +1,41 @@ +#ifndef HORCRUX_HORCRUX_H +#define HORCRUX_HORCRUX_H +#include +#include +#include + +#include "crypto.h" +#include "io.h" + +namespace horcrux { + +struct HorcruxOptions { + Mode mode; + int count; + std::vector input; + std::string output; + std::string base64_key; +}; + +class Horcrux { + + HorcruxOptions options; + std::unique_ptr cipher; + std::unique_ptr input; + std::unique_ptr output; + + void init(); + +public: + Horcrux(const HorcruxOptions& opt); + Horcrux(HorcruxOptions&& opt); + void execute(); + const Mode& mode() { return options.mode; } + const std::string& key() { return options.base64_key; } + +}; + +HorcruxOptions parse_arguments(std::vector&& arguments); + +}; //namespace +#endif //HORCRUX_HORCRUX_H diff --git a/src/io.cpp b/src/io.cpp index 8d6a625..31145ad 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -1,10 +1,11 @@ #include #include "io.h" +#include "utils.h" namespace horcrux { namespace fs = std::filesystem; -FsPlainInput::FsPlainInput(const std::string& path) : file_path(path) +FsPlainInput::FsPlainInput(const std::string& path) : file_path(fs::absolute(path)) { if (fs::status(path).type() != fs::file_type::regular){ throw std::invalid_argument("Input is not a regular file"); @@ -28,7 +29,7 @@ FsCryptoInput::FsCryptoInput(const std::vector& filenames) throw std::invalid_argument("No files to decrypt"); } for (auto name : filenames){ - auto path = fs::path{name}; + auto path = absolute(fs::absolute({name})); if (fs::status(path).type() != fs::file_type::regular){ throw std::invalid_argument("Input is not a regular file"); } @@ -52,7 +53,7 @@ std::vector FsCryptoInput::read(){ } FsPlainOutput::FsPlainOutput(const std::string& filename) - : file_path(filename) + : file_path(fs::absolute(filename)) { if (fs::exists(file_path) && fs::status(file_path).type() != fs::file_type::regular){ throw std::invalid_argument("Output file is not a regular file"); @@ -66,7 +67,7 @@ size_t FsPlainOutput::write(const std::vector& to_write){ FsCryptoOutput::FsCryptoOutput(const std::string& folder, const int horcrux_num, const std::string& filename, const size_t horcrux_size) - : folder_path(folder), base_name(filename), + : folder_path(fs::absolute(folder)), base_name(filename), num(horcrux_num), size(horcrux_size) { if (fs::status(folder_path).type() != fs::file_type::directory){ @@ -84,7 +85,7 @@ size_t FsCryptoOutput::write(const std::vector& to_write){ created_files.clear(); size_t data_written{0}; for (int i = 0; i < num; ++i){ - std::string name = base_name + '_' + std::to_string(i) + ".enc"; + std::string name = base_name + '.' + std::to_string(i) + ".enc"; created_files.emplace_back(folder_path / name); f = std::ofstream(created_files.back(), std::ios::binary | std::ios::trunc); diff --git a/src/main.cpp b/src/main.cpp index 94553a3..d705325 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,69 +1,30 @@ #include - -enum RetErr { - kOk = 0, - kUnknownMode, -}; - -enum HorcruxMode { - kCreate, - kLoad -}; - - -struct HorcruxOptions { - HorcruxMode mode; - unsigned int count; - std::string key; - std::string input; - std::string output; -}; - -//RetErr parse_create_options(std::vector& arguments, HorcruxOptions& opt){ -// opt.mode = kCreate; -//} -//RetErr parse_load_options(std::vector& arguments, HorcruxOptions& opt){ -// opt.mode = kLoad; -//} -// -//ret_err parse_options(int argc, const char *args[]){ -// const std::vector arguments; -// for (int i = 1; i < argc, ++i){ -// arguments.push_back(args[i]); -// } -// horcrux_options options; -// if (argc < 1) -// return -EINVAL; -// const std::string mode(args[1]); -// if (mode == "create"){ -// options.horcrux_mode = horcrux_create; -// } else if (mode == "load"){ -// options.horcrux_mode = horcrux_load; -// } else { -// return kUnknownMode; -// } -//} -// -//RetErr horcrux_create(HorcruxOptions& options){ -// -// -//} - +#include +#include "horcrux.h" int main(const int argc, const char *argv[]) { - HorcruxOptions options; -// RetErr ret = parse_arguments(argc, argv); -// switch (options.mode){ -// case kCreate: -// ret = horcrux_create(options); -// break; -// case kLoad: -// ret = horcrux_load(options); -// break; -// default: -// std::cout << "Error: Unknown Mode" << std::endl; -// break; -// } - return 0; + int ret = -1; + std::vector arguments; + for (int i = 0; i < argc; ++i){ + arguments.emplace_back(argv[i]); + } + + try { + horcrux::Horcrux h(horcrux::parse_arguments(std::move(arguments))); + h.execute(); + if (h.mode() == horcrux::Mode::kEncrypt){ + //print encryption key to stdout + std::cout << h.key() << std::endl; + } + ret = 0; + } catch (std::invalid_argument& ex){ + std::cerr << "Error: Invalid arguments. " << ex.what() << std::endl; + } catch (std::runtime_error& ex){ + std::cerr << "Runtime error: " << ex.what() << std::endl; + } catch (std::exception& ex){ + std::cerr << "Unknown error: " << ex.what() << std::endl; + } + + return ret; } diff --git a/src/utils.cpp b/src/utils.cpp index 66d82fe..630e271 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -5,7 +5,7 @@ #include "utils.h" -std::string utils::to_base64(const std::vector& binary) +std::string horcrux::to_base64(const std::vector& binary) { using namespace boost::archive::iterators; using It = base64_from_binary::const_iterator, 6, 8>>; @@ -14,7 +14,7 @@ std::string utils::to_base64(const std::vector& binary) return base64.append((3 - binary.size() % 3) % 3, '='); } -std::vector utils::from_base64(const std::string& base64) +std::vector horcrux::from_base64(const std::string& base64) { using namespace boost::archive::iterators; using It = transform_width, 8, 6>; @@ -32,7 +32,7 @@ std::vector utils::from_base64(const std::string& base64) return binary; } -std::vector utils::generate_random(const size_t size){ +std::vector horcrux::generate_random(const size_t size){ std::vector res(size); if(!RAND_bytes(res.data(), size)){ throw std::exception(); diff --git a/src/utils.h b/src/utils.h index f2d8868..709b735 100644 --- a/src/utils.h +++ b/src/utils.h @@ -2,8 +2,9 @@ #define HORCRUX_SRC_UTILS_H #include #include +#include -namespace utils { +namespace horcrux { std::string to_base64(const std::vector& binary); std::vector from_base64(const std::string& base64); diff --git a/test/integration-test.cpp b/test/integration-test.cpp index 963ae73..585399c 100644 --- a/test/integration-test.cpp +++ b/test/integration-test.cpp @@ -1,27 +1,29 @@ #include "gtest/gtest.h" #include "test.h" +#include "horcrux.h" +using namespace horcrux; TEST(IntegrationTest, EndToEndEncryptDecrypt){ auto buf = generic_read_file(image); //Prepare encrypt operation - auto in = horcrux::FsPlainInput(image); - auto cipher = horcrux::AES256_CBC(); - auto out = horcrux::FsCryptoOutput(folder, 3); + auto in = FsPlainInput(image); + auto cipher = AES256_CBC(); + auto out = FsCryptoOutput(folder, 3); // Perform encrypt operation out.write(cipher.encrypt(in.read())); //Prepare decrypt operation - auto in2 = horcrux::FsCryptoInput(get_created_filenames(out)); + auto in2 = FsCryptoInput(get_created_filenames(out)); //Perform decrypt operation auto buf2 = cipher.decrypt(in2.read()); //check outcome EXPECT_EQ(buf, buf2); - auto out2 = horcrux::FsPlainOutput(noexist); + auto out2 = FsPlainOutput(noexist); out2.write(cipher.decrypt(in2.read())); auto buf3 = generic_read_file(noexist); @@ -30,3 +32,97 @@ TEST(IntegrationTest, EndToEndEncryptDecrypt){ delete_created_files(out); std::filesystem::remove(noexist); } + +TEST(IntegrationTest, HorcruxOptions){ + HorcruxOptions options { + .mode = Mode::kEncrypt, + .count = -1, + .input = {noexist}, + .output = {image} + }; + EXPECT_THROW(Horcrux {options}, std::invalid_argument); + options.count = 1; + EXPECT_THROW(Horcrux {options}, std::invalid_argument); + options.input = {image}; + EXPECT_THROW(Horcrux {options}, std::invalid_argument); + options.output = {folder}; + options.count = 0; + EXPECT_THROW(Horcrux {options}, std::invalid_argument); + options.count = 2; + EXPECT_NO_THROW(Horcrux {options}); + options.mode = Mode::kDecrypt; + EXPECT_THROW(Horcrux {options}, std::invalid_argument); + options.input = {image, text}; + options.count = 1; + EXPECT_THROW(Horcrux {options}, std::invalid_argument); + options.output = {noexist}; + EXPECT_THROW(Horcrux {options}, std::invalid_argument); + options.count = 2; + EXPECT_THROW(Horcrux {options}, std::invalid_argument); + options.base64_key = to_base64(generate_random(32)); + EXPECT_NO_THROW(Horcrux {options}); +} +TEST(IntegrationTest, HorcruxEncryptiDecrypt) { + HorcruxOptions options { + .mode = Mode::kEncrypt, + .count = 3, + .input = {image}, + .output = {folder} + }; + Horcrux enc{options}; + + enc.execute(); + auto key = enc.key(); + + HorcruxOptions options2 { + .mode = Mode::kDecrypt, + .count = 3, + .input = {get_encrypted_files(folder, image)}, + .output = {noexist}, + .base64_key = key + }; + + Horcrux dec{options2}; + dec.execute(); + + //Compare input and ouput files + EXPECT_EQ(generic_read_file(image), generic_read_file(noexist)); + std::filesystem::remove(noexist); + std::for_each(options2.input.begin(), options2.input.end(), [](auto& p){ + std::filesystem::remove(p);}); +} +TEST(IntegrationTest, arguments){ + EXPECT_THROW( + parse_arguments({"horcrux", "create", "-n", "4", "input_file"}), + std::invalid_argument); + EXPECT_THROW( + parse_arguments({"horcrux", "pippo", "-n", "4", "input_file"}), + std::invalid_argument); + EXPECT_THROW( + parse_arguments({"horcrux", "create", "-n", "4", "input_file", "output_file", "garbage"}), + std::invalid_argument); + EXPECT_THROW( + parse_arguments({"horcrux", "create", "-h", "4", "input_file", "output_file"}), + std::invalid_argument); + EXPECT_THROW( + parse_arguments({"horcrux", "create", "-n", "boh", "input_file", "output_file"}), + std::invalid_argument); + EXPECT_NO_THROW( + parse_arguments({"horcrux", "create", "-n", "4", "input_file", "output_file"})); + EXPECT_THROW( + parse_arguments({"horcrux", "load", "-n", "4", "input_file"}), + std::invalid_argument); + EXPECT_THROW( + parse_arguments({"horcrux", "load", "-k", "lshgflushlgkjusghl", "input_file"}), + std::invalid_argument); + EXPECT_THROW( + parse_arguments({"horcrux", "load", "-r", "lshgflushlgkjusghl", "input", "input", "output"}), + std::invalid_argument); + EXPECT_THROW( + parse_arguments({"horcrux", "load", "-k", "lshgflushlgkjusghl", "input"}), + std::invalid_argument); + EXPECT_NO_THROW( + parse_arguments({"horcrux", "load", "-k", "lshgflushlgkjusghl", "input", "output"})); + EXPECT_NO_THROW( + parse_arguments({"horcrux", "load", "-k", "lshgflushlgkjusghl", "input", "input", "output"})); +} diff --git a/test/io-test.cpp b/test/io-test.cpp index 9c3a0d1..55c146f 100644 --- a/test/io-test.cpp +++ b/test/io-test.cpp @@ -171,5 +171,6 @@ TEST(IoTest, CryptoToPlain){ //check the outcome auto buf2 = generic_read_file(noexist); EXPECT_EQ(buf, buf2); + delete_created_files(out_test); std::filesystem::remove(noexist); } diff --git a/test/main.cpp b/test/main.cpp index 72bd115..1eb5aab 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,4 +1,38 @@ #include "gtest/gtest.h" +#include "test.h" + +/* Utility functions */ +std::vector generic_read_file(const std::string& filename){ + auto ifstream = std::ifstream{filename, std::ios::binary}; + auto path = std::filesystem::path{filename}; + auto size = std::filesystem::file_size(path); + std::vector buf(size); + ifstream.read(reinterpret_cast(buf.data()), size); + return buf; +} + +std::vector get_created_filenames(const horcrux::FsCryptoOutput& out){ + std::vector result(out.created_files.size()); + transform(out.created_files.begin(), out.created_files.end(), result.begin(), + [](auto path){return path.string();}); + return result; +} +void delete_created_files(const horcrux::FsCryptoOutput& out){ + std::for_each(out.created_files.begin(), out.created_files.end(), + [](auto f){std::filesystem::remove(f);}); +} + +std::vector get_encrypted_files(const std::string& folder, const std::string& basename) { + std::vector result; + for (auto& p: std::filesystem::directory_iterator(folder)){ + if (p.path().string().starts_with(basename) && + p.path().string().ends_with(".enc")) + result.push_back(p.path().string()); + } + std::sort(result.begin(), result.end()); + return result; +} + int main(int argc, char *argv[]) { ::testing::InitGoogleTest(&argc, argv); diff --git a/test/test.h b/test/test.h index ae17385..6a530ee 100644 --- a/test/test.h +++ b/test/test.h @@ -1,6 +1,7 @@ #ifndef HORCRUX_TEST_TEST_H #define HORCRUX_TEST_TEST_H #include +#include #include "io.h" #include "crypto.h" @@ -15,25 +16,13 @@ const std::string empty{TEST_WORK_DIR "/empty"}; const std::string text{TEST_WORK_DIR "/test.txt"}; const std::string image{TEST_WORK_DIR "/mangoni.jpg"}; -static std::vector generic_read_file(const std::string& filename){ - auto ifstream = std::ifstream{filename, std::ios::binary}; - auto path = std::filesystem::path{filename}; - auto size = std::filesystem::file_size(path); - std::vector buf(size); - ifstream.read(reinterpret_cast(buf.data()), size); - return buf; -} +std::vector generic_read_file(const std::string& filename); -static std::vector get_created_filenames(const horcrux::FsCryptoOutput& out){ - std::vector result(out.created_files.size()); - transform(out.created_files.begin(), out.created_files.end(), result.begin(), - [](auto path){return path.string();}); - return result; -} -static void delete_created_files(const horcrux::FsCryptoOutput& out){ - std::for_each(out.created_files.begin(), out.created_files.end(), - [](auto f){std::filesystem::remove(f);}); -} +std::vector get_created_filenames(const horcrux::FsCryptoOutput& out); + +void delete_created_files(const horcrux::FsCryptoOutput& out); + +std::vector get_encrypted_files(const std::string& folder, const std::string& basename); /* Crypto Test utils */ diff --git a/test/utils-test.cpp b/test/utils-test.cpp index 7db1df1..802c0b3 100644 --- a/test/utils-test.cpp +++ b/test/utils-test.cpp @@ -16,30 +16,30 @@ const std::string test4_str = "mi e' entrata una bruschetta nell'occhio"; const std::string test4_base64 = "bWkgZScgZW50cmF0YSB1bmEgYnJ1c2NoZXR0YSBuZWxsJ29jY2hpbw=="; TEST(utilTests, to_base64Test){ - EXPECT_EQ(test1_base64, utils::to_base64(std::vector(test1_str.begin(), test1_str.end()))); - EXPECT_EQ(test2_base64, utils::to_base64(std::vector(test2_str.begin(), test2_str.end()))); - EXPECT_EQ(test3_base64, utils::to_base64(std::vector(test3_str.begin(), test3_str.end()))); - EXPECT_EQ(test4_base64, utils::to_base64(std::vector(test4_str.begin(), test4_str.end()))); + EXPECT_EQ(test1_base64, horcrux::to_base64(std::vector(test1_str.begin(), test1_str.end()))); + EXPECT_EQ(test2_base64, horcrux::to_base64(std::vector(test2_str.begin(), test2_str.end()))); + EXPECT_EQ(test3_base64, horcrux::to_base64(std::vector(test3_str.begin(), test3_str.end()))); + EXPECT_EQ(test4_base64, horcrux::to_base64(std::vector(test4_str.begin(), test4_str.end()))); } TEST(utilTests, from_base64Test){ - auto result = utils::from_base64(test1_base64); + auto result = horcrux::from_base64(test1_base64); EXPECT_EQ(test1_str, std::string(result.begin(), result.end())); - result = utils::from_base64(test2_base64); + result = horcrux::from_base64(test2_base64); EXPECT_EQ(test2_str, std::string(result.begin(), result.end())); - result = utils::from_base64(test3_base64); + result = horcrux::from_base64(test3_base64); EXPECT_EQ(test3_str, std::string(result.begin(), result.end())); - result = utils::from_base64(test4_base64); + result = horcrux::from_base64(test4_base64); EXPECT_EQ(test4_str, std::string(result.begin(), result.end())); } TEST(utilTests, generate_random){ - EXPECT_NE(utils::generate_random(32), utils::generate_random(32)); - EXPECT_NE(utils::generate_random(16), utils::generate_random(16)); - EXPECT_NE(utils::generate_random(8), utils::generate_random(8)); - EXPECT_NE(utils::generate_random(1), utils::generate_random(1)); - EXPECT_EQ(utils::generate_random(0), utils::generate_random(0)); + EXPECT_NE(horcrux::generate_random(32), horcrux::generate_random(32)); + EXPECT_NE(horcrux::generate_random(16), horcrux::generate_random(16)); + EXPECT_NE(horcrux::generate_random(8), horcrux::generate_random(8)); + EXPECT_NE(horcrux::generate_random(1), horcrux::generate_random(1)); + EXPECT_EQ(horcrux::generate_random(0), horcrux::generate_random(0)); }