Separate CryConfigEncryptor from InnerEncryptor. This is the first step to do two layers of encryption.

This commit is contained in:
Sebastian Messmer 2015-10-27 15:28:11 +01:00
parent 88262c3ef9
commit 635349d636
12 changed files with 156 additions and 116 deletions

View File

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

View File

@ -1,92 +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 "RandomPadding.h"
#include "CryConfigEncryptor.h"
namespace cryfs {
//TODO Test
template<class Cipher>
class ConcreteCryConfigEncryptor: public CryConfigEncryptor {
public:
using ConfigEncryptionKey = DerivedKey<Cipher::EncryptionKey::BINARY_LENGTH>;
static constexpr size_t CONFIG_SIZE = 1024; // Config data is grown to this size before encryption to hide its actual size
ConcreteCryConfigEncryptor(ConfigEncryptionKey key);
cpputils::Data encrypt(const cpputils::Data &plaintext) override;
boost::optional<cpputils::Data> decrypt(const cpputils::Data &ciphertext) override;
private:
void _ignoreKey(cpputils::Deserializer *deserializer);
cpputils::Data _loadAndDecryptConfigData(cpputils::Deserializer *deserializer);
cpputils::Data _serialize(const cpputils::Data &ciphertext);
ConfigEncryptionKey _key;
};
template<class Cipher>
ConcreteCryConfigEncryptor<Cipher>::ConcreteCryConfigEncryptor(ConfigEncryptionKey key): _key(std::move(key)) {
}
template<class Cipher>
boost::optional<cpputils::Data> ConcreteCryConfigEncryptor<Cipher>::decrypt(const cpputils::Data &data) {
cpputils::Deserializer deserializer(&data);
try {
checkHeader(&deserializer);
_ignoreKey(&deserializer);
return _loadAndDecryptConfigData(&deserializer);
} catch (const std::exception &e) {
cpputils::logging::LOG(cpputils::logging::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.
}
}
template<class Cipher>
void ConcreteCryConfigEncryptor<Cipher>::_ignoreKey(cpputils::Deserializer *deserializer) {
DerivedKeyConfig::load(deserializer);
}
template<class Cipher>
cpputils::Data ConcreteCryConfigEncryptor<Cipher>::_loadAndDecryptConfigData(cpputils::Deserializer *deserializer) {
auto ciphertext = deserializer->readData();
auto decrypted = Cipher::decrypt(static_cast<const uint8_t*>(ciphertext.data()), ciphertext.size(), _key.key());
if (decrypted == boost::none) {
throw std::runtime_error("Couldn't decrypt config file. Wrong password?");
}
auto configData = RandomPadding::remove(*decrypted);
if (configData == boost::none) {
throw std::runtime_error("Couldn't decrypt config file because of wrong padding");
}
return std::move(*configData);
}
template<class Cipher>
cpputils::Data ConcreteCryConfigEncryptor<Cipher>::encrypt(const cpputils::Data &plaintext) {
auto paddedPlaintext = RandomPadding::add(plaintext, CONFIG_SIZE);
auto ciphertext = Cipher::encrypt(static_cast<const uint8_t*>(paddedPlaintext.data()), paddedPlaintext.size(), _key.key());
return _serialize(ciphertext);
}
template <class Cipher>
cpputils::Data ConcreteCryConfigEncryptor<Cipher>::_serialize(const cpputils::Data &ciphertext) {
try {
cpputils::Serializer serializer(cpputils::Serializer::StringSize(HEADER)
+ _key.config().serializedSize()
+ cpputils::Serializer::DataSize(ciphertext));
writeHeader(&serializer);
_key.config().serialize(&serializer);
serializer.writeData(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.
}
}
}
#endif

View File

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

View File

@ -0,0 +1,53 @@
#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 "RandomPadding.h"
#include "InnerEncryptor.h"
#include "kdf/DerivedKey.h"
namespace cryfs {
//TODO Test
template<class Cipher>
class ConcreteInnerEncryptor: public InnerEncryptor {
public:
static constexpr size_t CONFIG_SIZE = 1024; // 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 decrypted = Cipher::decrypt(static_cast<const uint8_t*>(ciphertext.data()), ciphertext.size(), _key);
if (decrypted == boost::none) {
return boost::none;
}
auto configData = 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 = RandomPadding::add(plaintext, CONFIG_SIZE);
return Cipher::encrypt(static_cast<const uint8_t*>(paddedPlaintext.data()), paddedPlaintext.size(), _key);
}
}
#endif

View File

@ -1,13 +1,20 @@
#include "CryConfigEncryptor.h"
#include <messmer/cpp-utils/logging/logging.h>
using std::string;
using cpputils::Deserializer;
using cpputils::Serializer;
using cpputils::unique_ref;
using cpputils::Data;
using boost::optional;
using boost::none;
namespace cryfs {
const string CryConfigEncryptor::HEADER = "cryfs.config;0.8.1;scrypt";
CryConfigEncryptor::CryConfigEncryptor(unique_ref<InnerEncryptor> innerEncryptor, DerivedKeyConfig keyConfig)
: _innerEncryptor(std::move(innerEncryptor)), _keyConfig(std::move(keyConfig)) {
}
void CryConfigEncryptor::checkHeader(Deserializer *deserializer) {
string header = deserializer->readString();
if (header != HEADER) {
@ -19,4 +26,46 @@ namespace cryfs {
serializer->writeString(HEADER);
}
}
Data CryConfigEncryptor::encrypt(const Data &plaintext) {
auto ciphertext = _innerEncryptor->encrypt(plaintext);
return _serialize(ciphertext);
}
Data CryConfigEncryptor::_serialize(const Data &ciphertext) {
try {
Serializer serializer(Serializer::StringSize(HEADER)
+ _keyConfig.serializedSize()
+ Serializer::DataSize(ciphertext));
writeHeader(&serializer);
_keyConfig.serialize(&serializer);
serializer.writeData(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 &plaintext) {
Deserializer deserializer(&plaintext);
try {
checkHeader(&deserializer);
_ignoreKey(&deserializer);
auto configData = _loadAndDecryptConfigData(&deserializer);
deserializer.finished();
return configData;
} catch (const std::exception &e) {
cpputils::logging::LOG(cpputils::logging::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->readData();
return _innerEncryptor->decrypt(ciphertext);
}
}

View File

@ -2,13 +2,11 @@
#ifndef MESSMER_CRYFS_SRC_CONFIG_CRYPTO_CRYCONFIGENCRYPTOR_H
#define MESSMER_CRYFS_SRC_CONFIG_CRYPTO_CRYCONFIGENCRYPTOR_H
#include <messmer/cpp-utils/data/Data.h>
#include <messmer/cpp-utils/pointer/unique_ref.h>
#include <messmer/cpp-utils/data/Deserializer.h>
#include <messmer/cpp-utils/data/Serializer.h>
#include "kdf/DerivedKey.h"
#include <string>
#include <stdexcept>
#include "InnerEncryptor.h"
#include "kdf/DerivedKeyConfig.h"
namespace cryfs {
//TODO Test
@ -17,17 +15,21 @@ namespace cryfs {
//TODO Use own exception for cpputils::Serializer/cpputils::Deserializer errors and only catch them
class CryConfigEncryptor {
public:
virtual cpputils::Data encrypt(const cpputils::Data &plaintext) = 0;
CryConfigEncryptor(cpputils::unique_ref<InnerEncryptor> innerEncryptor, DerivedKeyConfig keyConfig);
virtual boost::optional <cpputils::Data> decrypt(const cpputils::Data &plaintext) = 0;
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);
private:
template<class Cipher>
static DerivedKey<Cipher::EncryptionKey::BINARY_LENGTH> _loadKey(cpputils::Deserializer *deserializer,
const std::string &password);
void _ignoreKey(cpputils::Deserializer *deserializer);
boost::optional<cpputils::Data> _loadAndDecryptConfigData(cpputils::Deserializer *deserializer);
cpputils::Data _serialize(const cpputils::Data &ciphertext);
cpputils::unique_ref<InnerEncryptor> _innerEncryptor;
DerivedKeyConfig _keyConfig;
static const std::string HEADER;
};

View File

@ -23,19 +23,19 @@ namespace cryfs {
return DerivedKey<Cipher::EncryptionKey::BINARY_LENGTH>(std::move(keyConfig), std::move(key));
}
optional <unique_ref<CryConfigEncryptor>> CryConfigEncryptorFactory::loadKey(const Data &ciphertext,
const string &password) {
optional<unique_ref<CryConfigEncryptor>> CryConfigEncryptorFactory::loadKey(const Data &ciphertext,
const string &password) {
Deserializer deserializer(&ciphertext);
try {
CryConfigEncryptor::checkHeader(&deserializer);
auto key = _loadKey<blockstore::encrypted::AES256_GCM>(&deserializer, password); //TODO Allow other ciphers
return optional < unique_ref < CryConfigEncryptor >> (make_unique_ref < ConcreteCryConfigEncryptor <
blockstore::encrypted::AES256_GCM >>
(std::move(key))); //TODO Allow other ciphers
return make_unique_ref<CryConfigEncryptor>(
make_unique_ref<ConcreteInnerEncryptor<blockstore::encrypted::AES256_GCM>>(key.moveOutKey()), //TODO Allow other ciphers
key.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.
}
}
}
}

View File

@ -2,7 +2,8 @@
#ifndef MESSMER_CRYFS_SRC_CONFIG_CRYPTO_CRYCONFIGENCRYPTORFACTORY_H
#define MESSMER_CRYFS_SRC_CONFIG_CRYPTO_CRYCONFIGENCRYPTORFACTORY_H
#include "ConcreteCryConfigEncryptor.h"
#include "ConcreteInnerEncryptor.h"
#include "CryConfigEncryptor.h"
#include <messmer/cpp-utils/pointer/unique_ref.h>
#include "kdf/Scrypt.h"
@ -11,7 +12,7 @@ namespace cryfs {
class CryConfigEncryptorFactory {
public:
template<class Cipher, class SCryptConfig>
static cpputils::unique_ref <CryConfigEncryptor> deriveKey(const std::string &password);
static cpputils::unique_ref<CryConfigEncryptor> deriveKey(const std::string &password);
static boost::optional <cpputils::unique_ref<CryConfigEncryptor>> loadKey(const cpputils::Data &ciphertext,
const std::string &password);
@ -25,7 +26,10 @@ namespace cryfs {
template<class Cipher, class SCryptConfig>
cpputils::unique_ref<CryConfigEncryptor> CryConfigEncryptorFactory::deriveKey(const std::string &password) {
auto key = SCrypt().generateKey<Cipher::EncryptionKey::BINARY_LENGTH, SCryptConfig>(password);
return cpputils::make_unique_ref<ConcreteCryConfigEncryptor<Cipher>>(std::move(key));
return cpputils::make_unique_ref<CryConfigEncryptor>(
cpputils::make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key.moveOutKey()),
key.moveOutConfig()
);
}
}

View File

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

View File

@ -0,0 +1,17 @@
#pragma once
#ifndef MESSMER_CRYFS_SRC_CONFIG_CRYPTO_INNERENCRYPTOR_H
#define MESSMER_CRYFS_SRC_CONFIG_CRYPTO_INNERENCRYPTOR_H
#include <messmer/cpp-utils/data/Data.h>
#include <messmer/cpp-utils/pointer/unique_ref.h>
#include <boost/optional.hpp>
namespace cryfs {
class InnerEncryptor {
public:
virtual cpputils::Data encrypt(const cpputils::Data &plaintext) const = 0;
virtual boost::optional <cpputils::Data> decrypt(const cpputils::Data &plaintext) const = 0;
};
}
#endif

View File

@ -17,9 +17,17 @@ namespace cryfs {
return _config;
}
DerivedKeyConfig moveOutConfig() {
return std::move(_config);
}
const cpputils::FixedSizeData<KEY_LENGTH> &key() const {
return _key;
}
cpputils::FixedSizeData<KEY_LENGTH> moveOutKey() {
return std::move(_key);
}
private:
DerivedKeyConfig _config;
cpputils::FixedSizeData<KEY_LENGTH> _key;

View File

@ -44,8 +44,6 @@ namespace cryfs {
uint64_t _N;
uint32_t _r;
uint32_t _p;
DISALLOW_COPY_AND_ASSIGN(DerivedKeyConfig);
};
}