Refactor (de)serializing config files

This commit is contained in:
Sebastian Messmer 2015-11-10 17:50:08 -08:00
parent 4cedaa5bf4
commit 252a666a37
16 changed files with 280 additions and 220 deletions

View File

@ -17,11 +17,15 @@ using blockstore::encrypted::EncryptedBlockStore;
using namespace cryfs;
using namespace cpputils;
constexpr size_t CryCiphers::MAX_KEY_SIZE;
template<typename Cipher>
class CryCipherInstance: public CryCipher {
public:
BOOST_CONCEPT_ASSERT((CipherConcept<Cipher>));
static_assert(Cipher::EncryptionKey::BINARY_LENGTH <= CryCiphers::MAX_KEY_SIZE, "The key size for this cipher is too large. Please modify CryCiphers::MAX_KEY_SIZE");
CryCipherInstance(const optional<string> warning = none): _warning(warning) {
}
@ -86,4 +90,4 @@ vector<string> CryCiphers::supportedCipherNames() {
result.push_back(cipher->cipherName());
}
return result;
}
}

View File

@ -24,6 +24,10 @@ class CryCiphers {
public:
static std::vector<std::string> supportedCipherNames();
//A static_assert in CryCipherInstance ensures that there is no cipher with a key size larger than specified here.
//TODO Calculate this from SUPPORTED_CIPHERS instead of setting it manually
static constexpr size_t MAX_KEY_SIZE = 56; // in bytes
static const CryCipher& find(const std::string &cipherName);
private:

View File

@ -1,95 +0,0 @@
#pragma once
#ifndef MESSMER_CRYFS_SRC_CONFIG_CRYPTO_CONCRETECRYCONFIGENCRYPTOR_H
#define MESSMER_CRYFS_SRC_CONFIG_CRYPTO_CONCRETECRYCONFIGENCRYPTOR_H
#include <messmer/cpp-utils/data/Serializer.h>
#include <messmer/cpp-utils/data/Deserializer.h>
#include "InnerEncryptor.h"
#include <messmer/cpp-utils/crypto/RandomPadding.h>
#include <messmer/cpp-utils/crypto/kdf/DerivedKey.h>
namespace cryfs {
//TODO Test
template<class Cipher>
class ConcreteInnerEncryptor: public InnerEncryptor {
public:
static constexpr size_t CONFIG_SIZE = 512; // Inner config data is grown to this size before encryption to hide its actual size
ConcreteInnerEncryptor(typename Cipher::EncryptionKey key);
cpputils::Data encrypt(const cpputils::Data &plaintext) const override;
boost::optional<cpputils::Data> decrypt(const cpputils::Data &ciphertext) const override;
private:
cpputils::Data _serialize(const cpputils::Data &data) const;
boost::optional<cpputils::Data> _deserialize(const cpputils::Data &data) const;
typename Cipher::EncryptionKey _key;
};
template<class Cipher>
ConcreteInnerEncryptor<Cipher>::ConcreteInnerEncryptor(typename Cipher::EncryptionKey key)
: _key(std::move(key)) {
}
template<class Cipher>
boost::optional<cpputils::Data> ConcreteInnerEncryptor<Cipher>::decrypt(const cpputils::Data &ciphertext) const {
auto data = _deserialize(ciphertext);
if (data == boost::none) {
return boost::none;
}
auto decrypted = Cipher::decrypt(static_cast<const uint8_t*>(data->data()), data->size(), _key);
if (decrypted == boost::none) {
return boost::none;
}
auto configData = cpputils::RandomPadding::remove(*decrypted);
if (configData == boost::none) {
return boost::none;
}
return std::move(*configData);
}
template<class Cipher>
boost::optional<cpputils::Data> ConcreteInnerEncryptor<Cipher>::_deserialize(const cpputils::Data &ciphertext) const {
cpputils::Deserializer deserializer(&ciphertext);
try {
_checkHeader(&deserializer);
std::string readCipherName = deserializer.readString();
if (readCipherName != Cipher::NAME) {
cpputils::logging::LOG(cpputils::logging::ERROR) << "Wrong inner cipher used";
return boost::none;
}
auto result = deserializer.readTailData();
deserializer.finished();
return std::move(result); // TODO This std::move() is not necessary on newer gcc versions. Remove it and look for other occurrences of the same.
} catch (const std::exception &e) {
cpputils::logging::LOG(cpputils::logging::ERROR) << "Error serializing inner configuration: " << e.what();
return boost::none; // This can be caused by invalid input data and does not have to be a programming error. Don't throw exception.
}
}
template<class Cipher>
cpputils::Data ConcreteInnerEncryptor<Cipher>::encrypt(const cpputils::Data &plaintext) const {
auto paddedPlaintext = cpputils::RandomPadding::add(plaintext, CONFIG_SIZE);
auto encrypted = Cipher::encrypt(static_cast<const uint8_t*>(paddedPlaintext.data()), paddedPlaintext.size(), _key);
return _serialize(encrypted);
}
template<class Cipher>
cpputils::Data ConcreteInnerEncryptor<Cipher>::_serialize(const cpputils::Data &ciphertext) const {
try {
cpputils::Serializer serializer(cpputils::Serializer::StringSize(HEADER)
+ cpputils::Serializer::StringSize(Cipher::NAME)
+ ciphertext.size());
serializer.writeString(HEADER);
serializer.writeString(Cipher::NAME);
serializer.writeTailData(ciphertext);
return serializer.finished();
} catch (const std::exception &e) {
cpputils::logging::LOG(cpputils::logging::ERROR) << "Error serializing inner configuration: " << e.what();
throw; // This is a programming logic error, pass through exception.
}
}
}
#endif

View File

@ -1,9 +1,8 @@
#include "CryConfigEncryptor.h"
#include <messmer/cpp-utils/crypto/RandomPadding.h>
#include "OuterConfig.h"
using std::string;
using cpputils::Deserializer;
using cpputils::Serializer;
using cpputils::unique_ref;
using cpputils::Data;
using cpputils::RandomPadding;
@ -13,66 +12,27 @@ using boost::none;
using namespace cpputils::logging;
namespace cryfs {
const string CryConfigEncryptor::HEADER = "cryfs.config;0;scrypt";
CryConfigEncryptor::CryConfigEncryptor(unique_ref<InnerEncryptor> innerEncryptor, OuterCipher::EncryptionKey outerKey, DerivedKeyConfig keyConfig)
: _innerEncryptor(std::move(innerEncryptor)), _outerKey(std::move(outerKey)), _keyConfig(std::move(keyConfig)) {
}
void CryConfigEncryptor::checkHeader(Deserializer *deserializer) {
string header = deserializer->readString();
if (header != HEADER) {
throw std::runtime_error("Invalid header");
}
}
void CryConfigEncryptor::writeHeader(Serializer *serializer) {
serializer->writeString(HEADER);
}
Data CryConfigEncryptor::encrypt(const Data &plaintext) {
auto inner = _innerEncryptor->encrypt(plaintext);
auto padded = RandomPadding::add(inner, CONFIG_SIZE);
auto ciphertext = OuterCipher::encrypt(static_cast<const uint8_t*>(padded.data()), padded.size(), _outerKey);
return _serialize(ciphertext);
return OuterConfig{_keyConfig, std::move(ciphertext)}.serialize();
}
Data CryConfigEncryptor::_serialize(const Data &ciphertext) {
try {
Serializer serializer(Serializer::StringSize(HEADER)
+ _keyConfig.serializedSize()
+ ciphertext.size());
writeHeader(&serializer);
_keyConfig.serialize(&serializer);
serializer.writeTailData(ciphertext);
return serializer.finished();
} catch (const std::exception &e) {
cpputils::logging::LOG(cpputils::logging::ERROR) << "Error serializing CryConfigEncryptor: " << e.what();
throw; // This is a programming logic error. Pass through exception.
optional<Data> CryConfigEncryptor::decrypt(const Data &data) {
auto outerConfig = OuterConfig::deserialize(data);
if (outerConfig == none) {
return none;
}
return _decryptInnerConfig(outerConfig->encryptedInnerConfig);
}
optional<Data> CryConfigEncryptor::decrypt(const Data &plaintext) {
Deserializer deserializer(&plaintext);
try {
checkHeader(&deserializer);
_ignoreKey(&deserializer);
auto result = _loadAndDecryptConfigData(&deserializer);
deserializer.finished();
return result;
} catch (const std::exception &e) {
LOG(ERROR) << "Error loading configuration: " << e.what();
return boost::none; // This can be caused by invalid loaded data and is not necessarily a programming logic error. Don't throw exception.
}
}
void CryConfigEncryptor::_ignoreKey(Deserializer *deserializer) {
DerivedKeyConfig::load(deserializer);
}
optional<Data> CryConfigEncryptor::_loadAndDecryptConfigData(Deserializer *deserializer) {
auto ciphertext = deserializer->readTailData();
auto inner = OuterCipher::decrypt(static_cast<const uint8_t*>(ciphertext.data()), ciphertext.size(), _outerKey);
optional<Data> CryConfigEncryptor::_decryptInnerConfig(const Data &encryptedInnerConfig) {
auto inner = OuterCipher::decrypt(static_cast<const uint8_t*>(encryptedInnerConfig.data()), encryptedInnerConfig.size(), _outerKey);
if(inner == none) {
return none;
}

View File

@ -5,16 +5,14 @@
#include <messmer/cpp-utils/pointer/unique_ref.h>
#include <messmer/cpp-utils/data/Deserializer.h>
#include <messmer/cpp-utils/data/Serializer.h>
#include "InnerEncryptor.h"
#include "inner/InnerEncryptor.h"
#include <messmer/cpp-utils/crypto/kdf/DerivedKeyConfig.h>
#include <messmer/cpp-utils/crypto/symmetric/ciphers.h>
namespace cryfs {
//TODO Test
//TODO Test that encrypted config data always has the same size, no matter how big the plaintext config data
//TODO Don't only encrypt with the main cipher, but also use user specified cipher.
//TODO Use own exception for cpputils::Serializer/cpputils::Deserializer errors and only catch them
//TODO To get rid of many size fields, introduce Serializer::writeNullTerminatedString() and Serializer::writeUnterminatedData() (the latter one just writes until the end)
class CryConfigEncryptor {
public:
using OuterCipher = cpputils::AES256_GCM;
@ -23,21 +21,14 @@ namespace cryfs {
CryConfigEncryptor(cpputils::unique_ref<InnerEncryptor> innerEncryptor, OuterCipher::EncryptionKey outerKey, cpputils::DerivedKeyConfig keyConfig);
cpputils::Data encrypt(const cpputils::Data &plaintext);
boost::optional <cpputils::Data> decrypt(const cpputils::Data &plaintext);
static void checkHeader(cpputils::Deserializer *deserializer);
static void writeHeader(cpputils::Serializer *serializer);
boost::optional <cpputils::Data> decrypt(const cpputils::Data &data);
private:
void _ignoreKey(cpputils::Deserializer *deserializer);
boost::optional<cpputils::Data> _loadAndDecryptConfigData(cpputils::Deserializer *deserializer);
cpputils::Data _serialize(const cpputils::Data &ciphertext);
boost::optional<cpputils::Data> _decryptInnerConfig(const cpputils::Data &encryptedInnerConfig);
cpputils::unique_ref<InnerEncryptor> _innerEncryptor;
OuterCipher::EncryptionKey _outerKey;
cpputils::DerivedKeyConfig _keyConfig;
static const std::string HEADER;
};
}

View File

@ -1,5 +1,6 @@
#include "CryConfigEncryptorFactory.h"
#include <messmer/cpp-utils/crypto/symmetric/ciphers.h>
#include "OuterConfig.h"
using namespace cpputils::logging;
using boost::optional;
@ -7,30 +8,40 @@ using boost::none;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using cpputils::Data;
using cpputils::Deserializer;
using cpputils::DerivedKey;
using cpputils::DerivedKeyConfig;
using cpputils::SCrypt;
using std::string;
namespace cryfs {
constexpr size_t CryConfigEncryptorFactory::OuterKeySize;
constexpr size_t CryConfigEncryptorFactory::MaxTotalKeySize;
optional<unique_ref<CryConfigEncryptor>> CryConfigEncryptorFactory::loadKey(const Data &ciphertext,
optional<unique_ref<CryConfigEncryptor>> CryConfigEncryptorFactory::loadKey(const Data &data,
const string &password) {
using Cipher = cpputils::AES256_GCM; //TODO Allow other ciphers
Deserializer deserializer(&ciphertext);
try {
CryConfigEncryptor::checkHeader(&deserializer);
auto derivedKey = _loadKey<Cipher>(&deserializer, password);
auto outerKey = derivedKey.key().take<OuterKeySize>();
auto innerKey = derivedKey.key().drop<OuterKeySize>();
return make_unique_ref<CryConfigEncryptor>(
make_unique_ref<ConcreteInnerEncryptor<Cipher>>(innerKey),
outerKey,
derivedKey.moveOutConfig()
);
} catch (const std::exception &e) {
LOG(ERROR) << "Error loading configuration: " << e.what();
return none; // This can be caused by invalid loaded data and is not necessarily a programming logic error. Don't throw exception.
auto outerConfig = OuterConfig::deserialize(data);
if (outerConfig == none) {
return none;
}
auto derivedKey = _deriveKey(outerConfig->keyConfig, password);
auto outerKey = derivedKey.key().take<OuterKeySize>();
auto innerKey = derivedKey.key().drop<OuterKeySize>().take<Cipher::EncryptionKey::BINARY_LENGTH>();
return make_unique_ref<CryConfigEncryptor>(
make_unique_ref<ConcreteInnerEncryptor<Cipher>>(innerKey),
outerKey,
derivedKey.moveOutConfig()
);
}
cpputils::DerivedKey<CryConfigEncryptorFactory::MaxTotalKeySize>
CryConfigEncryptorFactory::_deriveKey(const DerivedKeyConfig &keyConfig, const std::string &password) {
//TODO It would be better, not to generate a MaxTotalKeySize key here, but to generate the outer key first, and then
// (once we know which inner cipher was used) only generate as many key bytes as we need for the inner cipher.
// This would need a change in the scrypt interface though, because right now we can't continue past key computations.
auto key = SCrypt().generateKeyFromConfig<MaxTotalKeySize>(password, keyConfig);
return DerivedKey<MaxTotalKeySize>(keyConfig, std::move(key));
}
}

View File

@ -2,10 +2,11 @@
#ifndef MESSMER_CRYFS_SRC_CONFIG_CRYPTO_CRYCONFIGENCRYPTORFACTORY_H
#define MESSMER_CRYFS_SRC_CONFIG_CRYPTO_CRYCONFIGENCRYPTORFACTORY_H
#include "ConcreteInnerEncryptor.h"
#include "inner/ConcreteInnerEncryptor.h"
#include "CryConfigEncryptor.h"
#include <messmer/cpp-utils/pointer/unique_ref.h>
#include <messmer/cpp-utils/crypto/kdf/Scrypt.h>
#include "../CryCipher.h"
namespace cryfs {
//TODO Test
@ -14,16 +15,15 @@ namespace cryfs {
template<class Cipher>
static cpputils::unique_ref<CryConfigEncryptor> deriveKey(const std::string &password, const cpputils::SCryptSettings &scryptSettings);
static boost::optional <cpputils::unique_ref<CryConfigEncryptor>> loadKey(const cpputils::Data &ciphertext,
const std::string &password);
static boost::optional<cpputils::unique_ref<CryConfigEncryptor>> loadKey(const cpputils::Data &ciphertext,
const std::string &password);
private:
static constexpr size_t OuterKeySize = CryConfigEncryptor::OuterCipher::EncryptionKey::BINARY_LENGTH;
template<class Cipher> static constexpr size_t TotalKeySize();
static constexpr size_t MaxTotalKeySize = OuterKeySize + CryCiphers::MAX_KEY_SIZE;
template<class Cipher>
static cpputils::DerivedKey<CryConfigEncryptor::OuterCipher::EncryptionKey::BINARY_LENGTH + Cipher::EncryptionKey::BINARY_LENGTH>
_loadKey(cpputils::Deserializer *deserializer, const std::string &password);
static cpputils::DerivedKey<MaxTotalKeySize> _deriveKey(const cpputils::DerivedKeyConfig &keyConfig, const std::string &password);
};
template<class Cipher> constexpr size_t CryConfigEncryptorFactory::TotalKeySize() {
@ -32,6 +32,7 @@ namespace cryfs {
template<class Cipher>
cpputils::unique_ref<CryConfigEncryptor> CryConfigEncryptorFactory::deriveKey(const std::string &password, const cpputils::SCryptSettings &scryptSettings) {
//TODO Use _deriveKey(keyConfig, password) instead and get rid of cpputils::SCryptSettings class in favor of cpputils::DerivedKeyConfig
auto derivedKey = cpputils::SCrypt().generateKey<TotalKeySize<Cipher>()>(password, scryptSettings);
auto outerKey = derivedKey.key().template take<OuterKeySize>();
auto innerKey = derivedKey.key().template drop<OuterKeySize>();
@ -41,17 +42,6 @@ namespace cryfs {
derivedKey.moveOutConfig()
);
}
template<class Cipher>
cpputils::DerivedKey<CryConfigEncryptor::OuterCipher::EncryptionKey::BINARY_LENGTH + Cipher::EncryptionKey::BINARY_LENGTH>
CryConfigEncryptorFactory::_loadKey(cpputils::Deserializer *deserializer, const std::string &password) {
auto keyConfig = cpputils::DerivedKeyConfig::load(deserializer);
//TODO This is only kept here to recognize when this is run in tests. After tests are faster, replace this with something in main(), saying something like "Loading configuration file..."
std::cout << "Deriving secure key for config file..." << std::flush;
auto key = cpputils::SCrypt().generateKeyFromConfig<TotalKeySize<Cipher>()>(password, keyConfig);
std::cout << "done" << std::endl;
return cpputils::DerivedKey<TotalKeySize<Cipher>()>(std::move(keyConfig), std::move(key));
}
}
#endif

View File

@ -1,21 +0,0 @@
#include "InnerEncryptor.h"
using std::string;
using cpputils::Deserializer;
using cpputils::Serializer;
namespace cryfs {
const string InnerEncryptor::HEADER = "cryfs.config.inner;0";
void InnerEncryptor::_checkHeader(Deserializer *deserializer) {
string header = deserializer->readString();
if (header != HEADER) {
throw std::runtime_error("Invalid header");
}
}
void InnerEncryptor::_writeHeader(Serializer *serializer) {
serializer->writeString(HEADER);
}
}

View File

@ -0,0 +1,55 @@
#include "OuterConfig.h"
using std::string;
using std::exception;
using cpputils::Data;
using cpputils::Serializer;
using cpputils::Deserializer;
using cpputils::DerivedKeyConfig;
using boost::optional;
using boost::none;
using namespace cpputils::logging;
namespace cryfs {
const string OuterConfig::HEADER = "cryfs.config;0;scrypt";
void OuterConfig::_checkHeader(Deserializer *deserializer) {
string header = deserializer->readString();
if (header != HEADER) {
throw std::runtime_error("Invalid header");
}
}
void OuterConfig::_writeHeader(Serializer *serializer) {
serializer->writeString(HEADER);
}
Data OuterConfig::serialize() {
try {
Serializer serializer(Serializer::StringSize(HEADER)
+ keyConfig.serializedSize()
+ encryptedInnerConfig.size());
_writeHeader(&serializer);
keyConfig.serialize(&serializer);
serializer.writeTailData(encryptedInnerConfig);
return serializer.finished();
} catch (const exception &e) {
LOG(ERROR) << "Error serializing CryConfigEncryptor: " << e.what();
throw; // This is a programming logic error. Pass through exception.
}
}
optional<OuterConfig> OuterConfig::deserialize(const Data &data) {
Deserializer deserializer(&data);
try {
_checkHeader(&deserializer);
auto keyConfig = DerivedKeyConfig::deserialize(&deserializer);
auto encryptedInnerConfig = deserializer.readTailData();
deserializer.finished();
return OuterConfig {std::move(keyConfig), std::move(encryptedInnerConfig)};
} catch (const exception &e) {
LOG(ERROR) << "Error deserializing outer configuration: " << e.what();
return none; // This can be caused by invalid input data and does not have to be a programming error. Don't throw exception.
}
}
}

View File

@ -0,0 +1,26 @@
#pragma once
#ifndef CRYFS_OUTERCONFIG_H
#define CRYFS_OUTERCONFIG_H
#include <messmer/cpp-utils/crypto/kdf/DerivedKeyConfig.h>
#include <messmer/cpp-utils/data/Data.h>
#include <messmer/cpp-utils/data/Serializer.h>
#include <messmer/cpp-utils/data/Deserializer.h>
namespace cryfs {
struct OuterConfig {
cpputils::DerivedKeyConfig keyConfig;
cpputils::Data encryptedInnerConfig;
cpputils::Data serialize();
static boost::optional<OuterConfig> deserialize(const cpputils::Data &data);
private:
static void _checkHeader(cpputils::Deserializer *deserializer);
static void _writeHeader(cpputils::Serializer *serializer);
static const std::string HEADER;
};
}
#endif

View File

@ -0,0 +1,61 @@
#pragma once
#ifndef MESSMER_CRYFS_SRC_CONFIG_CRYPTO_INNER_CONCRETECRYCONFIGENCRYPTOR_H
#define MESSMER_CRYFS_SRC_CONFIG_CRYPTO_INNER_CONCRETECRYCONFIGENCRYPTOR_H
#include <messmer/cpp-utils/crypto/RandomPadding.h>
#include <messmer/cpp-utils/crypto/kdf/DerivedKey.h>
#include "InnerEncryptor.h"
#include "InnerConfig.h"
namespace cryfs {
//TODO Test
template<class Cipher>
class ConcreteInnerEncryptor: public InnerEncryptor {
public:
static constexpr size_t CONFIG_SIZE = 512; // Inner config data is grown to this size before encryption to hide its actual size
ConcreteInnerEncryptor(typename Cipher::EncryptionKey key);
cpputils::Data encrypt(const cpputils::Data &plaintext) const override;
boost::optional<cpputils::Data> decrypt(const cpputils::Data &ciphertext) const override;
private:
typename Cipher::EncryptionKey _key;
};
template<class Cipher>
ConcreteInnerEncryptor<Cipher>::ConcreteInnerEncryptor(typename Cipher::EncryptionKey key)
: _key(std::move(key)) {
}
template<class Cipher>
boost::optional<cpputils::Data> ConcreteInnerEncryptor<Cipher>::decrypt(const cpputils::Data &ciphertext) const {
auto innerConfig = InnerConfig::deserialize(ciphertext);
if (innerConfig == boost::none) {
return boost::none;
}
if (innerConfig->cipherName != Cipher::NAME) {
cpputils::logging::LOG(cpputils::logging::ERROR) << "Wrong inner cipher used";
return boost::none;
}
auto decrypted = Cipher::decrypt(static_cast<const uint8_t*>(innerConfig->encryptedConfig.data()), innerConfig->encryptedConfig.size(), _key);
if (decrypted == boost::none) {
return boost::none;
}
auto configData = cpputils::RandomPadding::remove(*decrypted);
if (configData == boost::none) {
return boost::none;
}
return std::move(*configData);
}
template<class Cipher>
cpputils::Data ConcreteInnerEncryptor<Cipher>::encrypt(const cpputils::Data &plaintext) const {
auto paddedPlaintext = cpputils::RandomPadding::add(plaintext, CONFIG_SIZE);
auto encrypted = Cipher::encrypt(static_cast<const uint8_t*>(paddedPlaintext.data()), paddedPlaintext.size(), _key);
return InnerConfig{Cipher::NAME, std::move(encrypted)}.serialize();
}
}
#endif

View File

@ -0,0 +1,55 @@
#include "InnerConfig.h"
#include <messmer/cpp-utils/logging/logging.h>
using std::string;
using std::exception;
using cpputils::Deserializer;
using cpputils::Serializer;
using cpputils::Data;
using boost::optional;
using boost::none;
using namespace cpputils::logging;
namespace cryfs {
const string InnerConfig::HEADER = "cryfs.config.inner;0";
Data InnerConfig::serialize() {
try {
Serializer serializer(Serializer::StringSize(HEADER)
+ Serializer::StringSize(cipherName)
+ encryptedConfig.size());
serializer.writeString(HEADER);
serializer.writeString(cipherName);
serializer.writeTailData(encryptedConfig);
return serializer.finished();
} catch (const exception &e) {
LOG(ERROR) << "Error serializing inner configuration: " << e.what();
throw; // This is a programming logic error, pass through exception.
}
}
optional<InnerConfig> InnerConfig::deserialize(const Data &data) {
Deserializer deserializer(&data);
try {
_checkHeader(&deserializer);
string cipherName = deserializer.readString();
auto result = deserializer.readTailData();
deserializer.finished();
return InnerConfig {cipherName, std::move(result)};
} catch (const exception &e) {
LOG(ERROR) << "Error deserializing inner configuration: " << e.what();
return none; // This can be caused by invalid input data and does not have to be a programming error. Don't throw exception.
}
}
void InnerConfig::_checkHeader(Deserializer *deserializer) {
string header = deserializer->readString();
if (header != HEADER) {
throw std::runtime_error("Invalid header");
}
}
void InnerConfig::_writeHeader(Serializer *serializer) {
serializer->writeString(HEADER);
}
}

View File

@ -0,0 +1,25 @@
#pragma once
#ifndef MESSMER_CRYFS_SRC_CONFIG_CRYPTO_INNER_INNERCONFIG_H
#define MESSMER_CRYFS_SRC_CONFIG_CRYPTO_INNER_INNERCONFIG_H
#include <messmer/cpp-utils/data/Data.h>
#include <messmer/cpp-utils/data/Serializer.h>
#include <messmer/cpp-utils/data/Deserializer.h>
namespace cryfs {
struct InnerConfig {
std::string cipherName;
cpputils::Data encryptedConfig;
cpputils::Data serialize();
static boost::optional<InnerConfig> deserialize(const cpputils::Data &data);
private:
static void _checkHeader(cpputils::Deserializer *deserializer);
static void _writeHeader(cpputils::Serializer *serializer);
static const std::string HEADER;
};
}
#endif

View File

@ -0,0 +1 @@
#include "InnerEncryptor.h"

View File

@ -1,6 +1,6 @@
#pragma once
#ifndef MESSMER_CRYFS_SRC_CONFIG_CRYPTO_INNERENCRYPTOR_H
#define MESSMER_CRYFS_SRC_CONFIG_CRYPTO_INNERENCRYPTOR_H
#ifndef MESSMER_CRYFS_SRC_CONFIG_CRYPTO_INNER_INNERENCRYPTOR_H
#define MESSMER_CRYFS_SRC_CONFIG_CRYPTO_INNER_INNERENCRYPTOR_H
#include <messmer/cpp-utils/data/Data.h>
#include <messmer/cpp-utils/pointer/unique_ref.h>
@ -13,13 +13,6 @@ namespace cryfs {
public:
virtual cpputils::Data encrypt(const cpputils::Data &plaintext) const = 0;
virtual boost::optional<cpputils::Data> decrypt(const cpputils::Data &plaintext) const = 0;
protected:
static void _checkHeader(cpputils::Deserializer *deserializer);
static void _writeHeader(cpputils::Serializer *serializer);
private:
static const std::string HEADER;
};
}