Fix format

This commit is contained in:
Michele Rodolfi 2020-12-13 00:56:18 +01:00
parent 3d89f30a94
commit 01ff00f3b7
20 changed files with 855 additions and 817 deletions

View File

@ -1,6 +1,6 @@
root = true root = true
[*] [*]
end_of_line = lf end_of_line = lf
indent_style = tab indent_style = space
indent_size = 4 indent_size = 4
trim_trailing_whitespace = true trim_trailing_whitespace = true

View File

@ -6,16 +6,16 @@ set(CMAKE_CXX_STANDARD 20)
# Download and unpack googletest at configure time # Download and unpack googletest at configure time
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt) configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
if(result) if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}") message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif() endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build . execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
if(result) if(result)
message(FATAL_ERROR "Build step for googletest failed: ${result}") message(FATAL_ERROR "Build step for googletest failed: ${result}")
endif() endif()
# Prevent overriding the parent project's compiler/linker # Prevent overriding the parent project's compiler/linker
@ -32,7 +32,7 @@ add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src
# dependencies automatically when using CMake 2.8.11 or # dependencies automatically when using CMake 2.8.11 or
# later. Otherwise we have to add them here ourselves. # later. Otherwise we have to add them here ourselves.
if (CMAKE_VERSION VERSION_LESS 2.8.11) if (CMAKE_VERSION VERSION_LESS 2.8.11)
include_directories("${gtest_SOURCE_DIR}/include") include_directories("${gtest_SOURCE_DIR}/include")
endif() endif()

View File

@ -4,12 +4,12 @@ project(googletest-download NONE)
include(ExternalProject) include(ExternalProject)
ExternalProject_Add(googletest ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG master GIT_TAG master
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND "" CONFIGURE_COMMAND ""
BUILD_COMMAND "" BUILD_COMMAND ""
INSTALL_COMMAND "" INSTALL_COMMAND ""
TEST_COMMAND "" TEST_COMMAND ""
) )

View File

@ -1,9 +1,9 @@
set(SOURCES set(SOURCES
main.cpp main.cpp
horcrux.cpp horcrux.cpp
crypto.cpp crypto.cpp
io.cpp io.cpp
utils.cpp utils.cpp
) )
add_executable(${CMAKE_PROJECT_NAME} ${SOURCES}) add_executable(${CMAKE_PROJECT_NAME} ${SOURCES})
@ -16,5 +16,5 @@ target_link_libraries(${CMAKE_PROJECT_NAME} OpenSSL::Crypto)
target_link_libraries(${CMAKE_PROJECT_NAME}_lib OpenSSL::Crypto) target_link_libraries(${CMAKE_PROJECT_NAME}_lib OpenSSL::Crypto)
install(TARGETS ${CMAKE_PROJECT_NAME} install(TARGETS ${CMAKE_PROJECT_NAME}
DESTINATION /usr/local/bin DESTINATION /usr/local/bin
) )

View File

@ -1,3 +1,5 @@
#include "crypto.h"
#include <openssl/evp.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include <exception> #include <exception>
@ -7,188 +9,203 @@
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#include <openssl/evp.h>
#include "crypto.h"
#include "utils.h" #include "utils.h"
namespace horcrux { namespace horcrux {
class EvpCipherCtx { class EvpCipherCtx {
EVP_CIPHER_CTX *ptr; EVP_CIPHER_CTX *ptr;
public: public:
EvpCipherCtx(){ EvpCipherCtx() {
ptr = EVP_CIPHER_CTX_new(); ptr = EVP_CIPHER_CTX_new();
} }
~EvpCipherCtx(){ ~EvpCipherCtx() {
EVP_CIPHER_CTX_free(ptr); EVP_CIPHER_CTX_free(ptr);
} }
EVP_CIPHER_CTX* get(){ EVP_CIPHER_CTX* get() {
return ptr; return ptr;
} }
}; };
EvpCipherCtx AES256_CBC::init(Mode mode, EvpCipherCtx AES256_CBC::init(Mode mode,
const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv){ const std::vector<unsigned char>& key,
if (key.size() != kKeySize){ const std::vector<unsigned char>& iv) {
throw std::runtime_error("Wrong key size"); if (key.size() != kKeySize) {
} throw std::runtime_error("Wrong key size");
if (iv.size() != kIvSize){ }
throw std::runtime_error("Wrong IV size"); if (iv.size() != kIvSize) {
} throw std::runtime_error("Wrong IV size");
}
EvpCipherCtx ctx; EvpCipherCtx ctx;
if (mode == Mode::kEncrypt){ if (mode == Mode::kEncrypt) {
if (EVP_EncryptInit(ctx.get(), EVP_aes_256_cbc(), if (EVP_EncryptInit(ctx.get(), EVP_aes_256_cbc(),
(key.data()), (iv.data())) == 0){ key.data(), iv.data()) == 0) {
throw std::runtime_error("EVP_EncryptInit"); throw std::runtime_error("EVP_EncryptInit");
} }
} else if (mode == Mode::kDecrypt){ } else if (mode == Mode::kDecrypt) {
if (EVP_DecryptInit(ctx.get(), EVP_aes_256_cbc(), if (EVP_DecryptInit(ctx.get(), EVP_aes_256_cbc(),
(key.data()), (iv.data())) == 0){ key.data(), iv.data()) == 0) {
throw std::runtime_error("EVP_DecryptInit"); throw std::runtime_error("EVP_DecryptInit");
} }
} else throw std::invalid_argument("Invalid Cipher mode"); } else {
return ctx; throw std::invalid_argument("Invalid Cipher mode");
}
return ctx;
} }
size_t AES256_CBC::process_chunk(Mode mode, EvpCipherCtx& ctx, size_t AES256_CBC::process_chunk(
std::vector<unsigned char>::const_iterator begin, Mode mode, EvpCipherCtx& ctx,
std::vector<unsigned char>::const_iterator end, std::vector<unsigned char>::const_iterator begin,
std::vector<unsigned char>& output, size_t output_offset, std::vector<unsigned char>::const_iterator end,
bool resize_in, bool resize_out) std::vector<unsigned char>& output, size_t output_offset,
{ bool resize_in, bool resize_out) {
auto chunk_size = end - begin; auto chunk_size = end - begin;
int len; int len;
if(resize_in){ if (resize_in) {
// Make sure ouput is large enough to add encrypted data + padding // Make sure ouput is large enough to add encrypted data + padding
output.resize(output_offset + chunk_size + kIvSize); output.resize(output_offset + chunk_size + kIvSize);
} }
if (mode == Mode::kEncrypt) { if (mode == Mode::kEncrypt) {
if (1 != EVP_EncryptUpdate(ctx.get(), if (1 != EVP_EncryptUpdate(ctx.get(),
output.data() + output_offset, &len, &*begin, chunk_size)){ output.data() + output_offset, &len,
throw std::runtime_error("EVP_EncryptUpdate"); &*begin, chunk_size)) {
} throw std::runtime_error("EVP_EncryptUpdate");
} else { }
if (1 != EVP_DecryptUpdate(ctx.get(), } else {
output.data() + output_offset, &len, &*begin, chunk_size)){ if (1 != EVP_DecryptUpdate(ctx.get(),
throw std::runtime_error("EVP_DecryptUpdate"); output.data() + output_offset, &len,
} &*begin, chunk_size)) {
} throw std::runtime_error("EVP_DecryptUpdate");
if (resize_out) }
output.resize(output_offset + len); }
return len; if (resize_out)
output.resize(output_offset + len);
return len;
} }
size_t AES256_CBC::process_final(Mode mode, EvpCipherCtx& ctx, size_t AES256_CBC::process_final(Mode mode, EvpCipherCtx& ctx,
std::vector<unsigned char>& output, size_t output_offset, std::vector<unsigned char>& output,
bool resize_in, bool resize_out) size_t output_offset,
{ bool resize_in, bool resize_out) {
int len; int len;
if (resize_in) { if (resize_in) {
// Make sure output is large enough to add the last block // Make sure output is large enough to add the last block
output.resize(output_offset + kIvSize); output.resize(output_offset + kIvSize);
} }
if (mode == Mode::kEncrypt) { if (mode == Mode::kEncrypt) {
if (1 != EVP_EncryptFinal_ex(ctx.get(), output.data() + output_offset, &len)){ if (1 != EVP_EncryptFinal_ex(ctx.get(), output.data() + output_offset,
throw std::runtime_error("EVP_EncryptFinal"); &len)) {
} throw std::runtime_error("EVP_EncryptFinal");
} else { }
if (1 != EVP_DecryptFinal_ex(ctx.get(), (output.data()) + output_offset, &len)){ } else {
throw std::runtime_error("EVP_DecryptFinal"); if (1 != EVP_DecryptFinal_ex(ctx.get(), (output.data()) + output_offset,
} &len)) {
} throw std::runtime_error("EVP_DecryptFinal");
if (resize_out) }
output.resize(output_offset + len); }
return len; if (resize_out)
output.resize(output_offset + len);
return len;
} }
size_t AES256_CBC::process_all(Mode mode, EvpCipherCtx& ctx, size_t AES256_CBC::process_all(
std::vector<unsigned char>::const_iterator begin, Mode mode, EvpCipherCtx& ctx,
std::vector<unsigned char>::const_iterator end, std::vector<unsigned char>::const_iterator begin,
std::vector<unsigned char>& output, size_t output_offset, std::vector<unsigned char>::const_iterator end,
bool resize_in, bool resize_out) std::vector<unsigned char>& output, size_t output_offset,
{ bool resize_in, bool resize_out) {
int len = process_chunk(mode, ctx, begin, end, int len = process_chunk(mode, ctx, begin, end, output, output_offset,
output, output_offset, resize_in, false); resize_in, false);
len += process_final(mode, ctx, len += process_final(mode, ctx, output, output_offset + len, false,
output, output_offset + len, false, resize_out); resize_out);
return len; return len;
} }
std::vector<unsigned char> AES256_CBC::process(const std::vector<unsigned char>& inputdata) { std::vector<unsigned char> AES256_CBC::process(
if (mode == Mode::kEncrypt) const std::vector<unsigned char>& inputdata) {
return encrypt(inputdata); if (mode == Mode::kEncrypt)
else return encrypt(inputdata);
return decrypt(inputdata); else
return decrypt(inputdata);
} }
std::vector<unsigned char> AES256_CBC::encrypt(const std::vector<unsigned char>& plaintext) { std::vector<unsigned char> AES256_CBC::encrypt(
return encrypt(encryption_key, horcrux::generate_random(kIvSize), plaintext); const std::vector<unsigned char>& plaintext) {
} return encrypt(encryption_key, horcrux::generate_random(kIvSize),
std::vector<unsigned char> AES256_CBC::decrypt(const std::vector<unsigned char>& ciphertext) { plaintext);
return decrypt(encryption_key, ciphertext);
}
std::vector<unsigned char> AES256_CBC::encrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
const std::vector<unsigned char>& input)
{
auto ctx = init(Mode::kEncrypt, key, iv);
// Make sure ouput is large enough to contain IV + encrypted data + padding
std::vector<unsigned char> output(input.size() + (2 * kIvSize));
std::copy(iv.begin(), iv.end(), output.begin());
process_all(Mode::kEncrypt, ctx, input.begin(), input.end(), output, kIvSize);
return output;
}
int AES256_CBC::encrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
const std::vector<unsigned char>& input, std::vector<unsigned char>& output)
{
auto ctx = init(Mode::kEncrypt, key, iv);
process_all(Mode::kEncrypt, ctx, input.begin(), input.end(), output, 0);
return 0;
}
int AES256_CBC::encrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
std::istream input, const size_t input_len,
std::ostream output, size_t& output_len){
auto inbuf = std::vector<unsigned char>(input_len);
auto outbuf = std::vector<unsigned char>(input_len + 16);
input.read(reinterpret_cast<char*>(inbuf.data()), input_len);
encrypt(key, iv, inbuf, outbuf);
output.write(reinterpret_cast<char*>(outbuf.data()), outbuf.size());
return 0;
}
int AES256_CBC::decrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
const std::vector<unsigned char>& input, std::vector<unsigned char>& output)
{
auto ctx = init(Mode::kDecrypt, key, iv);
process_all(Mode::kDecrypt, ctx, input.begin(), input.end(), output, 0);
return 0;
}
std::vector<unsigned char> AES256_CBC::decrypt(const std::vector<unsigned char>& key,
const std::vector<unsigned char>& ciphertext){
std::vector<unsigned char> iv(ciphertext.begin(), ciphertext.begin() + kIvSize);
return decrypt(key, iv, ciphertext.begin() + kIvSize, ciphertext.end());
} }
std::vector<unsigned char> AES256_CBC::decrypt( std::vector<unsigned char> AES256_CBC::decrypt(
const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv, const std::vector<unsigned char>& ciphertext) {
std::vector<unsigned char>::const_iterator begin, std::vector<unsigned char>::const_iterator end) return decrypt(encryption_key, ciphertext);
{
auto ctx = init(Mode::kDecrypt, key, iv);
std::vector<unsigned char> output;
process_all(Mode::kDecrypt, ctx, begin, end, output, 0);
return output;
} }
}; //namespace
std::vector<unsigned char> AES256_CBC::encrypt(
const std::vector<unsigned char>& key,
const std::vector<unsigned char>& iv,
const std::vector<unsigned char>& input) {
auto ctx = init(Mode::kEncrypt, key, iv);
// Make sure ouput is large enough to contain IV + encrypted data + padding
std::vector<unsigned char> output(input.size() + (2 * kIvSize));
std::copy(iv.begin(), iv.end(), output.begin());
process_all(Mode::kEncrypt, ctx, input.begin(), input.end(), output,
kIvSize);
return output;
}
int AES256_CBC::encrypt(const std::vector<unsigned char>& key,
const std::vector<unsigned char>& iv,
const std::vector<unsigned char>& input,
std::vector<unsigned char>& output) {
auto ctx = init(Mode::kEncrypt, key, iv);
process_all(Mode::kEncrypt, ctx, input.begin(), input.end(), output, 0);
return 0;
}
int AES256_CBC::encrypt(const std::vector<unsigned char>& key,
const std::vector<unsigned char>& iv,
std::istream input, const size_t input_len,
std::ostream output, size_t& output_len) {
auto inbuf = std::vector<unsigned char>(input_len);
auto outbuf = std::vector<unsigned char>(input_len + 16);
input.read(reinterpret_cast<char*>(inbuf.data()), input_len);
encrypt(key, iv, inbuf, outbuf);
output.write(reinterpret_cast<char*>(outbuf.data()), outbuf.size());
return 0;
}
int AES256_CBC::decrypt(const std::vector<unsigned char>& key,
const std::vector<unsigned char>& iv,
const std::vector<unsigned char>& input,
std::vector<unsigned char>& output) {
auto ctx = init(Mode::kDecrypt, key, iv);
process_all(Mode::kDecrypt, ctx, input.begin(), input.end(), output, 0);
return 0;
}
std::vector<unsigned char> AES256_CBC::decrypt(
const std::vector<unsigned char>& key,
const std::vector<unsigned char>& ciphertext) {
std::vector<unsigned char> iv(ciphertext.begin(),
ciphertext.begin() + kIvSize);
return decrypt(key, iv, ciphertext.begin() + kIvSize, ciphertext.end());
}
std::vector<unsigned char> AES256_CBC::decrypt(
const std::vector<unsigned char>& key,
const std::vector<unsigned char>& iv,
std::vector<unsigned char>::const_iterator begin,
std::vector<unsigned char>::const_iterator end) {
auto ctx = init(Mode::kDecrypt, key, iv);
std::vector<unsigned char> output;
process_all(Mode::kDecrypt, ctx, begin, end, output, 0);
return output;
}
}; // namespace horcrux

