This commit is contained in:
2023-06-02 12:51:08 +02:00
commit 0e355fbe42
142 changed files with 10281 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
//
// Created by Stepan Usatiuk on 12.05.2023.
//
#include "CheckFilter.h"
#include "../crypto/CRC32.h"
#include "../repo/Serialize.h"
std::vector<char> CheckFilter::filterWrite(std::vector<char> from) const {
return filterWriteStatic(std::move(from));
}
std::vector<char> CheckFilter::filterRead(std::vector<char> from) const {
return filterReadStatic(std::move(from));
}
std::vector<char> CheckFilter::filterWriteStatic(std::vector<char> from) {
auto out = magic;
Serialize::serialize(from, out);
auto crc = CRC32::calculate(from);
Serialize::serialize(crc, out);
return out;
}
std::vector<char> CheckFilter::filterReadStatic(std::vector<char> from) {
if (from.size() < magic.size()) throw Exception("Input is corrupted (too small)!");
for (size_t i = 0; i < magic.size(); i++) {
if (from[i] != magic[i]) throw Exception("Magic prefix is wrong!");
}
auto fromIt = from.cbegin() + magic.size();
auto out = Serialize::deserialize<std::vector<char>>(fromIt, from.cend());
auto crc = CRC32::calculate(out);
auto crcRecorded = Serialize::deserialize<CRC32::crcType>(fromIt, from.cend());
if (crc != crcRecorded) throw Exception("CRC mismatch!");
return out;
}

36
src/filters/CheckFilter.h Normal file
View File

@@ -0,0 +1,36 @@
//
// Created by Stepan Usatiuk on 12.05.2023.
//
#ifndef SEMBACKUP_CHECKFILTER_H
#define SEMBACKUP_CHECKFILTER_H
#include "Filter.h"
/// Filter implementation that checks the input for corruption using CRC
/**
* Additionally, it has static methods for work outside FilterContainer%s
*/
class CheckFilter : public Filter {
public:
/// \copydoc Filter::filterWrite
/// \copydoc CheckFilter::filterWriteS
std::vector<char> filterWrite(std::vector<char> from) const override;
/// \copydoc Filter::filterRead
/// \copydoc CheckFilter::filterReadS
std::vector<char> filterRead(std::vector<char> from) const override;
/// Adds CRC hash and magic string to the the \p from vector
static std::vector<char> filterWriteStatic(std::vector<char> from);
/// Checks the \p from vector and removes the metadata
/// \throws Exception on any error
static std::vector<char> filterReadStatic(std::vector<char> from);
private:
static const inline std::vector<char> magic{'s', 'e', 'm', 'b', 'a'};
};
#endif//SEMBACKUP_CHECKFILTER_H

6
src/filters/Filter.cpp Normal file
View File

@@ -0,0 +1,6 @@
//
// Created by Stepan Usatiuk on 22.04.2023.
//
#include "Filter.h"
Filter::~Filter() = default;

30
src/filters/Filter.h Normal file
View File

@@ -0,0 +1,30 @@
//
// Created by Stepan Usatiuk on 22.04.2023.
//
#ifndef SEMBACKUP_FILTER_H
#define SEMBACKUP_FILTER_H
#include <vector>
/// Interface class for I/O filters
class Filter {
public:
/// Applies the filter to \p from vector and returns the result
/// Note: the vector is passed by value, as it allows to avoid copying with std::move in case the filter modifies the \p in vector in-place
/// \param from Source vector of chars
/// \return Filtered vector of chars
virtual std::vector<char> filterWrite(std::vector<char> from) const = 0;
/// Reverses the applied filter from \p from vector and returns the result
/// Note: the vector is passed by value, as it allows to avoid copying with std::move in case the filter modifies the \p in vector in-place
/// \param from Source vector of chars
/// \return Filtered vector of chars
virtual std::vector<char> filterRead(std::vector<char> from) const = 0;
/// Default virtual destructor
virtual ~Filter();
};
#endif//SEMBACKUP_FILTER_H

17
src/filters/FilterAES.cpp Normal file
View File

@@ -0,0 +1,17 @@
//
// Created by Stepan Usatiuk on 23.04.2023.
//
#include "FilterAES.h"
#include "../crypto/AES.h"
std::vector<char> FilterAES::filterWrite(std::vector<char> from) const {
return AES::encrypt(from, key);
}
std::vector<char> FilterAES::filterRead(std::vector<char> from) const {
return AES::decrypt(from, key);
}
FilterAES::FilterAES(const std::string &password, const std::string &salt) : key(AES::deriveKey(password, salt)) {}

37
src/filters/FilterAES.h Normal file
View File

