Encrypt config file twice - with an inner and an outer key
This commit is contained in:
parent
635349d636
commit
d9eaac5f75
@ -11,8 +11,8 @@ using boost::none;
|
|||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
const string CryConfigEncryptor::HEADER = "cryfs.config;0.8.1;scrypt";
|
const string CryConfigEncryptor::HEADER = "cryfs.config;0.8.1;scrypt";
|
||||||
|
|
||||||
CryConfigEncryptor::CryConfigEncryptor(unique_ref<InnerEncryptor> innerEncryptor, DerivedKeyConfig keyConfig)
|
CryConfigEncryptor::CryConfigEncryptor(unique_ref<InnerEncryptor> innerEncryptor, OuterCipher::EncryptionKey outerKey, DerivedKeyConfig keyConfig)
|
||||||
: _innerEncryptor(std::move(innerEncryptor)), _keyConfig(std::move(keyConfig)) {
|
: _innerEncryptor(std::move(innerEncryptor)), _outerKey(std::move(outerKey)), _keyConfig(std::move(keyConfig)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CryConfigEncryptor::checkHeader(Deserializer *deserializer) {
|
void CryConfigEncryptor::checkHeader(Deserializer *deserializer) {
|
||||||
@ -27,7 +27,8 @@ namespace cryfs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Data CryConfigEncryptor::encrypt(const Data &plaintext) {
|
Data CryConfigEncryptor::encrypt(const Data &plaintext) {
|
||||||
auto ciphertext = _innerEncryptor->encrypt(plaintext);
|
auto inner = _innerEncryptor->encrypt(plaintext);
|
||||||
|
auto ciphertext = OuterCipher::encrypt(static_cast<const uint8_t*>(inner.data()), inner.size(), _outerKey);
|
||||||
return _serialize(ciphertext);
|
return _serialize(ciphertext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +67,10 @@ namespace cryfs {
|
|||||||
|
|
||||||
optional<Data> CryConfigEncryptor::_loadAndDecryptConfigData(Deserializer *deserializer) {
|
optional<Data> CryConfigEncryptor::_loadAndDecryptConfigData(Deserializer *deserializer) {
|
||||||
auto ciphertext = deserializer->readData();
|
auto ciphertext = deserializer->readData();
|
||||||
return _innerEncryptor->decrypt(ciphertext);
|
auto inner = OuterCipher::decrypt(static_cast<const uint8_t*>(ciphertext.data()), ciphertext.size(), _outerKey);
|
||||||
|
if(inner == none) {
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
return _innerEncryptor->decrypt(*inner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <messmer/cpp-utils/data/Serializer.h>
|
#include <messmer/cpp-utils/data/Serializer.h>
|
||||||
#include "InnerEncryptor.h"
|
#include "InnerEncryptor.h"
|
||||||
#include "kdf/DerivedKeyConfig.h"
|
#include "kdf/DerivedKeyConfig.h"
|
||||||
|
#include <messmer/blockstore/implementations/encrypted/ciphers/ciphers.h>
|
||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
//TODO Test
|
//TODO Test
|
||||||
@ -15,7 +16,9 @@ namespace cryfs {
|
|||||||
//TODO Use own exception for cpputils::Serializer/cpputils::Deserializer errors and only catch them
|
//TODO Use own exception for cpputils::Serializer/cpputils::Deserializer errors and only catch them
|
||||||
class CryConfigEncryptor {
|
class CryConfigEncryptor {
|
||||||
public:
|
public:
|
||||||
CryConfigEncryptor(cpputils::unique_ref<InnerEncryptor> innerEncryptor, DerivedKeyConfig keyConfig);
|
using OuterCipher = blockstore::encrypted::AES256_GCM;
|
||||||
|
|
||||||
|
CryConfigEncryptor(cpputils::unique_ref<InnerEncryptor> innerEncryptor, OuterCipher::EncryptionKey outerKey, DerivedKeyConfig keyConfig);
|
||||||
|
|
||||||
cpputils::Data encrypt(const cpputils::Data &plaintext);
|
cpputils::Data encrypt(const cpputils::Data &plaintext);
|
||||||
boost::optional <cpputils::Data> decrypt(const cpputils::Data &plaintext);
|
boost::optional <cpputils::Data> decrypt(const cpputils::Data &plaintext);
|
||||||
@ -29,6 +32,7 @@ namespace cryfs {
|
|||||||
cpputils::Data _serialize(const cpputils::Data &ciphertext);
|
cpputils::Data _serialize(const cpputils::Data &ciphertext);
|
||||||
|
|
||||||
cpputils::unique_ref<InnerEncryptor> _innerEncryptor;
|
cpputils::unique_ref<InnerEncryptor> _innerEncryptor;
|
||||||
|
OuterCipher::EncryptionKey _outerKey;
|
||||||
DerivedKeyConfig _keyConfig;
|
DerivedKeyConfig _keyConfig;
|
||||||
|
|
||||||
static const std::string HEADER;
|
static const std::string HEADER;
|
||||||
|
@ -12,26 +12,21 @@ using std::string;
|
|||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
|
|
||||||
template<class Cipher>
|
constexpr size_t CryConfigEncryptorFactory::OuterKeySize;
|
||||||
DerivedKey<Cipher::EncryptionKey::BINARY_LENGTH> CryConfigEncryptorFactory::_loadKey(cpputils::Deserializer *deserializer,
|
|
||||||
const std::string &password) {
|
|
||||||
auto keyConfig = 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 = SCrypt().generateKeyFromConfig<Cipher::EncryptionKey::BINARY_LENGTH>(password, keyConfig);
|
|
||||||
std::cout << "done" << std::endl;
|
|
||||||
return DerivedKey<Cipher::EncryptionKey::BINARY_LENGTH>(std::move(keyConfig), std::move(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
optional<unique_ref<CryConfigEncryptor>> CryConfigEncryptorFactory::loadKey(const Data &ciphertext,
|
optional<unique_ref<CryConfigEncryptor>> CryConfigEncryptorFactory::loadKey(const Data &ciphertext,
|
||||||
const string &password) {
|
const string &password) {
|
||||||
|
using Cipher = blockstore::encrypted::AES256_GCM; //TODO Allow other ciphers
|
||||||
Deserializer deserializer(&ciphertext);
|
Deserializer deserializer(&ciphertext);
|
||||||
try {
|
try {
|
||||||
CryConfigEncryptor::checkHeader(&deserializer);
|
CryConfigEncryptor::checkHeader(&deserializer);
|
||||||
auto key = _loadKey<blockstore::encrypted::AES256_GCM>(&deserializer, password); //TODO Allow other ciphers
|
auto derivedKey = _loadKey<Cipher>(&deserializer, password);
|
||||||
|
auto outerKey = derivedKey.key().take<OuterKeySize>();
|
||||||
|
auto innerKey = derivedKey.key().drop<OuterKeySize>();
|
||||||
return make_unique_ref<CryConfigEncryptor>(
|
return make_unique_ref<CryConfigEncryptor>(
|
||||||
make_unique_ref<ConcreteInnerEncryptor<blockstore::encrypted::AES256_GCM>>(key.moveOutKey()), //TODO Allow other ciphers
|
make_unique_ref<ConcreteInnerEncryptor<Cipher>>(innerKey),
|
||||||
key.moveOutConfig()
|
outerKey,
|
||||||
|
derivedKey.moveOutConfig()
|
||||||
);
|
);
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
LOG(ERROR) << "Error loading configuration: " << e.what();
|
LOG(ERROR) << "Error loading configuration: " << e.what();
|
||||||
|
@ -18,19 +18,40 @@ namespace cryfs {
|
|||||||
const std::string &password);
|
const std::string &password);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr size_t OuterKeySize = CryConfigEncryptor::OuterCipher::EncryptionKey::BINARY_LENGTH;
|
||||||
|
template<class Cipher> static constexpr size_t TotalKeySize();
|
||||||
|
|
||||||
template<class Cipher>
|
template<class Cipher>
|
||||||
static DerivedKey<Cipher::EncryptionKey::BINARY_LENGTH> _loadKey(cpputils::Deserializer *deserializer,
|
static DerivedKey<CryConfigEncryptor::OuterCipher::EncryptionKey::BINARY_LENGTH + Cipher::EncryptionKey::BINARY_LENGTH>
|
||||||
const std::string &password);
|
_loadKey(cpputils::Deserializer *deserializer, const std::string &password);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class Cipher> constexpr size_t CryConfigEncryptorFactory::TotalKeySize() {
|
||||||
|
return OuterKeySize + Cipher::EncryptionKey::BINARY_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
template<class Cipher, class SCryptConfig>
|
template<class Cipher, class SCryptConfig>
|
||||||
cpputils::unique_ref<CryConfigEncryptor> CryConfigEncryptorFactory::deriveKey(const std::string &password) {
|
cpputils::unique_ref<CryConfigEncryptor> CryConfigEncryptorFactory::deriveKey(const std::string &password) {
|
||||||
auto key = SCrypt().generateKey<Cipher::EncryptionKey::BINARY_LENGTH, SCryptConfig>(password);
|
auto derivedKey = SCrypt().generateKey<TotalKeySize<Cipher>(), SCryptConfig>(password);
|
||||||
|
auto outerKey = derivedKey.key().template take<OuterKeySize>();
|
||||||
|
auto innerKey = derivedKey.key().template drop<OuterKeySize>();
|
||||||
return cpputils::make_unique_ref<CryConfigEncryptor>(
|
return cpputils::make_unique_ref<CryConfigEncryptor>(
|
||||||
cpputils::make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key.moveOutKey()),
|
cpputils::make_unique_ref<ConcreteInnerEncryptor<Cipher>>(innerKey),
|
||||||
key.moveOutConfig()
|
outerKey,
|
||||||
|
derivedKey.moveOutConfig()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
DerivedKey<CryConfigEncryptor::OuterCipher::EncryptionKey::BINARY_LENGTH + Cipher::EncryptionKey::BINARY_LENGTH>
|
||||||
|
CryConfigEncryptorFactory::_loadKey(cpputils::Deserializer *deserializer, const std::string &password) {
|
||||||
|
auto keyConfig = 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 = SCrypt().generateKeyFromConfig<TotalKeySize<Cipher>()>(password, keyConfig);
|
||||||
|
std::cout << "done" << std::endl;
|
||||||
|
return DerivedKey<TotalKeySize<Cipher>()>(std::move(keyConfig), std::move(key));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user