View File

@ -8,93 +8,114 @@
namespace horcrux { namespace horcrux {
enum class Mode {kEncrypt, kDecrypt}; enum class Mode { kEncrypt, kDecrypt };
class Cipher { class Cipher {
protected: protected:
Cipher() = delete; Cipher() = delete;
Cipher(Mode m) : mode(m) { } explicit Cipher(Mode m) : mode(m) { }
Cipher(Mode m, const std::vector<unsigned char>& key) : Cipher(Mode m, const std::vector<unsigned char>& key) :
mode(m), encryption_key(key) {} mode(m), encryption_key(key) {}
Cipher(Mode m, std::vector<unsigned char>&& key) : Cipher(Mode m, std::vector<unsigned char>&& key) :
mode(m), encryption_key(key) {} mode(m), encryption_key(key) {}
std::vector<unsigned char> encryption_key;
std::vector<unsigned char> encryption_key;
public: public:
const Mode mode; const Mode mode;
const std::vector<unsigned char>& get_encryption_key() {return encryption_key;} const std::vector<unsigned char>& get_encryption_key() {
return encryption_key;
}
virtual std::vector<unsigned char> process(const std::vector<unsigned char>& inputdata) = 0; virtual std::vector<unsigned char> process(
virtual std::vector<unsigned char> encrypt(const std::vector<unsigned char>& plaintext) = 0; const std::vector<unsigned char>& inputdata) = 0;
virtual std::vector<unsigned char> decrypt(const std::vector<unsigned char>& ciphertext) = 0;
virtual std::vector<unsigned char> encrypt(
const std::vector<unsigned char>& plaintext) = 0;
virtual std::vector<unsigned char> decrypt(
const std::vector<unsigned char>& ciphertext) = 0;
}; };
class EvpCipherCtx; class EvpCipherCtx;
class AES256_CBC : public Cipher { class AES256_CBC : public Cipher {
const size_t kKeySize = 32;
const size_t kKeySize = 32; const size_t kIvSize = 16;
const size_t kIvSize = 16;
public: public:
AES256_CBC() : Cipher(Mode::kEncrypt) { AES256_CBC() : Cipher(Mode::kEncrypt) {
encryption_key = horcrux::generate_random(kKeySize); encryption_key = horcrux::generate_random(kKeySize);
} }
AES256_CBC(const std::vector<unsigned char>& key) : Cipher(Mode::kDecrypt, key) explicit AES256_CBC(const std::vector<unsigned char>& key)
{ : Cipher(Mode::kDecrypt, key) {
if (key.size() != kKeySize) if (key.size() != kKeySize)
throw std::invalid_argument("Invalid key size"); throw std::invalid_argument("Invalid key size");
} }
AES256_CBC(std::vector<unsigned char>&& key) : Cipher(Mode::kDecrypt, key) explicit AES256_CBC(std::vector<unsigned char>&& key)
{ : Cipher(Mode::kDecrypt, key) {
if (key.size() != kKeySize) if (key.size() != kKeySize)
throw std::invalid_argument("Invalid key size"); throw std::invalid_argument("Invalid key size");
} }
std::vector<unsigned char> process(const std::vector<unsigned char>& inputdata) override; std::vector<unsigned char> process(
std::vector<unsigned char> encrypt(const std::vector<unsigned char>& plaintext) override; const std::vector<unsigned char>& inputdata) override;
std::vector<unsigned char> decrypt(const std::vector<unsigned char>& ciphertext) override; std::vector<unsigned char> encrypt(
const std::vector<unsigned char>& plaintext) override;
std::vector<unsigned char> decrypt(
const std::vector<unsigned char>& ciphertext) override;
std::vector<unsigned char> encrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv, std::vector<unsigned char> encrypt(const std::vector<unsigned char>& key,
const std::vector<unsigned char>& input); const std::vector<unsigned char>& iv,
const std::vector<unsigned char>& input);
int encrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv, int encrypt(const std::vector<unsigned char>& key,
const std::vector<unsigned char>& input, std::vector<unsigned char>& output); const std::vector<unsigned char>& iv,
const std::vector<unsigned char>& input,
std::vector<unsigned char>& output);
int encrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv, int encrypt(const std::vector<unsigned char>& key,
std::istream input, const size_t input_len, const std::vector<unsigned char>& iv,
std::ostream output, size_t& output_len); std::istream input, const size_t input_len,
std::ostream output, size_t& output_len);
int decrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv, int decrypt(const std::vector<unsigned char>& key,
const std::vector<unsigned char>& input, std::vector<unsigned char>& output); const std::vector<unsigned char>& iv,
const std::vector<unsigned char>& input,
std::vector<unsigned char>& output);
std::vector<unsigned char> decrypt(const std::vector<unsigned char>& key, std::vector<unsigned char> decrypt(
const std::vector<unsigned char>& ciphertext); const std::vector<unsigned char>& key,
const std::vector<unsigned char>& ciphertext);
std::vector<unsigned char> decrypt( std::vector<unsigned char> decrypt(
const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv, const std::vector<unsigned char>& key,
std::vector<unsigned char>::const_iterator begin, std::vector<unsigned char>::const_iterator end); const std::vector<unsigned char>& iv,
std::vector<unsigned char>::const_iterator begin,
std::vector<unsigned char>::const_iterator end);
private: private:
EvpCipherCtx init(Mode mode, EvpCipherCtx init(Mode mode, const std::vector<unsigned char>& key,
const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv); const std::vector<unsigned char>& iv);
size_t process_chunk(Mode mode, EvpCipherCtx& ctx, size_t process_chunk(Mode mode, EvpCipherCtx& ctx,
std::vector<unsigned char>::const_iterator begin, std::vector<unsigned char>::const_iterator begin,
std::vector<unsigned char>::const_iterator end, std::vector<unsigned char>::const_iterator end,
std::vector<unsigned char>& output, size_t output_offset, std::vector<unsigned char>& output,
bool resize_in = true, bool resize_out = true); size_t output_offset,
bool resize_in = true, bool resize_out = true);
size_t process_final(Mode mode, EvpCipherCtx& ctx, size_t process_final(Mode mode, EvpCipherCtx& ctx,
std::vector<unsigned char>& output, size_t output_offset, std::vector<unsigned char>& output,
bool resize_in = true, bool resize_out = true); size_t output_offset,
bool resize_in = true, bool resize_out = true);
size_t process_all(Mode mode, EvpCipherCtx& ctx, size_t process_all(Mode mode, EvpCipherCtx& ctx,
std::vector<unsigned char>::const_iterator begin, std::vector<unsigned char>::const_iterator begin,
std::vector<unsigned char>::const_iterator end, std::vector<unsigned char>::const_iterator end,
std::vector<unsigned char>& output, size_t output_offset, std::vector<unsigned char>& output, size_t output_offset,
bool resize_in = true, bool resize_out = true); bool resize_in = true, bool resize_out = true);
}; };
}; //namespace }; // namespace horcrux
#endif //HORCRUX_SRC_CRYPTO_H #endif // HORCRUX_SRC_CRYPTO_H

