Add main and user interface
This commit is contained in:
parent
1fb526e711
commit
570b5e45f5
@ -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_executable(horcrux ${SOURCES})
|
||||||
add_library(${CMAKE_PROJECT_NAME}_lib STATIC ${SOURCES})
|
add_library(${CMAKE_PROJECT_NAME}_lib STATIC ${SOURCES})
|
||||||
|
@ -32,17 +32,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
AES256_CBC::AES256_CBC(){
|
EvpCipherCtx AES256_CBC::init(Mode mode,
|
||||||
encryption_key = utils::generate_random(kKeySize);
|
|
||||||
}
|
|
||||||
AES256_CBC::AES256_CBC(const std::vector<unsigned char>& key){
|
|
||||||
encryption_key = key;
|
|
||||||
}
|
|
||||||
AES256_CBC::AES256_CBC(std::vector<unsigned char>&& key){
|
|
||||||
encryption_key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
EvpCipherCtx AES256_CBC::init(Cipher::Mode mode,
|
|
||||||
const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv){
|
const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv){
|
||||||
if (key.size() != kKeySize){
|
if (key.size() != kKeySize){
|
||||||
throw std::runtime_error("Wrong key size");
|
throw std::runtime_error("Wrong key size");
|
||||||
@ -52,12 +42,12 @@ EvpCipherCtx AES256_CBC::init(Cipher::Mode mode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
EvpCipherCtx ctx;
|
EvpCipherCtx ctx;
|
||||||
if (mode == Cipher::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 == Cipher::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");
|
||||||
@ -66,7 +56,7 @@ EvpCipherCtx AES256_CBC::init(Cipher::Mode mode,
|
|||||||
return ctx;
|
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<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,
|
||||||
@ -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
|
// 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 == Cipher::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, &*begin, chunk_size)){
|
||||||
throw std::runtime_error("EVP_EncryptUpdate");
|
throw std::runtime_error("EVP_EncryptUpdate");
|
||||||
@ -94,7 +84,7 @@ size_t AES256_CBC::process_chunk(Cipher::Mode mode, EvpCipherCtx& ctx,
|
|||||||
return len;
|
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<unsigned char>& output, size_t output_offset,
|
std::vector<unsigned char>& output, size_t output_offset,
|
||||||
bool resize_in, bool resize_out)
|
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
|
// Make sure output is large enough to add the last block
|
||||||
output.resize(output_offset + kIvSize);
|
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)){
|
if (1 != EVP_EncryptFinal_ex(ctx.get(), output.data() + output_offset, &len)){
|
||||||
throw std::runtime_error("EVP_EncryptFinal");
|
throw std::runtime_error("EVP_EncryptFinal");
|
||||||
}
|
}
|
||||||
@ -117,7 +107,7 @@ size_t AES256_CBC::process_final(Cipher::Mode mode, EvpCipherCtx& ctx,
|
|||||||
return len;
|
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<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,
|
||||||
@ -130,9 +120,15 @@ size_t AES256_CBC::process_all(Cipher::Mode mode, EvpCipherCtx& ctx,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned char> AES256_CBC::process(const std::vector<unsigned char>& inputdata) {
|
||||||
|
if (mode == Mode::kEncrypt)
|
||||||
|
return encrypt(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(const std::vector<unsigned char>& plaintext) {
|
||||||
return encrypt(encryption_key, utils::generate_random(kIvSize), plaintext);
|
return encrypt(encryption_key, horcrux::generate_random(kIvSize), plaintext);
|
||||||
}
|
}
|
||||||
std::vector<unsigned char> AES256_CBC::decrypt(const std::vector<unsigned char>& ciphertext) {
|
std::vector<unsigned char> AES256_CBC::decrypt(const std::vector<unsigned char>& ciphertext) {
|
||||||
return decrypt(encryption_key, ciphertext);
|
return decrypt(encryption_key, ciphertext);
|
||||||
@ -141,12 +137,12 @@ std::vector<unsigned char> AES256_CBC::decrypt(const std::vector<unsigned char>&
|
|||||||
std::vector<unsigned char> AES256_CBC::encrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
|
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)
|
const std::vector<unsigned char>& 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
|
// Make sure ouput is large enough to contain IV + encrypted data + padding
|
||||||
std::vector<unsigned char> output(input.size() + (2 * kIvSize));
|
std::vector<unsigned char> output(input.size() + (2 * kIvSize));
|
||||||
std::copy(iv.begin(), iv.end(), output.begin());
|
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;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,8 +150,8 @@ std::vector<unsigned char> AES256_CBC::encrypt(const std::vector<unsigned char>&
|
|||||||
int AES256_CBC::encrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
|
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)
|
const std::vector<unsigned char>& input, std::vector<unsigned char>& output)
|
||||||
{
|
{
|
||||||
auto ctx = init(Cipher::Mode::kEncrypt, key, iv);
|
auto ctx = init(Mode::kEncrypt, key, iv);
|
||||||
process_all(Cipher::Mode::kEncrypt, ctx, input.begin(), input.end(), output, 0);
|
process_all(Mode::kEncrypt, ctx, input.begin(), input.end(), output, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,8 +173,8 @@ int AES256_CBC::encrypt(const std::vector<unsigned char>& key, const std::vector
|
|||||||
int AES256_CBC::decrypt(const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
|
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)
|
const std::vector<unsigned char>& input, std::vector<unsigned char>& output)
|
||||||
{
|
{
|
||||||
auto ctx = init(Cipher::Mode::kDecrypt, key, iv);
|
auto ctx = init(Mode::kDecrypt, key, iv);
|
||||||
process_all(Cipher::Mode::kDecrypt, ctx, input.begin(), input.end(), output, 0);
|
process_all(Mode::kDecrypt, ctx, input.begin(), input.end(), output, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
std::vector<unsigned char> AES256_CBC::decrypt(const std::vector<unsigned char>& key,
|
std::vector<unsigned char> AES256_CBC::decrypt(const std::vector<unsigned char>& key,
|
||||||
@ -190,9 +186,9 @@ std::vector<unsigned char> AES256_CBC::decrypt(
|
|||||||
const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv,
|
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)
|
std::vector<unsigned char>::const_iterator begin, std::vector<unsigned char>::const_iterator end)
|
||||||
{
|
{
|
||||||
auto ctx = init(Cipher::Mode::kDecrypt, key, iv);
|
auto ctx = init(Mode::kDecrypt, key, iv);
|
||||||
std::vector<unsigned char> output;
|
std::vector<unsigned char> output;
|
||||||
process_all(Cipher::Mode::kDecrypt, ctx, begin, end, output, 0);
|
process_all(Mode::kDecrypt, ctx, begin, end, output, 0);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}; //namespace
|
}; //namespace
|
||||||
|
83
src/crypto.h
83
src/crypto.h
@ -4,44 +4,30 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
namespace horcrux {
|
namespace horcrux {
|
||||||
enum class CipherType {AES256_CBC};
|
|
||||||
|
enum class Mode {kEncrypt, kDecrypt};
|
||||||
|
|
||||||
class Cipher {
|
class Cipher {
|
||||||
protected:
|
protected:
|
||||||
|
Cipher() = delete;
|
||||||
|
Cipher(Mode m) : mode(m) { }
|
||||||
|
Cipher(Mode m, const std::vector<unsigned char>& key) :
|
||||||
|
mode(m), encryption_key(key) {}
|
||||||
|
|
||||||
|
Cipher(Mode m, std::vector<unsigned char>&& key) :
|
||||||
|
mode(m), encryption_key(key) {}
|
||||||
|
|
||||||
std::vector<unsigned char> encryption_key;
|
std::vector<unsigned char> encryption_key;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Mode {
|
const Mode mode;
|
||||||
kEncrypt,
|
const std::vector<unsigned char>& get_encryption_key() {return encryption_key;}
|
||||||
kDecrypt
|
|
||||||
};
|
|
||||||
|
|
||||||
|
virtual std::vector<unsigned char> process(const std::vector<unsigned char>& inputdata) = 0;
|
||||||
virtual std::vector<unsigned char> encrypt(const std::vector<unsigned char>& plaintext) = 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;
|
virtual std::vector<unsigned char> decrypt(const std::vector<unsigned char>& ciphertext) = 0;
|
||||||
/*
|
|
||||||
virtual std::pair<std::vector<unsigned char>, std::vector<unsigned char>>
|
|
||||||
encrypt_all(std::vector<unsigned char>& plaintext) = 0;
|
|
||||||
|
|
||||||
virtual std::vector<unsigned char>
|
|
||||||
encrypt_all(std::vector<unsigned char>& plaintext,
|
|
||||||
std::ostream);
|
|
||||||
|
|
||||||
virtual std::vector<unsigned char>
|
|
||||||
decrypt_all(std::vector<unsigned char>& ciphertext, std::vector<unsigned char>& key) = 0;
|
|
||||||
|
|
||||||
virtual void encrypt_init(std::vector<unsigned char>& key, std::vector<unsigned char>& iv) = 0;
|
|
||||||
|
|
||||||
virtual void encrypt_chunk() = 0;
|
|
||||||
|
|
||||||
virtual void encrypt_fini() = 0;
|
|
||||||
|
|
||||||
virtual void decrypt_init(std::vector<unsigned char>& key, std::vector<unsigned char>& iv) = 0;
|
|
||||||
|
|
||||||
virtual void decrypt_chunk() = 0;
|
|
||||||
|
|
||||||
virtual void decrypt_fini() = 0;
|
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class EvpCipherCtx;
|
class EvpCipherCtx;
|
||||||
@ -51,19 +37,27 @@ class AES256_CBC : public Cipher {
|
|||||||
const size_t kIvSize = 16;
|
const size_t kIvSize = 16;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AES256_CBC();
|
AES256_CBC() : Cipher(Mode::kEncrypt) {
|
||||||
AES256_CBC(const std::vector<unsigned char>& key);
|
encryption_key = horcrux::generate_random(kKeySize);
|
||||||
AES256_CBC(std::vector<unsigned char>&& key);
|
}
|
||||||
|
AES256_CBC(const std::vector<unsigned char>& key) : Cipher(Mode::kDecrypt, key)
|
||||||
|
{
|
||||||
|
if (key.size() != kKeySize)
|
||||||
|
throw std::invalid_argument("Invalid key size");
|
||||||
|
}
|
||||||
|
AES256_CBC(std::vector<unsigned char>&& key) : Cipher(Mode::kDecrypt, key)
|
||||||
|
{
|
||||||
|
if (key.size() != kKeySize)
|
||||||
|
throw std::invalid_argument("Invalid key size");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned char> process(const std::vector<unsigned char>& inputdata) override;
|
||||||
std::vector<unsigned char> encrypt(const std::vector<unsigned char>& plaintext) 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> 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>& iv,
|
||||||
const std::vector<unsigned char>& input);
|
const std::vector<unsigned char>& input);
|
||||||
|
|
||||||
//int encrypt(const std::vector<unsigned char>& key,
|
|
||||||
// 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, const std::vector<unsigned char>& iv,
|
||||||
const std::vector<unsigned char>& input, std::vector<unsigned char>& output);
|
const std::vector<unsigned char>& input, std::vector<unsigned char>& output);
|
||||||
|
|
||||||
@ -82,34 +76,25 @@ public:
|
|||||||
std::vector<unsigned char>::const_iterator begin, std::vector<unsigned char>::const_iterator end);
|
std::vector<unsigned char>::const_iterator begin, std::vector<unsigned char>::const_iterator end);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EvpCipherCtx init(Cipher::Mode mode,
|
EvpCipherCtx init(Mode mode,
|
||||||
const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv);
|
const std::vector<unsigned char>& key, const std::vector<unsigned char>& iv);
|
||||||
|
|
||||||
size_t process_chunk(Cipher::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, size_t output_offset,
|
||||||
bool resize_in = true, bool resize_out = true);
|
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<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);
|
||||||
|
|
||||||
size_t process_all(Cipher::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);
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::unique_ptr<Cipher> createCipher(CipherType type){
|
}; //namespace
|
||||||
switch(type){
|
|
||||||
case CipherType::AES256_CBC:
|
|
||||||
return std::make_unique<AES256_CBC>();
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Unknown cipher");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
#endif //HORCRUX_SRC_CRYPTO_H
|
#endif //HORCRUX_SRC_CRYPTO_H
|
||||||
|
82
src/horcrux.cpp
Normal file
82
src/horcrux.cpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <exception>
|
||||||
|
#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<AES256_CBC>();
|
||||||
|
input = std::make_unique<FsPlainInput>(options.input[0]);
|
||||||
|
output = std::make_unique<FsCryptoOutput>(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<AES256_CBC>(from_base64(options.base64_key));
|
||||||
|
input = std::make_unique<FsCryptoInput>(options.input);
|
||||||
|
output = std::make_unique<FsPlainOutput>(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 <horcrux count> <input path> <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){
|
||||||
|
print_usage(program);
|
||||||
|
throw std::invalid_argument(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
HorcruxOptions parse_arguments(std::vector<std::string>&& 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
|
41
src/horcrux.h
Normal file
41
src/horcrux.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef HORCRUX_HORCRUX_H
|
||||||
|
#define HORCRUX_HORCRUX_H
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "crypto.h"
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
namespace horcrux {
|
||||||
|
|
||||||
|
struct HorcruxOptions {
|
||||||
|
Mode mode;
|
||||||
|
int count;
|
||||||
|
std::vector<std::string> input;
|
||||||
|
std::string output;
|
||||||
|
std::string base64_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Horcrux {
|
||||||
|
|
||||||
|
HorcruxOptions options;
|
||||||
|
std::unique_ptr<Cipher> cipher;
|
||||||
|
std::unique_ptr<Input> input;
|
||||||
|
std::unique_ptr<Output> 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<std::string>&& arguments);
|
||||||
|
|
||||||
|
}; //namespace
|
||||||
|
#endif //HORCRUX_HORCRUX_H
|
11
src/io.cpp
11
src/io.cpp
@ -1,10 +1,11 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
namespace horcrux {
|
namespace horcrux {
|
||||||
namespace fs = std::filesystem;
|
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){
|
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");
|
||||||
@ -28,7 +29,7 @@ FsCryptoInput::FsCryptoInput(const std::vector<std::string>& filenames)
|
|||||||
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 = fs::path{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");
|
||||||
}
|
}
|
||||||
@ -52,7 +53,7 @@ std::vector<unsigned char> FsCryptoInput::read(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
FsPlainOutput::FsPlainOutput(const std::string& filename)
|
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){
|
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");
|
throw std::invalid_argument("Output file is not a regular file");
|
||||||
@ -66,7 +67,7 @@ size_t FsPlainOutput::write(const std::vector<unsigned char>& to_write){
|
|||||||
|
|
||||||
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(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){
|
||||||
@ -84,7 +85,7 @@ size_t FsCryptoOutput::write(const std::vector<unsigned char>& to_write){
|
|||||||
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);
|
||||||
|
89
src/main.cpp
89
src/main.cpp
@ -1,69 +1,30 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
enum RetErr {
|
#include "horcrux.h"
|
||||||
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<std::string>& arguments, HorcruxOptions& opt){
|
|
||||||
// opt.mode = kCreate;
|
|
||||||
//}
|
|
||||||
//RetErr parse_load_options(std::vector<std::string>& arguments, HorcruxOptions& opt){
|
|
||||||
// opt.mode = kLoad;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//ret_err parse_options(int argc, const char *args[]){
|
|
||||||
// const std::vector<const std:string> 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){
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
int main(const int argc, const char *argv[]) {
|
int main(const int argc, const char *argv[]) {
|
||||||
HorcruxOptions options;
|
int ret = -1;
|
||||||
// RetErr ret = parse_arguments(argc, argv);
|
std::vector<std::string> arguments;
|
||||||
// switch (options.mode){
|
for (int i = 0; i < argc; ++i){
|
||||||
// case kCreate:
|
arguments.emplace_back(argv[i]);
|
||||||
// ret = horcrux_create(options);
|
}
|
||||||
// break;
|
|
||||||
// case kLoad:
|
try {
|
||||||
// ret = horcrux_load(options);
|
horcrux::Horcrux h(horcrux::parse_arguments(std::move(arguments)));
|
||||||
// break;
|
h.execute();
|
||||||
// default:
|
if (h.mode() == horcrux::Mode::kEncrypt){
|
||||||
// std::cout << "Error: Unknown Mode" << std::endl;
|
//print encryption key to stdout
|
||||||
// break;
|
std::cout << h.key() << std::endl;
|
||||||
// }
|
}
|
||||||
return 0;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
std::string utils::to_base64(const std::vector<unsigned char>& binary)
|
std::string horcrux::to_base64(const std::vector<unsigned char>& binary)
|
||||||
{
|
{
|
||||||
using namespace boost::archive::iterators;
|
using namespace boost::archive::iterators;
|
||||||
using It = base64_from_binary<transform_width<std::vector<unsigned char>::const_iterator, 6, 8>>;
|
using It = base64_from_binary<transform_width<std::vector<unsigned char>::const_iterator, 6, 8>>;
|
||||||
@ -14,7 +14,7 @@ std::string utils::to_base64(const std::vector<unsigned char>& binary)
|
|||||||
return base64.append((3 - binary.size() % 3) % 3, '=');
|
return base64.append((3 - binary.size() % 3) % 3, '=');
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> utils::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>, 8, 6>;
|
using It = transform_width<binary_from_base64<std::string::const_iterator>, 8, 6>;
|
||||||
@ -32,7 +32,7 @@ std::vector<unsigned char> utils::from_base64(const std::string& base64)
|
|||||||
return binary;
|
return binary;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> utils::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();
|
||||||
|
@ -2,8 +2,9 @@
|
|||||||
#define HORCRUX_SRC_UTILS_H
|
#define HORCRUX_SRC_UTILS_H
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
namespace utils {
|
namespace horcrux {
|
||||||
|
|
||||||
std::string to_base64(const std::vector<unsigned char>& binary);
|
std::string to_base64(const std::vector<unsigned char>& binary);
|
||||||
std::vector<unsigned char> from_base64(const std::string& base64);
|
std::vector<unsigned char> from_base64(const std::string& base64);
|
||||||
|
@ -1,27 +1,29 @@
|
|||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
#include "horcrux.h"
|
||||||
|
|
||||||
|
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 = horcrux::FsPlainInput(image);
|
auto in = FsPlainInput(image);
|
||||||
auto cipher = horcrux::AES256_CBC();
|
auto cipher = AES256_CBC();
|
||||||
auto out = horcrux::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 = horcrux::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 = horcrux::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);
|
||||||
@ -30,3 +32,97 @@ TEST(IntegrationTest, EndToEndEncryptDecrypt){
|
|||||||
delete_created_files(out);
|
delete_created_files(out);
|
||||||
std::filesystem::remove(noexist);
|
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"}));
|
||||||
|
}
|
||||||
|
@ -171,5 +171,6 @@ TEST(IoTest, CryptoToPlain){
|
|||||||
//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);
|
||||||
std::filesystem::remove(noexist);
|
std::filesystem::remove(noexist);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,38 @@
|
|||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
/* Utility functions */
|
||||||
|
std::vector<unsigned char> 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<unsigned char> buf(size);
|
||||||
|
ifstream.read(reinterpret_cast<char*>(buf.data()), size);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> get_created_filenames(const horcrux::FsCryptoOutput& out){
|
||||||
|
std::vector<std::string> 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<std::string> get_encrypted_files(const std::string& folder, const std::string& basename) {
|
||||||
|
std::vector<std::string> 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[]) {
|
int main(int argc, char *argv[]) {
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
25
test/test.h
25
test/test.h
@ -1,6 +1,7 @@
|
|||||||
#ifndef HORCRUX_TEST_TEST_H
|
#ifndef HORCRUX_TEST_TEST_H
|
||||||
#define HORCRUX_TEST_TEST_H
|
#define HORCRUX_TEST_TEST_H
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <algorithm>
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "crypto.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 text{TEST_WORK_DIR "/test.txt"};
|
||||||
const std::string image{TEST_WORK_DIR "/mangoni.jpg"};
|
const std::string image{TEST_WORK_DIR "/mangoni.jpg"};
|
||||||
|
|
||||||
static 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 path = std::filesystem::path{filename};
|
|
||||||
auto size = std::filesystem::file_size(path);
|
|
||||||
std::vector<unsigned char> buf(size);
|
|
||||||
ifstream.read(reinterpret_cast<char*>(buf.data()), size);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::vector<std::string> get_created_filenames(const horcrux::FsCryptoOutput& out){
|
std::vector<std::string> get_created_filenames(const horcrux::FsCryptoOutput& out);
|
||||||
std::vector<std::string> result(out.created_files.size());
|
|
||||||
transform(out.created_files.begin(), out.created_files.end(), result.begin(),
|
void delete_created_files(const horcrux::FsCryptoOutput& out);
|
||||||
[](auto path){return path.string();});
|
|
||||||
return result;
|
std::vector<std::string> get_encrypted_files(const std::string& folder, const std::string& basename);
|
||||||
}
|
|
||||||
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);});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Crypto Test utils */
|
/* Crypto Test utils */
|
||||||
|
|
||||||
|
@ -16,30 +16,30 @@ 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, utils::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, utils::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, utils::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, utils::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 = utils::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 = utils::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 = utils::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 = utils::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){
|
||||||
EXPECT_NE(utils::generate_random(32), utils::generate_random(32));
|
EXPECT_NE(horcrux::generate_random(32), horcrux::generate_random(32));
|
||||||
EXPECT_NE(utils::generate_random(16), utils::generate_random(16));
|
EXPECT_NE(horcrux::generate_random(16), horcrux::generate_random(16));
|
||||||
EXPECT_NE(utils::generate_random(8), utils::generate_random(8));
|
EXPECT_NE(horcrux::generate_random(8), horcrux::generate_random(8));
|
||||||
EXPECT_NE(utils::generate_random(1), utils::generate_random(1));
|
EXPECT_NE(horcrux::generate_random(1), horcrux::generate_random(1));
|
||||||
EXPECT_EQ(utils::generate_random(0), utils::generate_random(0));
|
EXPECT_EQ(horcrux::generate_random(0), horcrux::generate_random(0));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user