@@ -0,0 +1,37 @@
//
// Created by Stepan Usatiuk on 23.04.2023.
//
#ifndef SEMBACKUP_FILTERAES_H
#define SEMBACKUP_FILTERAES_H
#include <array>
#include <cstdint>
#include <string>
#include "Filter.h"
/// Filter implementation that encrypts/decrypts data using provided password and salt
class FilterAES : public Filter {
public:
/// Constructs the filter, using \p password and \p salt to generate the encryption key
/// \param password Constant reference to password string
/// \param salt Constant reference to salt string
FilterAES(const std::string &password, const std::string &salt);
/// Encrypts the \p from vector
/// \copydoc Filter::filterWrite
/// \throws Exception on any error
std::vector<char> filterWrite(std::vector<char> from) const override;
/// Decrypts the \p from vector
/// \copydoc Filter::filterRead
/// \throws Exception on any error
std::vector<char> filterRead(std::vector<char> from) const override;
private:
const std::array<uint8_t, 32> key;///< Key used for encryption, derived from \p password and \p salt
};
#endif//SEMBACKUP_FILTERAES_H

View File

@@ -0,0 +1,23 @@
//
// Created by Stepan Usatiuk on 22.04.2023.
//
#include "FilterContainer.h"
FilterContainer::FilterContainer() = default;
FilterContainer &FilterContainer::addFilter(std::unique_ptr<Filter> &&f) {
filters.emplace_back(std::move(f));
return *this;
}
std::vector<char> FilterContainer::filterWrite(std::vector<char> from) const {
for (auto const &f: filters) from = f->filterWrite(std::move(from));
return from;
}
std::vector<char> FilterContainer::filterRead(std::vector<char> from) const {
for (auto f = filters.crbegin(); f != filters.crend(); f++)
from = (*f)->filterRead(std::move(from));
return from;
}

View File

@@ -0,0 +1,37 @@
//
// Created by Stepan Usatiuk on 22.04.2023.
//
#ifndef SEMBACKUP_FILTERCONTAINER_H
#define SEMBACKUP_FILTERCONTAINER_H
#include <memory>
#include <vector>
#include "Filter.h"
/// Convenience Filter implementation, that applies multiple Filter%s in succession
class FilterContainer : public Filter {
public:
/// Constructs an empty FilterContainer
FilterContainer();
/// Adds a Filter into itself
/// \param f Rvalue reference to a unique pointer to Filter
/// \return Reference to itself
FilterContainer &addFilter(std::unique_ptr<Filter> &&f);
/// Applies the filters in order of insertion
/// \copydoc Filter::filterWrite
std::vector<char> filterWrite(std::vector<char> from) const override;
/// Applies the filters in reverse order of insertion
/// \copydoc Filter::filterRead
std::vector<char> filterRead(std::vector<char> from) const override;
private:
std::vector<std::unique_ptr<Filter>> filters;///< Vector of unique pointers to Filter%s
};
#endif//SEMBACKUP_FILTERCONTAINER_H

View File

@@ -0,0 +1,32 @@
//
// Created by Stepan Usatiuk on 22.04.2023.
//
#include "FilterFactory.h"
#include "../Exception.h"
#include "CheckFilter.h"
#include "FilterAES.h"
#include "FilterShift.h"
#include "FilterShiftSecret.h"
#include "FilterZlib.h"
std::unique_ptr<Filter> FilterFactory::makeFilter(const std::string &type, const Config &config) {
if (type == "none") throw Exception("Trying to make a \"none\" filter!");
if (type == "aes") {
return std::make_unique<FilterAES>(config.getStr("password"), config.getStr("salt"));
} else if (type == "zlib") {
return std::make_unique<FilterZlib>(config.getInt("compression-level"));
} else if (type == "crc") {
return std::make_unique<CheckFilter>();
}
#ifdef TEST
else if (type == "shiftC") {
return std::make_unique<FilterShift>(config.getInt("compression-level"));
} else if (type == "shiftE")
return std::make_unique<FilterShiftSecret>(config.getStr("password"), config.getStr("salt"));
#endif
throw Exception("Unknown filter value");
}

View File

@@ -0,0 +1,25 @@
//
// Created by Stepan Usatiuk on 22.04.2023.
//
#ifndef SEMBACKUP_FILTERFACTORY_H
#define SEMBACKUP_FILTERFACTORY_H
#include <memory>
#include <string>
#include "../Config.h"
#include "Filter.h"
/// Utility factory class for Filter%s
class FilterFactory {
public:
/// Constructs a Filter of type \p type according to \p config
/// \param type Constant reference to a string containing the type of filter to construct
/// \param config Constant reference to Config which will be used to determine constructed Filter%'s parameters
/// \return Unique pointer to the constructed Filter
static std::unique_ptr<Filter> makeFilter(const std::string &type, const Config &config);
};
#endif//SEMBACKUP_FILTERFACTORY_H

View File

@@ -0,0 +1,18 @@
//
// Created by Stepan Usatiuk on 22.04.2023.
//
#ifdef TEST
#include "FilterShift.h"
std::vector<char> FilterShift::filterWrite(std::vector<char> from) const {
for (auto &c: from) c += shiftVal;
return from;
}
std::vector<char> FilterShift::filterRead(std::vector<char> from) const {
for (auto &c: from) c -= shiftVal;
return from;
}
FilterShift::FilterShift(int level) : shiftVal(level) {}
#endif

30
src/filters/FilterShift.h Normal file
View File