View File

@ -1,82 +1,82 @@
#include "horcrux.h"
#include <iostream> #include <iostream>
#include <exception> #include <exception>
#include "horcrux.h"
#include "utils.h" #include "utils.h"
namespace horcrux { namespace horcrux {
Horcrux::Horcrux(HorcruxOptions&& opt) : options(opt){ init(); } Horcrux::Horcrux(HorcruxOptions&& opt) : options(opt) { init(); }
Horcrux::Horcrux(const HorcruxOptions& opt) : options(opt){ init(); } Horcrux::Horcrux(const HorcruxOptions& opt) : options(opt) { init(); }
void Horcrux::init(){ void Horcrux::init() {
if (options.count <= 0){ if (options.count <= 0) {
throw std::invalid_argument("Invalid horcrux count"); throw std::invalid_argument("Invalid horcrux count");
} }
switch (options.mode){ switch (options.mode) {
case Mode::kEncrypt: case Mode::kEncrypt:
cipher = std::make_unique<AES256_CBC>(); cipher = std::make_unique<AES256_CBC>();
input = std::make_unique<FsPlainInput>(options.input[0]); input = std::make_unique<FsPlainInput>(options.input[0]);
output = std::make_unique<FsCryptoOutput>(options.output, options.count, output = std::make_unique<FsCryptoOutput>(options.output, options.count,
std::filesystem::path(options.input[0]).filename().string()); std::filesystem::path(options.input[0]).filename().string());
options.base64_key = to_base64(cipher->get_encryption_key()); options.base64_key = to_base64(cipher->get_encryption_key());
break; break;
case Mode::kDecrypt: case Mode::kDecrypt:
if (options.count != options.input.size()) if (options.count != options.input.size()) {
throw std::invalid_argument("Invalid horcrux count"); throw std::invalid_argument("Invalid horcrux count");
cipher = std::make_unique<AES256_CBC>(from_base64(options.base64_key)); }
input = std::make_unique<FsCryptoInput>(options.input); cipher = std::make_unique<AES256_CBC>(from_base64(options.base64_key));
output = std::make_unique<FsPlainOutput>(options.output); input = std::make_unique<FsCryptoInput>(options.input);
break; output = std::make_unique<FsPlainOutput>(options.output);
default: break;
throw std::invalid_argument("Invalid horcrux mode"); default:
} throw std::invalid_argument("Invalid horcrux mode");
}
} }
void Horcrux::execute(){ void Horcrux::execute() {
if (options.mode == Mode::kEncrypt) if (options.mode == Mode::kEncrypt)
output->write(cipher->encrypt(input->read())); output->write(cipher->encrypt(input->read()));
else else
output->write(cipher->decrypt(input->read())); output->write(cipher->decrypt(input->read()));
} }
static void print_usage(const std::string& program){ static void print_usage(const std::string& program) {
std::cout << "Usage:" << std::endl << std::cout << "Usage:" << std::endl <<
"\t\t" << program << " create -n <horcrux count> <input path> <output path>" << std::endl << "\t\t" << program << " create -n <horcrux count> <input path> <output path>" << std::endl <<
"\t\t" << program << " load -k <decryption key> <input files> <output_path>" << std::endl; "\t\t" << program << " load -k <decryption key> <input files> <output_path>" << std::endl;
} }
static void parse_error(const std::string& program, const std::string& error){ static void parse_error(const std::string& program, const std::string& error) {
print_usage(program); print_usage(program);
throw std::invalid_argument(error); throw std::invalid_argument(error);
} }
HorcruxOptions parse_arguments(std::vector<std::string>&& arguments){ HorcruxOptions parse_arguments(std::vector<std::string>&& arguments) {
if (arguments.size() < 6){ if (arguments.size() < 6) {
parse_error(std::string(arguments[0]), "Wrong argument number"); parse_error(std::string(arguments[0]), "Wrong argument number");
} }
HorcruxOptions opt; HorcruxOptions opt;
if (arguments[1] == "create") { if (arguments[1] == "create") {
if (arguments.size() != 6){ if (arguments.size() != 6) {
parse_error(std::string(arguments[0]), "Wrong argument number"); parse_error(std::string(arguments[0]), "Wrong argument number");
} }
opt.mode = Mode::kEncrypt; opt.mode = Mode::kEncrypt;
if (arguments[2] != "-n") if (arguments[2] != "-n")
parse_error(arguments[0], "create: unknown option " + arguments[2]); parse_error(arguments[0], "create: unknown option " + arguments[2]);
opt.count = std::stoi(arguments[3]); opt.count = std::stoi(arguments[3]);
opt.input.emplace_back(arguments[4]); opt.input.emplace_back(arguments[4]);
opt.output = arguments[5]; opt.output = arguments[5];
} else if (arguments[1] == "load"){ } else if (arguments[1] == "load") {
opt.mode = Mode::kDecrypt; opt.mode = Mode::kDecrypt;
if (arguments[2] != "-k") if (arguments[2] != "-k")
parse_error(arguments[0], "load: unknown option " + arguments[2]); parse_error(arguments[0], "load: unknown option " + arguments[2]);
opt.base64_key = arguments[3]; opt.base64_key = arguments[3];
opt.input.insert(opt.input.begin(), arguments.begin() + 4, arguments.end() - 1); opt.input.insert(opt.input.begin(), arguments.begin() + 4,
opt.count = opt.input.size(); arguments.end() - 1);
opt.output = arguments.back(); opt.count = opt.input.size();
} else { opt.output = arguments.back();
parse_error(arguments[0], "unknown mode: " + arguments[1]); } else {
} parse_error(arguments[0], "unknown mode: " + arguments[1]);
return opt; }
return opt;
} }
}; // namespace horcrux
}; //namespace

View File

