mirror of
https://github.com/usatiuk/backup.git
synced 2025-10-27 01:37:49 +01:00
init
This commit is contained in:
47
src/filters/CheckFilter.cpp
Normal file
47
src/filters/CheckFilter.cpp
Normal 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
36
src/filters/CheckFilter.h
Normal 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
6
src/filters/Filter.cpp
Normal 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
30
src/filters/Filter.h
Normal 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
17
src/filters/FilterAES.cpp
Normal 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
37
src/filters/FilterAES.h
Normal 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
|
||||
23
src/filters/FilterContainer.cpp
Normal file
23
src/filters/FilterContainer.cpp
Normal 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;
|
||||
}
|
||||
37
src/filters/FilterContainer.h
Normal file
37
src/filters/FilterContainer.h
Normal 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
|
||||
32
src/filters/FilterFactory.cpp
Normal file
32
src/filters/FilterFactory.cpp
Normal 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");
|
||||
}
|
||||
25
src/filters/FilterFactory.h
Normal file
25
src/filters/FilterFactory.h
Normal 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
|
||||
18
src/filters/FilterShift.cpp
Normal file
18
src/filters/FilterShift.cpp
Normal 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
30
src/filters/FilterShift.h
Normal 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
|
||||
23
src/filters/FilterShiftSecret.cpp
Normal file
23
src/filters/FilterShiftSecret.cpp
Normal 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
|
||||
33
src/filters/FilterShiftSecret.h
Normal file
33
src/filters/FilterShiftSecret.h
Normal 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
|
||||
50
src/filters/FilterZlib.cpp
Normal file
50
src/filters/FilterZlib.cpp
Normal 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
31
src/filters/FilterZlib.h
Normal 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
|
||||
Reference in New Issue
Block a user