@@ -0,0 +1,30 @@
//
// Created by Stepan Usatiuk on 22.04.2023.
//
#ifdef TEST
#ifndef SEMBACKUP_FILTERSHIFT_H
#define SEMBACKUP_FILTERSHIFT_H
#include "Filter.h"
/// Filter implementation that shifts every byte in input vector using provided value
/// \warning For testing purposes only!
class FilterShift : public Filter {
public:
/// Constructs the filter using \p level as shift value
/// \param level Number that will be added to each input byte
FilterShift(int level);
/// \copydoc Filter::filterWrite
std::vector<char> filterWrite(std::vector<char> from) const override;
/// \copydoc Filter::filterRead
std::vector<char> filterRead(std::vector<char> from) const override;
private:
int shiftVal;///< Value to add to input bytes
};
#endif//SEMBACKUP_FILTERSHIFT_H
#endif//TEST

View File

@@ -0,0 +1,23 @@
//
// Created by Stepan Usatiuk on 23.04.2023.
//
#ifdef TEST
#include "FilterShiftSecret.h"
#include <string>
std::vector<char> FilterShiftSecret::filterWrite(std::vector<char> from) const {
for (auto &c: from) c += shiftVal;
return from;
}
std::vector<char> FilterShiftSecret::filterRead(std::vector<char> from) const {
for (auto &c: from) c -= shiftVal;
return from;
}
FilterShiftSecret::FilterShiftSecret(const std::string &password, const std::string &salt) {
shiftVal = password[0] + salt[0];
}
#endif

View File

@@ -0,0 +1,33 @@
//
// Created by Stepan Usatiuk on 23.04.2023.
//
#ifdef TEST
#ifndef SEMBACKUP_FILTERSHIFTSECRET_H
#define SEMBACKUP_FILTERSHIFTSECRET_H
#include <string>
#include "Filter.h"
/// Filter implementation that shifts every byte in input vector using two provided value
/// \warning For testing purposes only!
class FilterShiftSecret : public Filter {
public:
/// Constructs the filter using the sum of first bytes of \p password and \p salt to initialize shiftVal
/// \param password Constant reference to "password" string
/// \param salt Constant reference to "salt" string
FilterShiftSecret(const std::string &password, const std::string &salt);
/// \copydoc Filter::filterWrite
std::vector<char> filterWrite(std::vector<char> from) const override;
/// \copydoc Filter::filterRead
std::vector<char> filterRead(std::vector<char> from) const override;
private:
int shiftVal = 0;///< Value to add to input bytes
};
#endif//SEMBACKUP_FILTERSHIFTSECRET_H
#endif//TEST

View File

@@ -0,0 +1,50 @@
//
// Created by Stepan Usatiuk on 23.04.2023.
//
#include "FilterZlib.h"
#include <zlib.h>
#include "../repo/Serialize.h"
std::vector<char> FilterZlib::filterWrite(std::vector<char> from) const {
uLongf outSize = compressBound(from.size());
std::vector<char> out;
Serialize::serialize('C', out);
Serialize::serialize(static_cast<unsigned long long>(from.size()), out);
uLongf sizeSize = out.size();
out.resize(sizeSize + outSize);
if (compress2(reinterpret_cast<Bytef *>(out.data() + sizeSize), &outSize, reinterpret_cast<const Bytef *>(from.data()), from.size(), level) !=
Z_OK)
throw Exception("Error compressing!");
out.resize(outSize + sizeSize);
return out;
}
std::vector<char> FilterZlib::filterRead(std::vector<char> from) const {
auto desI = from.cbegin();
char C = Serialize::deserialize<char>(desI, from.cend());
if (C != 'C') throw Exception("Bad compression prefix!");
uLongf size = Serialize::deserialize<unsigned long long>(desI, from.cend());
std::vector<char> out(size);
if (desI >= from.cend()) throw Exception("Unexpected end of archive!");
if (uncompress(reinterpret_cast<Bytef *>(out.data()), &size, reinterpret_cast<const Bytef *>(&(*desI)), std::distance(desI, from.cend())) !=
Z_OK)
throw Exception("Error decompressing!");
return out;
}
FilterZlib::FilterZlib(int level) : level(level) {}

31
src/filters/FilterZlib.h Normal file
View File

@@ -0,0 +1,31 @@
//
// Created by Stepan Usatiuk on 23.04.2023.
//
#ifndef SEMBACKUP_FILTERZLIB_H
#define SEMBACKUP_FILTERZLIB_H
#include "Filter.h"
/// Filter implementation that uses Zlib to compress data
class FilterZlib : public Filter {
public:
/// Creates the filter using \p level as compression level
/// \param level
FilterZlib(int level);
/// Compresses the \p from vector
/// \copydoc Filter::filterWrite
/// \throws Exception on any error
std::vector<char> filterWrite(std::vector<char> from) const override;
/// Decompresses the \p from vector
/// \copydoc Filter::filterRead
/// \throws Exception on any error
std::vector<char> filterRead(std::vector<char> from) const override;
private:
int level = -1;///< Compression level to use, -1 is the Zlib default
};
#endif//SEMBACKUP_FILTERZLIB_H