@ -10,32 +10,30 @@
namespace horcrux { namespace horcrux {
struct HorcruxOptions { struct HorcruxOptions {
Mode mode; Mode mode;
int count; int count;
std::vector<std::string> input; std::vector<std::string> input;
std::string output; std::string output;
std::string base64_key; std::string base64_key;
}; };
class Horcrux { class Horcrux {
HorcruxOptions options;
std::unique_ptr<Cipher> cipher;
std::unique_ptr<Input> input;
std::unique_ptr<Output> output;
HorcruxOptions options; void init();
std::unique_ptr<Cipher> cipher;
std::unique_ptr<Input> input;
std::unique_ptr<Output> output;
void init();
public: public:
Horcrux(const HorcruxOptions& opt); explicit Horcrux(const HorcruxOptions& opt);
Horcrux(HorcruxOptions&& opt); explicit Horcrux(HorcruxOptions&& opt);
void execute(); void execute();
const Mode& mode() { return options.mode; } const Mode& mode() { return options.mode; }
const std::string& key() { return options.base64_key; } const std::string& key() { return options.base64_key; }
}; };
HorcruxOptions parse_arguments(std::vector<std::string>&& arguments); HorcruxOptions parse_arguments(std::vector<std::string>&& arguments);
}; //namespace }; // namespace horcrux
#endif //HORCRUX_HORCRUX_H #endif // HORCRUX_HORCRUX_H

View File

@ -1,98 +1,97 @@
#include <iostream>
#include "io.h" #include "io.h"
#include <iostream>
#include "utils.h" #include "utils.h"
namespace horcrux { namespace horcrux {
namespace fs = std::filesystem; namespace fs = std::filesystem;
FsPlainInput::FsPlainInput(const std::string& path) : file_path(fs::absolute(path)) FsPlainInput::FsPlainInput(const std::string& path)
{ : file_path(fs::absolute(path)) {
if (fs::status(path).type() != fs::file_type::regular){ if (fs::status(path).type() != fs::file_type::regular) {
throw std::invalid_argument("Input is not a regular file"); throw std::invalid_argument("Input is not a regular file");
} }
file_size = fs::file_size(file_path); file_size = fs::file_size(file_path);
if (file_size == 0){ if (file_size == 0) {
throw std::invalid_argument("Input is empty, nothing to encrypt"); throw std::invalid_argument("Input is empty, nothing to encrypt");
} }
file_stream = std::ifstream(file_path, std::ios::binary); file_stream = std::ifstream(file_path, std::ios::binary);
} }
std::vector<unsigned char> FsPlainInput::read(){ std::vector<unsigned char> FsPlainInput::read() {
std::vector<unsigned char> result(file_size); std::vector<unsigned char> result(file_size);
file_stream.read(reinterpret_cast<char*>(result.data()), file_size); file_stream.read(reinterpret_cast<char*>(result.data()), file_size);
return result; return result;
} }
FsCryptoInput::FsCryptoInput(const std::vector<std::string>& filenames) FsCryptoInput::FsCryptoInput(const std::vector<std::string>& filenames) {
{ if (filenames.empty()){
if (filenames.empty()){ throw std::invalid_argument("No files to decrypt");
throw std::invalid_argument("No files to decrypt"); }
} for (auto name : filenames) {
for (auto name : filenames){ auto path = absolute(fs::absolute({name}));
auto path = absolute(fs::absolute({name})); if (fs::status(path).type() != fs::file_type::regular) {
if (fs::status(path).type() != fs::file_type::regular){ throw std::invalid_argument("Input is not a regular file");
throw std::invalid_argument("Input is not a regular file"); }
} file_paths.emplace_back(path, fs::file_size(path));
file_paths.emplace_back(path, fs::file_size(path)); total_size += file_paths.back().second;
total_size += file_paths.back().second; }
} if (total_size == 0) {
if (total_size == 0){ throw std::invalid_argument("No data to decrypt");
throw std::invalid_argument("No data to decrypt"); }
}
} }
std::vector<unsigned char> FsCryptoInput::read(){ std::vector<unsigned char> FsCryptoInput::read() {
std::vector<unsigned char> result(total_size); std::vector<unsigned char> result(total_size);
size_t data_read{0}; size_t data_read{0};
for (auto& f : file_paths){ for (auto& f : file_paths) {
std::ifstream ifstream(f.first); std::ifstream ifstream(f.first);
ifstream.read(reinterpret_cast<char*>(result.data()) + data_read, f.second); ifstream.read(reinterpret_cast<char*>(result.data()) + data_read, f.second);
data_read += f.second; data_read += f.second;
} }
return result; return result;
} }
FsPlainOutput::FsPlainOutput(const std::string& filename) FsPlainOutput::FsPlainOutput(const std::string& filename)
: file_path(fs::absolute(filename)) : file_path(fs::absolute(filename)) {
{ if (fs::exists(file_path)
if (fs::exists(file_path) && fs::status(file_path).type() != fs::file_type::regular){ && fs::status(file_path).type() != fs::file_type::regular) {
throw std::invalid_argument("Output file is not a regular file"); throw std::invalid_argument("Output file is not a regular file");
} }
} }
size_t FsPlainOutput::write(const std::vector<unsigned char>& to_write){ size_t FsPlainOutput::write(const std::vector<unsigned char>& to_write) {
std::ofstream out(file_path, std::ios::binary); std::ofstream out(file_path, std::ios::binary);
out.write(reinterpret_cast<const char*>(to_write.data()), to_write.size()); out.write(reinterpret_cast<const char*>(to_write.data()), to_write.size());
return to_write.size(); return to_write.size();
} }
FsCryptoOutput::FsCryptoOutput(const std::string& folder, const int horcrux_num, FsCryptoOutput::FsCryptoOutput(const std::string& folder, const int horcrux_num,
const std::string& filename, const size_t horcrux_size) const std::string& filename, const size_t horcrux_size)
: folder_path(fs::absolute(folder)), base_name(filename), : folder_path(fs::absolute(folder)), base_name(filename),
num(horcrux_num), size(horcrux_size) num(horcrux_num), size(horcrux_size) {
{ if (fs::status(folder_path).type() != fs::file_type::directory) {
if (fs::status(folder_path).type() != fs::file_type::directory){ throw std::invalid_argument("Output is not a directory");
throw std::invalid_argument("Output is not a directory"); }
}
if (horcrux_num <= 0){ if (horcrux_num <= 0) {
throw std::invalid_argument("Invalid horcrux num"); throw std::invalid_argument("Invalid horcrux num");
} }
} }
size_t FsCryptoOutput::write(const std::vector<unsigned char>& to_write){ size_t FsCryptoOutput::write(const std::vector<unsigned char>& to_write) {
size = to_write.size() / num; size = to_write.size() / num;
std::ofstream f; std::ofstream f;
created_files.clear(); created_files.clear();
size_t data_written{0}; size_t data_written{0};
for (int i = 0; i < num; ++i){ 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); created_files.emplace_back(folder_path / name);
f = std::ofstream(created_files.back(), f = std::ofstream(created_files.back(),
std::ios::binary | std::ios::trunc); std::ios::binary | std::ios::trunc);
auto chunk_size = i + 1 != num ? size : size + to_write.size() % size; auto chunk_size = i + 1 != num ? size : size + to_write.size() % size;
f.write(reinterpret_cast<const char*>(to_write.data()) + data_written, chunk_size); f.write(reinterpret_cast<const char*>(to_write.data()) + data_written,
data_written += chunk_size; chunk_size);
} data_written += chunk_size;
return data_written; }
return data_written;
} }
}; };

View File

@ -4,16 +4,17 @@
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <vector> #include <vector>
#include <utility>
namespace horcrux { namespace horcrux {
class Input { class Input {
public: public:
virtual std::vector<unsigned char> read() = 0; virtual std::vector<unsigned char> read() = 0;
}; };
class Output { class Output {
public: public:
virtual size_t write(const std::vector<unsigned char>& data) = 0; virtual size_t write(const std::vector<unsigned char>& data) = 0;
}; };
class PlainInput : public Input {}; class PlainInput : public Input {};
class CryptoInput : public Input {}; class CryptoInput : public Input {};
@ -21,48 +22,49 @@ class PlainOutput : public Output {};
class CryptoOutput : public Output {}; class CryptoOutput : public Output {};
class FsPlainInput : public Input { class FsPlainInput : public Input {
std::filesystem::path file_path; std::filesystem::path file_path;
size_t file_size; size_t file_size;
std::ifstream file_stream; std::ifstream file_stream;
FsPlainInput() = delete; FsPlainInput() = delete;
public: public:
FsPlainInput(const std::string& path); explicit FsPlainInput(const std::string& path);
std::vector<unsigned char> read() override; std::vector<unsigned char> read() override;
}; };
class FsCryptoInput : public Input{ class FsCryptoInput : public Input{
std::vector<std::pair<std::filesystem::path, size_t>> file_paths; std::vector<std::pair<std::filesystem::path, size_t>> file_paths;
size_t total_size{0}; size_t total_size{0};
FsCryptoInput() = delete; FsCryptoInput() = delete;
public: public:
FsCryptoInput(const std::vector<std::string>& filenames); explicit FsCryptoInput(const std::vector<std::string>& filenames);
std::vector<unsigned char> read() override; std::vector<unsigned char> read() override;
}; };
class FsPlainOutput : public Output { class FsPlainOutput : public Output {
std::filesystem::path file_path; std::filesystem::path file_path;
FsPlainOutput() = delete; FsPlainOutput() = delete;
public: public:
FsPlainOutput(const std::string& filename); explicit FsPlainOutput(const std::string& filename);
size_t write(const std::vector<unsigned char>& to_write) override; size_t write(const std::vector<unsigned char>& to_write) override;
}; };
class FsCryptoOutput : public Output { class FsCryptoOutput : public Output {
std::filesystem::path folder_path; std::filesystem::path folder_path;
std::string base_name; std::string base_name;
int num; int num;
size_t size; size_t size;
FsCryptoOutput() = delete; FsCryptoOutput() = delete;
public: public:
std::vector<std::filesystem::path> created_files; std::vector<std::filesystem::path> created_files;
FsCryptoOutput(const std::string& folder, const int horcrux_num, FsCryptoOutput(const std::string& folder, const int horcrux_num,
const std::string& filename = "horcrux", const size_t horcrux_size = 0); const std::string& filename = "horcrux",
size_t write(const std::vector<unsigned char>& to_write) override; const size_t horcrux_size = 0);
size_t write(const std::vector<unsigned char>& to_write) override;
}; };
}; }; // namespace horcrux
#endif //HORCRUX_SRC_IO_H #endif // HORCRUX_SRC_IO_H

View File

@ -3,28 +3,28 @@
#include "horcrux.h" #include "horcrux.h"
int main(const int argc, const char *argv[]) { int main(const int argc, const char *argv[]) {
int ret = -1; int ret = -1;
std::vector<std::string> arguments; std::vector<std::string> arguments;
for (int i = 0; i < argc; ++i){ for (int i = 0; i < argc; ++i) {
arguments.emplace_back(argv[i]); arguments.emplace_back(argv[i]);
} }
try { try {
horcrux::Horcrux h(horcrux::parse_arguments(std::move(arguments))); horcrux::Horcrux h(horcrux::parse_arguments(std::move(arguments)));
h.execute(); h.execute();
if (h.mode() == horcrux::Mode::kEncrypt){ if (h.mode() == horcrux::Mode::kEncrypt) {
//print encryption key to stdout // print encryption key to stdout
std::cout << h.key() << std::endl; std::cout << h.key() << std::endl;
} }
ret = 0; ret = 0;
} catch (std::invalid_argument& ex){ } catch (std::invalid_argument& ex) {
std::cerr << "Error: Invalid arguments. " << ex.what() << std::endl; std::cerr << "Error: Invalid arguments. " << ex.what() << std::endl;
} catch (std::runtime_error& ex){ } catch (std::runtime_error& ex) {
std::cerr << "Runtime error: " << ex.what() << std::endl; std::cerr << "Runtime error: " << ex.what() << std::endl;
} catch (std::exception& ex){ } catch (std::exception& ex) {
std::cerr << "Unknown error: " << ex.what() << std::endl; std::cerr << "Unknown error: " << ex.what() << std::endl;
} }
return ret; return ret;
} }

View File

