Separate CryConfigEncryptor from InnerEncryptor. This is the first step to do two layers of encryption.
This commit is contained in:
parent
88262c3ef9
commit
635349d636
@ -1 +0,0 @@
|
||||
#include "ConcreteCryConfigEncryptor.h"
|
@ -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
|
1
src/config/crypto/ConcreteInnerEncryptor.cpp
Normal file
1
src/config/crypto/ConcreteInnerEncryptor.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "ConcreteInnerEncryptor.h"
|
53
src/config/crypto/ConcreteInnerEncryptor.h
Normal file
53
src/config/crypto/ConcreteInnerEncryptor.h
Normal 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
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
1
src/config/crypto/InnerEncryptor.cpp
Normal file
1
src/config/crypto/InnerEncryptor.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "InnerEncryptor.h"
|
17
src/config/crypto/InnerEncryptor.h
Normal file
17
src/config/crypto/InnerEncryptor.h
Normal 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
|
@ -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;
|
||||
|
@ -44,8 +44,6 @@ namespace cryfs {
|
||||
uint64_t _N;
|
||||
uint32_t _r;
|
||||
uint32_t _p;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DerivedKeyConfig);
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user