Fix format
This commit is contained in:
parent
3d89f30a94
commit
01ff00f3b7
@ -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
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 ""
|
||||||
)
|
)
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
|
331
src/crypto.cpp
331
src/crypto.cpp
@ -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
|
||||||
|
147
src/crypto.h
147
src/crypto.h
@ -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
|
||||||
|
134
src/horcrux.cpp
134
src/horcrux.cpp
@ -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
|
|
||||||
|
@ -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
|
||||||
|
147
src/io.cpp
147
src/io.cpp
@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
58
src/io.h
58
src/io.h
@ -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
|
||||||
|
42
src/main.cpp
42
src/main.cpp
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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")
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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"}));
|
||||||
}
|
}
|
||||||
|
230
test/io-test.cpp
230
test/io-test.cpp
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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";
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user