@ -1,41 +1,39 @@
#include "utils.h"
#include <openssl/rand.h>
#include <boost/archive/iterators/binary_from_base64.hpp> #include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/base64_from_binary.hpp> #include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/transform_width.hpp> #include <boost/archive/iterators/transform_width.hpp>
#include <openssl/rand.h>
#include "utils.h" std::string horcrux::to_base64(const std::vector<unsigned char>& binary) {
using namespace boost::archive::iterators;
std::string horcrux::to_base64(const std::vector<unsigned char>& binary) using It = base64_from_binary<transform_width<
{ std::vector<unsigned char>::const_iterator, 6, 8>>;
using namespace boost::archive::iterators; auto base64 = std::string(It(binary.begin()), It(binary.end()));
using It = base64_from_binary<transform_width<std::vector<unsigned char>::const_iterator, 6, 8>>; // Add padding.
auto base64 = std::string(It(binary.begin()), It(binary.end())); return base64.append((3 - binary.size() % 3) % 3, '=');
// Add padding.
return base64.append((3 - binary.size() % 3) % 3, '=');
} }
std::vector<unsigned char> horcrux::from_base64(const std::string& base64) std::vector<unsigned char> horcrux::from_base64(const std::string& base64) {
{ using namespace boost::archive::iterators;
using namespace boost::archive::iterators; using It = transform_width<binary_from_base64<std::string::const_iterator>,
using It = transform_width<binary_from_base64<std::string::const_iterator>, 8, 6>; 8, 6>;
auto binary = std::vector<unsigned char>(It(base64.begin()), It(base64.end())); auto binary = std::vector<unsigned char>(It(base64.begin()),
// Remove padding. It(base64.end()));
auto length = base64.size(); // Remove padding.
if(binary.size() > 2 && base64[length - 1] == '=' && base64[length - 2] == '=') auto length = base64.size();
{ if (binary.size() > 2 && base64[length - 1] == '='
binary.erase(binary.end() - 2, binary.end()); && base64[length - 2] == '=') {
} binary.erase(binary.end() - 2, binary.end());
else if(binary.size() > 1 && base64[length - 1] == '=') } else if (binary.size() > 1 && base64[length - 1] == '=') {
{ binary.erase(binary.end() - 1, binary.end());
binary.erase(binary.end() - 1, binary.end()); }
} return binary;
return binary;
} }
std::vector<unsigned char> horcrux::generate_random(const size_t size){ std::vector<unsigned char> horcrux::generate_random(const size_t size) {
std::vector<unsigned char> res(size); std::vector<unsigned char> res(size);
if(!RAND_bytes(res.data(), size)){ if (!RAND_bytes(res.data(), size)) {
throw std::exception(); throw std::exception();
} }
return res; return res;
} }

View File

@ -11,4 +11,4 @@ std::vector<unsigned char> from_base64(const std::string& base64);
std::vector<unsigned char> generate_random(const size_t buf_len); std::vector<unsigned char> generate_random(const size_t buf_len);
} }
#endif //HORCRUX_SRC_UTILS_H #endif // HORCRUX_SRC_UTILS_H

View File

@ -1,11 +1,11 @@
set(BINARY ${CMAKE_PROJECT_NAME}_test) set(BINARY ${CMAKE_PROJECT_NAME}_test)
add_executable(${BINARY} add_executable(${BINARY}
main.cpp main.cpp
crypto-test.cpp crypto-test.cpp
io-test.cpp io-test.cpp
utils-test.cpp utils-test.cpp
integration-test.cpp integration-test.cpp
) )
add_test(NAME test COMMAND ${BINARY}) add_test(NAME test COMMAND ${BINARY})
@ -14,5 +14,5 @@ target_link_libraries(${BINARY} PUBLIC ${CMAKE_PROJECT_NAME}_lib gtest)
#Copy files needed for unit tests #Copy files needed for unit tests
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test_work_dir file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test_work_dir
DESTINATION ${CMAKE_BINARY_DIR}) DESTINATION ${CMAKE_BINARY_DIR})
add_definitions(-DTEST_WORK_DIR="${CMAKE_BINARY_DIR}/test_work_dir") add_definitions(-DTEST_WORK_DIR="${CMAKE_BINARY_DIR}/test_work_dir")

View File

@ -6,94 +6,94 @@
using namespace horcrux; using namespace horcrux;
TEST(CryptoTest, encrypt1){ TEST(CryptoTest, encrypt1){
const std::vector<unsigned char> plaintext(test1_str.begin(), test1_str.end()); const std::vector<unsigned char> plaintext(test1_str.begin(), test1_str.end());
size_t output_len = plaintext.size() + 16; size_t output_len = plaintext.size() + 16;
std::vector<unsigned char> output(output_len); std::vector<unsigned char> output(output_len);
const std::vector<unsigned char> key(test1_key.begin(), test1_key.end()); const std::vector<unsigned char> key(test1_key.begin(), test1_key.end());
const std::vector<unsigned char> iv(test1_iv.begin(), test1_iv.end()); const std::vector<unsigned char> iv(test1_iv.begin(), test1_iv.end());
AES256_CBC a; AES256_CBC a;
a.encrypt(key, iv, plaintext, output); a.encrypt(key, iv, plaintext, output);
EXPECT_EQ(test1_enc, output); EXPECT_EQ(test1_enc, output);
} }
TEST(CryptoTest, encrypt2){ TEST(CryptoTest, encrypt2){
const std::vector<unsigned char> plaintext(test1_str.begin(), test1_str.end()); const std::vector<unsigned char> plaintext(test1_str.begin(), test1_str.end());
//size_t output_len = plaintext.size() + 16; //size_t output_len = plaintext.size() + 16;
//std::vector<unsigned char> output(output_len); //std::vector<unsigned char> output(output_len);
const std::vector<unsigned char> key(test1_key.begin(), test1_key.end()); const std::vector<unsigned char> key(test1_key.begin(), test1_key.end());
const std::vector<unsigned char> iv(test1_iv.begin(), test1_iv.end()); const std::vector<unsigned char> iv(test1_iv.begin(), test1_iv.end());
AES256_CBC a; AES256_CBC a;
auto output = a.encrypt(key, iv, plaintext); auto output = a.encrypt(key, iv, plaintext);
auto temp = iv; auto temp = iv;
temp.insert(temp.end(), test1_enc.begin(), test1_enc.end()); temp.insert(temp.end(), test1_enc.begin(), test1_enc.end());
EXPECT_EQ(temp.size(), output.size()); EXPECT_EQ(temp.size(), output.size());
EXPECT_EQ(temp, output); EXPECT_EQ(temp, output);
} }
TEST(CryptoTest, encrypt3){ TEST(CryptoTest, encrypt3){
const std::vector<unsigned char> plaintext(test1_str.begin(), test1_str.end()); const std::vector<unsigned char> plaintext(test1_str.begin(), test1_str.end());
//size_t output_len = plaintext.size() + 16; //size_t output_len = plaintext.size() + 16;
//std::vector<unsigned char> output(output_len); //std::vector<unsigned char> output(output_len);
const std::vector<unsigned char> key(test1_key.begin(), test1_key.end()); const std::vector<unsigned char> key(test1_key.begin(), test1_key.end());
const std::vector<unsigned char> iv(test1_iv.begin(), test1_iv.end()); const std::vector<unsigned char> iv(test1_iv.begin(), test1_iv.end());
AES256_CBC a(key); AES256_CBC a(key);
auto output = a.encrypt(plaintext); auto output = a.encrypt(plaintext);
auto temp = iv; auto temp = iv;
temp.insert(temp.end(), test1_enc.begin(), test1_enc.end()); temp.insert(temp.end(), test1_enc.begin(), test1_enc.end());
EXPECT_EQ(temp.size(), output.size()); EXPECT_EQ(temp.size(), output.size());
} }
TEST(CryptoTest, decrypt1){ TEST(CryptoTest, decrypt1){
const std::vector<unsigned char> plaintext(test1_str.begin(), test1_str.end()); const std::vector<unsigned char> plaintext(test1_str.begin(), test1_str.end());
size_t output_len = test1_enc.size(); size_t output_len = test1_enc.size();
std::vector<unsigned char> output(output_len); std::vector<unsigned char> output(output_len);
const std::vector<unsigned char> key(test1_key.begin(), test1_key.end()); const std::vector<unsigned char> key(test1_key.begin(), test1_key.end());
const std::vector<unsigned char> iv(test1_iv.begin(), test1_iv.end()); const std::vector<unsigned char> iv(test1_iv.begin(), test1_iv.end());
AES256_CBC a; AES256_CBC a;
a.decrypt(key, iv, test1_enc, output); a.decrypt(key, iv, test1_enc, output);
EXPECT_EQ(plaintext, output); EXPECT_EQ(plaintext, output);
} }
TEST(CryptoTest, decrypt2){ TEST(CryptoTest, decrypt2){
const std::vector<unsigned char> plaintext(test1_str.begin(), test1_str.end()); const std::vector<unsigned char> plaintext(test1_str.begin(), test1_str.end());
size_t output_len = test1_enc.size(); size_t output_len = test1_enc.size();
const std::vector<unsigned char> key(test1_key.begin(), test1_key.end()); const std::vector<unsigned char> key(test1_key.begin(), test1_key.end());
const std::vector<unsigned char> iv(test1_iv.begin(), test1_iv.end()); const std::vector<unsigned char> iv(test1_iv.begin(), test1_iv.end());
// constructs encrypted input (iv + encrypted_data) // constructs encrypted input (iv + encrypted_data)
auto input = std::vector<unsigned char>(iv); auto input = std::vector<unsigned char>(iv);
input.insert(input.end(),test1_enc.begin(), test1_enc.end()); input.insert(input.end(),test1_enc.begin(), test1_enc.end());
AES256_CBC a; AES256_CBC a;
auto output = a.decrypt(key, input); auto output = a.decrypt(key, input);
EXPECT_EQ(plaintext, output); EXPECT_EQ(plaintext, output);
} }
TEST(CryptoTest, decrypt3){ TEST(CryptoTest, decrypt3){
const std::vector<unsigned char> plaintext(test1_str.begin(), test1_str.end()); const std::vector<unsigned char> plaintext(test1_str.begin(), test1_str.end());
size_t output_len = test1_enc.size(); size_t output_len = test1_enc.size();
const std::vector<unsigned char> key(test1_key.begin(), test1_key.end()); const std::vector<unsigned char> key(test1_key.begin(), test1_key.end());
const std::vector<unsigned char> iv(test1_iv.begin(), test1_iv.end()); const std::vector<unsigned char> iv(test1_iv.begin(), test1_iv.end());
// constructs encrypted input (iv + encrypted_data) // constructs encrypted input (iv + encrypted_data)
auto input = std::vector<unsigned char>(iv); auto input = std::vector<unsigned char>(iv);
input.insert(input.end(),test1_enc.begin(), test1_enc.end()); input.insert(input.end(),test1_enc.begin(), test1_enc.end());
AES256_CBC a(key); AES256_CBC a(key);
auto output = a.decrypt(input); auto output = a.decrypt(input);
EXPECT_EQ(plaintext, output); EXPECT_EQ(plaintext, output);
} }
TEST(CryptoTest, endToEnd){ TEST(CryptoTest, endToEnd){
const std::vector<unsigned char> plaintext(test1_str.begin(), test1_str.end()); const std::vector<unsigned char> plaintext(test1_str.begin(), test1_str.end());
AES256_CBC a; AES256_CBC a;
auto crypto = a.encrypt(plaintext); auto crypto = a.encrypt(plaintext);
EXPECT_GT(crypto.size(), plaintext.size()); EXPECT_GT(crypto.size(), plaintext.size());
auto decrypted = a.decrypt(crypto); auto decrypted = a.decrypt(crypto);
EXPECT_EQ(plaintext, decrypted); EXPECT_EQ(plaintext, decrypted);
} }

View File

@ -5,124 +5,124 @@
using namespace horcrux; using namespace horcrux;
TEST(IntegrationTest, EndToEndEncryptDecrypt){ TEST(IntegrationTest, EndToEndEncryptDecrypt){
auto buf = generic_read_file(image); auto buf = generic_read_file(image);
//Prepare encrypt operation //Prepare encrypt operation
auto in = FsPlainInput(image); auto in = FsPlainInput(image);
auto cipher = AES256_CBC(); auto cipher = AES256_CBC();
auto out = FsCryptoOutput(folder, 3); auto out = FsCryptoOutput(folder, 3);
// Perform encrypt operation // Perform encrypt operation
out.write(cipher.encrypt(in.read())); out.write(cipher.encrypt(in.read()));
//Prepare decrypt operation //Prepare decrypt operation
auto in2 = FsCryptoInput(get_created_filenames(out)); auto in2 = FsCryptoInput(get_created_filenames(out));
//Perform decrypt operation //Perform decrypt operation
auto buf2 = cipher.decrypt(in2.read()); auto buf2 = cipher.decrypt(in2.read());
//check outcome //check outcome
EXPECT_EQ(buf, buf2); EXPECT_EQ(buf, buf2);
auto out2 = FsPlainOutput(noexist); auto out2 = FsPlainOutput(noexist);
out2.write(cipher.decrypt(in2.read())); out2.write(cipher.decrypt(in2.read()));
auto buf3 = generic_read_file(noexist); auto buf3 = generic_read_file(noexist);
EXPECT_EQ(buf, buf3); EXPECT_EQ(buf, buf3);
delete_created_files(out); delete_created_files(out);
std::filesystem::remove(noexist); std::filesystem::remove(noexist);
} }
TEST(IntegrationTest, HorcruxOptions){ TEST(IntegrationTest, HorcruxOptions){
HorcruxOptions options { HorcruxOptions options {
.mode = Mode::kEncrypt, .mode = Mode::kEncrypt,
.count = -1, .count = -1,
.input = {noexist}, .input = {noexist},
.output = {image} .output = {image}
}; };
EXPECT_THROW(Horcrux {options}, std::invalid_argument); EXPECT_THROW(Horcrux {options}, std::invalid_argument);
options.count = 1; options.count = 1;
EXPECT_THROW(Horcrux {options}, std::invalid_argument); EXPECT_THROW(Horcrux {options}, std::invalid_argument);
options.input = {image}; options.input = {image};
EXPECT_THROW(Horcrux {options}, std::invalid_argument); EXPECT_THROW(Horcrux {options}, std::invalid_argument);
options.output = {folder}; options.output = {folder};
options.count = 0; options.count = 0;
EXPECT_THROW(Horcrux {options}, std::invalid_argument); EXPECT_THROW(Horcrux {options}, std::invalid_argument);
options.count = 2; options.count = 2;
EXPECT_NO_THROW(Horcrux {options}); EXPECT_NO_THROW(Horcrux {options});
options.mode = Mode::kDecrypt; options.mode = Mode::kDecrypt;
EXPECT_THROW(Horcrux {options}, std::invalid_argument); EXPECT_THROW(Horcrux {options}, std::invalid_argument);
options.input = {image, text}; options.input = {image, text};
options.count = 1; options.count = 1;
EXPECT_THROW(Horcrux {options}, std::invalid_argument); EXPECT_THROW(Horcrux {options}, std::invalid_argument);
options.output = {noexist}; options.output = {noexist};
EXPECT_THROW(Horcrux {options}, std::invalid_argument); EXPECT_THROW(Horcrux {options}, std::invalid_argument);
options.count = 2; options.count = 2;
EXPECT_THROW(Horcrux {options}, std::invalid_argument); EXPECT_THROW(Horcrux {options}, std::invalid_argument);
options.base64_key = to_base64(generate_random(32)); options.base64_key = to_base64(generate_random(32));
EXPECT_NO_THROW(Horcrux {options}); EXPECT_NO_THROW(Horcrux {options});
} }
TEST(IntegrationTest, HorcruxEncryptiDecrypt) { TEST(IntegrationTest, HorcruxEncryptiDecrypt) {
HorcruxOptions options { HorcruxOptions options {
.mode = Mode::kEncrypt, .mode = Mode::kEncrypt,
.count = 3, .count = 3,
.input = {image}, .input = {image},
.output = {folder} .output = {folder}
}; };
Horcrux enc{options}; Horcrux enc{options};
enc.execute(); enc.execute();
auto key = enc.key(); auto key = enc.key();
HorcruxOptions options2 { HorcruxOptions options2 {
.mode = Mode::kDecrypt, .mode = Mode::kDecrypt,
.count = 3, .count = 3,
.input = {get_encrypted_files(folder, image)}, .input = {get_encrypted_files(folder, image)},
.output = {noexist}, .output = {noexist},
.base64_key = key .base64_key = key
}; };
Horcrux dec{options2}; Horcrux dec{options2};
dec.execute(); dec.execute();
//Compare input and ouput files //Compare input and ouput files
EXPECT_EQ(generic_read_file(image), generic_read_file(noexist)); EXPECT_EQ(generic_read_file(image), generic_read_file(noexist));
std::filesystem::remove(noexist); std::filesystem::remove(noexist);
std::for_each(options2.input.begin(), options2.input.end(), [](auto& p){ std::for_each(options2.input.begin(), options2.input.end(), [](auto& p){
std::filesystem::remove(p);}); std::filesystem::remove(p);});
} }
TEST(IntegrationTest, arguments){ TEST(IntegrationTest, arguments){
EXPECT_THROW( EXPECT_THROW(
parse_arguments({"horcrux", "create", "-n", "4", "input_file"}), parse_arguments({"horcrux", "create", "-n", "4", "input_file"}),
std::invalid_argument); std::invalid_argument);
EXPECT_THROW( EXPECT_THROW(
parse_arguments({"horcrux", "pippo", "-n", "4", "input_file"}), parse_arguments({"horcrux", "pippo", "-n", "4", "input_file"}),
std::invalid_argument); std::invalid_argument);
EXPECT_THROW( EXPECT_THROW(
parse_arguments({"horcrux", "create", "-n", "4", "input_file", "output_file", "garbage"}), parse_arguments({"horcrux", "create", "-n", "4", "input_file", "output_file", "garbage"}),
std::invalid_argument); std::invalid_argument);
EXPECT_THROW( EXPECT_THROW(
parse_arguments({"horcrux", "create", "-h", "4", "input_file", "output_file"}), parse_arguments({"horcrux", "create", "-h", "4", "input_file", "output_file"}),
std::invalid_argument); std::invalid_argument);
EXPECT_THROW( EXPECT_THROW(
parse_arguments({"horcrux", "create", "-n", "boh", "input_file", "output_file"}), parse_arguments({"horcrux", "create", "-n", "boh", "input_file", "output_file"}),
std::invalid_argument); std::invalid_argument);
EXPECT_NO_THROW( EXPECT_NO_THROW(
parse_arguments({"horcrux", "create", "-n", "4", "input_file", "output_file"})); parse_arguments({"horcrux", "create", "-n", "4", "input_file", "output_file"}));
EXPECT_THROW( EXPECT_THROW(
parse_arguments({"horcrux", "load", "-n", "4", "input_file"}), parse_arguments({"horcrux", "load", "-n", "4", "input_file"}),
std::invalid_argument); std::invalid_argument);
EXPECT_THROW( EXPECT_THROW(
parse_arguments({"horcrux", "load", "-k", "lshgflushlgkjusghl", "input_file"}), parse_arguments({"horcrux", "load", "-k", "lshgflushlgkjusghl", "input_file"}),
std::invalid_argument); std::invalid_argument);
EXPECT_THROW( EXPECT_THROW(
parse_arguments({"horcrux", "load", "-r", "lshgflushlgkjusghl", "input", "input", "output"}), parse_arguments({"horcrux", "load", "-r", "lshgflushlgkjusghl", "input", "input", "output"}),
std::invalid_argument); std::invalid_argument);
EXPECT_THROW( EXPECT_THROW(
parse_arguments({"horcrux", "load", "-k", "lshgflushlgkjusghl", "input"}), parse_arguments({"horcrux", "load", "-k", "lshgflushlgkjusghl", "input"}),
std::invalid_argument); std::invalid_argument);
EXPECT_NO_THROW( EXPECT_NO_THROW(
parse_arguments({"horcrux", "load", "-k", "lshgflushlgkjusghl", "input", "output"})); parse_arguments({"horcrux", "load", "-k", "lshgflushlgkjusghl", "input", "output"}));
EXPECT_NO_THROW( EXPECT_NO_THROW(
parse_arguments({"horcrux", "load", "-k", "lshgflushlgkjusghl", "input", "input", "output"})); parse_arguments({"horcrux", "load", "-k", "lshgflushlgkjusghl", "input", "input", "output"}));
} }

View File

@ -3,174 +3,174 @@
#include "test.h" #include "test.h"
TEST(IoTests, FsPlainInput) { TEST(IoTests, FsPlainInput) {
EXPECT_THROW(horcrux::FsPlainInput input{noexist}, std::invalid_argument); EXPECT_THROW(horcrux::FsPlainInput input{noexist}, std::invalid_argument);
EXPECT_THROW(horcrux::FsPlainInput input{folder}, std::invalid_argument); EXPECT_THROW(horcrux::FsPlainInput input{folder}, std::invalid_argument);
EXPECT_THROW(horcrux::FsPlainInput input{empty}, std::invalid_argument); EXPECT_THROW(horcrux::FsPlainInput input{empty}, std::invalid_argument);
EXPECT_NO_THROW(horcrux::FsPlainInput input{text}); EXPECT_NO_THROW(horcrux::FsPlainInput input{text});
EXPECT_NO_THROW(horcrux::FsPlainInput input{image}); EXPECT_NO_THROW(horcrux::FsPlainInput input{image});
} }
TEST(IoTests, FsPlainInputReadText) { TEST(IoTests, FsPlainInputReadText) {
auto input = horcrux::FsPlainInput{text}; auto input = horcrux::FsPlainInput{text};
auto buf = generic_read_file(text); auto buf = generic_read_file(text);
EXPECT_EQ(buf, input.read()); EXPECT_EQ(buf, input.read());
} }
TEST(IoTests, FsPlainInputReadImg) { TEST(IoTests, FsPlainInputReadImg) {
auto input = horcrux::FsPlainInput{image}; auto input = horcrux::FsPlainInput{image};
auto buf = generic_read_file(image); auto buf = generic_read_file(image);
EXPECT_EQ(buf, input.read()); EXPECT_EQ(buf, input.read());
} }
TEST(IoTests, FsCryptoOutput) { TEST(IoTests, FsCryptoOutput) {
EXPECT_THROW(horcrux::FsCryptoOutput output(noexist, 1), std::invalid_argument); EXPECT_THROW(horcrux::FsCryptoOutput output(noexist, 1), std::invalid_argument);
EXPECT_NO_THROW(horcrux::FsCryptoOutput output(folder, 1)); EXPECT_NO_THROW(horcrux::FsCryptoOutput output(folder, 1));
EXPECT_THROW(horcrux::FsCryptoOutput output(folder, 0), std::invalid_argument); EXPECT_THROW(horcrux::FsCryptoOutput output(folder, 0), std::invalid_argument);
EXPECT_THROW(horcrux::FsCryptoOutput output(empty, 1), std::invalid_argument); EXPECT_THROW(horcrux::FsCryptoOutput output(empty, 1), std::invalid_argument);
EXPECT_THROW(horcrux::FsCryptoOutput output(text, 1), std::invalid_argument); EXPECT_THROW(horcrux::FsCryptoOutput output(text, 1), std::invalid_argument);
EXPECT_THROW(horcrux::FsCryptoOutput output(image, 1), std::invalid_argument); EXPECT_THROW(horcrux::FsCryptoOutput output(image, 1), std::invalid_argument);
} }
TEST(IoTests, FsCryptoOutputWriteImage){ TEST(IoTests, FsCryptoOutputWriteImage){
auto ifstream = std::ifstream{image, std::ios::binary}; auto ifstream = std::ifstream{image, std::ios::binary};
auto buf = generic_read_file(image); auto buf = generic_read_file(image);
horcrux::FsCryptoOutput out(folder, 10); horcrux::FsCryptoOutput out(folder, 10);
auto written = out.write(buf); auto written = out.write(buf);
EXPECT_EQ(written, buf.size()); EXPECT_EQ(written, buf.size());
EXPECT_EQ(10, out.created_files.size()); EXPECT_EQ(10, out.created_files.size());
delete_created_files(out); delete_created_files(out);
} }
TEST(IoTests, FsCryptoOutputWriteText){ TEST(IoTests, FsCryptoOutputWriteText){
auto buf = generic_read_file(text); auto buf = generic_read_file(text);
horcrux::FsCryptoOutput out(folder, 2); horcrux::FsCryptoOutput out(folder, 2);
auto written = out.write(buf); auto written = out.write(buf);
EXPECT_EQ(written, buf.size()); EXPECT_EQ(written, buf.size());
EXPECT_EQ(2, out.created_files.size()); EXPECT_EQ(2, out.created_files.size());
delete_created_files(out); delete_created_files(out);
} }
TEST(IoTest, FsCryptoInput){ TEST(IoTest, FsCryptoInput){
EXPECT_THROW(horcrux::FsCryptoInput output({noexist, text, image}), std::invalid_argument); EXPECT_THROW(horcrux::FsCryptoInput output({noexist, text, image}), std::invalid_argument);
EXPECT_THROW(horcrux::FsCryptoInput output({folder, text, image}), std::invalid_argument); EXPECT_THROW(horcrux::FsCryptoInput output({folder, text, image}), std::invalid_argument);
EXPECT_THROW(horcrux::FsCryptoInput output(std::vector<std::string>{}), std::invalid_argument); EXPECT_THROW(horcrux::FsCryptoInput output(std::vector<std::string>{}), std::invalid_argument);
EXPECT_THROW(horcrux::FsCryptoInput output({empty}), std::invalid_argument); EXPECT_THROW(horcrux::FsCryptoInput output({empty}), std::invalid_argument);
EXPECT_THROW(horcrux::FsCryptoInput output({empty, empty}), std::invalid_argument); EXPECT_THROW(horcrux::FsCryptoInput output({empty, empty}), std::invalid_argument);
EXPECT_NO_THROW(horcrux::FsCryptoInput output({empty, empty, text})); EXPECT_NO_THROW(horcrux::FsCryptoInput output({empty, empty, text}));
EXPECT_NO_THROW(horcrux::FsCryptoInput output({image, empty, text})); EXPECT_NO_THROW(horcrux::FsCryptoInput output({image, empty, text}));
} }
TEST(IoTest, FsCryptoInputImage){ TEST(IoTest, FsCryptoInputImage){
auto buf = generic_read_file(image); auto buf = generic_read_file(image);
//split image using FsCryptoOutput //split image using FsCryptoOutput
auto out = horcrux::FsCryptoOutput(folder, 7); auto out = horcrux::FsCryptoOutput(folder, 7);
auto written = out.write(buf); auto written = out.write(buf);
EXPECT_EQ(written, buf.size()); EXPECT_EQ(written, buf.size());
auto files = get_created_filenames(out); auto files = get_created_filenames(out);
auto in = horcrux::FsCryptoInput(files); auto in = horcrux::FsCryptoInput(files);
auto read = in.read(); auto read = in.read();
EXPECT_EQ(read, buf); EXPECT_EQ(read, buf);
files.push_back(text); files.push_back(text);
in = horcrux::FsCryptoInput(files); in = horcrux::FsCryptoInput(files);
read = in.read(); read = in.read();
EXPECT_NE(read, buf); EXPECT_NE(read, buf);
delete_created_files(out); delete_created_files(out);
} }
TEST(IoTest, FsPlainOuput){ TEST(IoTest, FsPlainOuput){
EXPECT_NO_THROW(horcrux::FsPlainOutput output{noexist}); EXPECT_NO_THROW(horcrux::FsPlainOutput output{noexist});
EXPECT_THROW(horcrux::FsPlainOutput output{folder}, std::invalid_argument); EXPECT_THROW(horcrux::FsPlainOutput output{folder}, std::invalid_argument);
EXPECT_NO_THROW(horcrux::FsPlainOutput output{empty}); EXPECT_NO_THROW(horcrux::FsPlainOutput output{empty});
EXPECT_NO_THROW(horcrux::FsPlainOutput output{text}); EXPECT_NO_THROW(horcrux::FsPlainOutput output{text});
EXPECT_NO_THROW(horcrux::FsPlainOutput output{image}); EXPECT_NO_THROW(horcrux::FsPlainOutput output{image});
} }
TEST(IoTest, FsPlainOutputWrite){ TEST(IoTest, FsPlainOutputWrite){
auto buf = generic_read_file(image); auto buf = generic_read_file(image);
auto out = horcrux::FsPlainOutput(noexist); auto out = horcrux::FsPlainOutput(noexist);
auto written = out.write(buf); auto written = out.write(buf);
EXPECT_EQ(written, buf.size()); EXPECT_EQ(written, buf.size());
auto buf2 = generic_read_file(noexist); auto buf2 = generic_read_file(noexist);
EXPECT_EQ(buf, buf2); EXPECT_EQ(buf, buf2);
std::filesystem::remove(noexist); std::filesystem::remove(noexist);
} }
TEST(IoTest, PlainToPlain){ TEST(IoTest, PlainToPlain){
auto buf = generic_read_file(image); auto buf = generic_read_file(image);
auto in = horcrux::FsPlainInput(image); auto in = horcrux::FsPlainInput(image);
auto out = horcrux::FsPlainOutput(noexist); auto out = horcrux::FsPlainOutput(noexist);
//Execute Plain To Plain //Execute Plain To Plain
out.write(in.read()); out.write(in.read());
//Check outcome //Check outcome
auto buf2 = generic_read_file(noexist); auto buf2 = generic_read_file(noexist);
EXPECT_EQ(buf, buf2); EXPECT_EQ(buf, buf2);
std::filesystem::remove(noexist); std::filesystem::remove(noexist);
} }
TEST(IoTest, PlainToCrypto){ TEST(IoTest, PlainToCrypto){
auto buf = generic_read_file(image); auto buf = generic_read_file(image);
auto in = horcrux::FsPlainInput(image); auto in = horcrux::FsPlainInput(image);
auto out = horcrux::FsCryptoOutput(folder, 5); auto out = horcrux::FsCryptoOutput(folder, 5);
//Execute Plain to Crypto //Execute Plain to Crypto
out.write(in.read()); out.write(in.read());
//use FsCryptoInput to re-join the files and check the outcome //use FsCryptoInput to re-join the files and check the outcome
auto files = get_created_filenames(out); auto files = get_created_filenames(out);
auto in_test = horcrux::FsCryptoInput(files); auto in_test = horcrux::FsCryptoInput(files);
auto buf2 = in_test.read(); auto buf2 = in_test.read();
EXPECT_EQ(buf, buf2); EXPECT_EQ(buf, buf2);
delete_created_files(out); delete_created_files(out);
} }
TEST(IoTest, CryptoToCrypto){ TEST(IoTest, CryptoToCrypto){
auto buf = generic_read_file(image); auto buf = generic_read_file(image);
// First use FsCryptoOutput to split the files // First use FsCryptoOutput to split the files
auto out_test = horcrux::FsCryptoOutput(folder, 8); auto out_test = horcrux::FsCryptoOutput(folder, 8);
out_test.write(buf); out_test.write(buf);
//use FsCryptoInput to re-join the files //use FsCryptoInput to re-join the files
auto files = get_created_filenames(out_test); auto files = get_created_filenames(out_test);
auto in = horcrux::FsCryptoInput(files); auto in = horcrux::FsCryptoInput(files);
auto out = horcrux::FsCryptoOutput(folder, 5, "test"); auto out = horcrux::FsCryptoOutput(folder, 5, "test");
//Execute Crypto to Crypto //Execute Crypto to Crypto
out.write(in.read()); out.write(in.read());
//use FsCryptoInput to re-join the files and check the outcome //use FsCryptoInput to re-join the files and check the outcome
files = get_created_filenames(out); files = get_created_filenames(out);
auto in_test = horcrux::FsCryptoInput(files); auto in_test = horcrux::FsCryptoInput(files);
auto buf2 = in_test.read(); auto buf2 = in_test.read();
EXPECT_EQ(buf, buf2); EXPECT_EQ(buf, buf2);
delete_created_files(out_test); delete_created_files(out_test);
delete_created_files(out); delete_created_files(out);
} }
TEST(IoTest, CryptoToPlain){ TEST(IoTest, CryptoToPlain){
auto buf = generic_read_file(image); auto buf = generic_read_file(image);
// First use FsCryptoOutput to split the files // First use FsCryptoOutput to split the files
auto out_test = horcrux::FsCryptoOutput(folder, 8); auto out_test = horcrux::FsCryptoOutput(folder, 8);
out_test.write(buf); out_test.write(buf);
//use FsCryptoInput to re-join the files //use FsCryptoInput to re-join the files
auto files = get_created_filenames(out_test); auto files = get_created_filenames(out_test);
auto in = horcrux::FsCryptoInput(files); auto in = horcrux::FsCryptoInput(files);
auto out = horcrux::FsPlainOutput(noexist); auto out = horcrux::FsPlainOutput(noexist);
//Execute Crypto to Plain //Execute Crypto to Plain
out.write(in.read()); out.write(in.read());
//check the outcome //check the outcome
auto buf2 = generic_read_file(noexist); auto buf2 = generic_read_file(noexist);
EXPECT_EQ(buf, buf2); EXPECT_EQ(buf, buf2);
delete_created_files(out_test); delete_created_files(out_test);
std::filesystem::remove(noexist); std::filesystem::remove(noexist);
} }

View File

@ -1,40 +1,43 @@
#include "gtest/gtest.h"
#include "test.h" #include "test.h"
#include "gtest/gtest.h"
/* Utility functions */ /* Utility functions */
std::vector<unsigned char> generic_read_file(const std::string& filename){ std::vector<unsigned char> generic_read_file(const std::string& filename) {
auto ifstream = std::ifstream{filename, std::ios::binary}; auto ifstream = std::ifstream{filename, std::ios::binary};
auto path = std::filesystem::path{filename}; auto path = std::filesystem::path{filename};
auto size = std::filesystem::file_size(path); auto size = std::filesystem::file_size(path);
std::vector<unsigned char> buf(size); std::vector<unsigned char> buf(size);
ifstream.read(reinterpret_cast<char*>(buf.data()), size); ifstream.read(reinterpret_cast<char*>(buf.data()), size);
return buf; return buf;
} }
std::vector<std::string> get_created_filenames(const horcrux::FsCryptoOutput& out){ std::vector<std::string> get_created_filenames(
std::vector<std::string> result(out.created_files.size()); const horcrux::FsCryptoOutput& out) {
transform(out.created_files.begin(), out.created_files.end(), result.begin(), std::vector<std::string> result(out.created_files.size());
[](auto path){return path.string();}); transform(out.created_files.begin(), out.created_files.end(),
return result; result.begin(), [](auto path) { return path.string(); } );
return result;
} }
void delete_created_files(const horcrux::FsCryptoOutput& out){ void delete_created_files(const horcrux::FsCryptoOutput& out) {
std::for_each(out.created_files.begin(), out.created_files.end(), std::for_each(out.created_files.begin(), out.created_files.end(),
[](auto f){std::filesystem::remove(f);}); [](auto f) { std::filesystem::remove(f); } );
} }
std::vector<std::string> get_encrypted_files(const std::string& folder, const std::string& basename) { std::vector<std::string> get_encrypted_files(const std::string& folder,
std::vector<std::string> result; const std::string& basename) {
for (auto& p: std::filesystem::directory_iterator(folder)){ std::vector<std::string> result;
if (p.path().string().starts_with(basename) && for (auto& p: std::filesystem::directory_iterator(folder)) {
p.path().string().ends_with(".enc")) if (p.path().string().starts_with(basename)
result.push_back(p.path().string()); && p.path().string().ends_with(".enc")) {
} result.push_back(p.path().string());
std::sort(result.begin(), result.end()); }
return result; }
std::sort(result.begin(), result.end());
return result;
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
} }

View File

@ -28,8 +28,8 @@ std::vector<std::string> get_encrypted_files(const std::string& folder, const st
/* test command: /* test command:
echo "ditemi perche' se la mucca fa mu il merlo non fa me" | echo "ditemi perche' se la mucca fa mu il merlo non fa me" |
scripts/aes256.sh -k 0123456789ABCDEF0123456789ABCDEF -i 0123456789ABCDEF | scripts/aes256.sh -k 0123456789ABCDEF0123456789ABCDEF -i 0123456789ABCDEF |
xxd -i xxd -i
*/ */
const std::string test1_str = "ditemi perche' se la mucca fa mu il merlo non fa me"; const std::string test1_str = "ditemi perche' se la mucca fa mu il merlo non fa me";
const std::string test1_key = "0123456789ABCDEF0123456789ABCDEF"; const std::string test1_key = "0123456789ABCDEF0123456789ABCDEF";

View File

@ -16,31 +16,31 @@ const std::string test4_str = "mi e' entrata una bruschetta nell'occhio";
const std::string test4_base64 = "bWkgZScgZW50cmF0YSB1bmEgYnJ1c2NoZXR0YSBuZWxsJ29jY2hpbw=="; const std::string test4_base64 = "bWkgZScgZW50cmF0YSB1bmEgYnJ1c2NoZXR0YSBuZWxsJ29jY2hpbw==";
TEST(utilTests, to_base64Test){ TEST(utilTests, to_base64Test){
EXPECT_EQ(test1_base64, horcrux::to_base64(std::vector<unsigned char>(test1_str.begin(), test1_str.end()))); EXPECT_EQ(test1_base64, horcrux::to_base64(std::vector<unsigned char>(test1_str.begin(), test1_str.end())));
EXPECT_EQ(test2_base64, horcrux::to_base64(std::vector<unsigned char>(test2_str.begin(), test2_str.end()))); EXPECT_EQ(test2_base64, horcrux::to_base64(std::vector<unsigned char>(test2_str.begin(), test2_str.end())));
EXPECT_EQ(test3_base64, horcrux::to_base64(std::vector<unsigned char>(test3_str.begin(), test3_str.end()))); EXPECT_EQ(test3_base64, horcrux::to_base64(std::vector<unsigned char>(test3_str.begin(), test3_str.end())));
EXPECT_EQ(test4_base64, horcrux::to_base64(std::vector<unsigned char>(test4_str.begin(), test4_str.end()))); EXPECT_EQ(test4_base64, horcrux::to_base64(std::vector<unsigned char>(test4_str.begin(), test4_str.end())));
} }
TEST(utilTests, from_base64Test){ TEST(utilTests, from_base64Test){
auto result = horcrux::from_base64(test1_base64); auto result = horcrux::from_base64(test1_base64);
EXPECT_EQ(test1_str, std::string(result.begin(), result.end())); EXPECT_EQ(test1_str, std::string(result.begin(), result.end()));
result = horcrux::from_base64(test2_base64); result = horcrux::from_base64(test2_base64);
EXPECT_EQ(test2_str, std::string(result.begin(), result.end())); EXPECT_EQ(test2_str, std::string(result.begin(), result.end()));
result = horcrux::from_base64(test3_base64); result = horcrux::from_base64(test3_base64);
EXPECT_EQ(test3_str, std::string(result.begin(), result.end())); EXPECT_EQ(test3_str, std::string(result.begin(), result.end()));
result = horcrux::from_base64(test4_base64); result = horcrux::from_base64(test4_base64);
EXPECT_EQ(test4_str, std::string(result.begin(), result.end())); EXPECT_EQ(test4_str, std::string(result.begin(), result.end()));
} }
TEST(utilTests, generate_random){ TEST(utilTests, generate_random){
/* It works, but it's not deterministic */ /* It works, but it's not deterministic */
//EXPECT_NE(horcrux::generate_random(32), horcrux::generate_random(32)); //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(16), horcrux::generate_random(16));
//EXPECT_NE(horcrux::generate_random(8), horcrux::generate_random(8)); //EXPECT_NE(horcrux::generate_random(8), horcrux::generate_random(8));
//EXPECT_NE(horcrux::generate_random(1), horcrux::generate_random(1)); //EXPECT_NE(horcrux::generate_random(1), horcrux::generate_random(1));
EXPECT_EQ(horcrux::generate_random(0), horcrux::generate_random(0)); EXPECT_EQ(horcrux::generate_random(0), horcrux::generate_random(0));
} }