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 {
|
||||
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)) {
|
||||
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) {
|
||||
@ -27,7 +27,8 @@ namespace cryfs {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -66,6 +67,10 @@ namespace cryfs {
|
||||
|
||||
optional<Data> CryConfigEncryptor::_loadAndDecryptConfigData(Deserializer *deserializer) {
|
||||
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 "InnerEncryptor.h"
|
||||
#include "kdf/DerivedKeyConfig.h"
|
||||
#include <messmer/blockstore/implementations/encrypted/ciphers/ciphers.h>
|
||||
|
||||
namespace cryfs {
|
||||
//TODO Test
|
||||
@ -15,7 +16,9 @@ namespace cryfs {
|
||||
//TODO Use own exception for cpputils::Serializer/cpputils::Deserializer errors and only catch them
|
||||
class CryConfigEncryptor {
|
||||
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);
|
||||
boost::optional <cpputils::Data> decrypt(const cpputils::Data &plaintext);
|
||||
@ -29,6 +32,7 @@ namespace cryfs {
|
||||
cpputils::Data _serialize(const cpputils::Data &ciphertext);
|
||||
|
||||
cpputils::unique_ref<InnerEncryptor> _innerEncryptor;
|
||||
OuterCipher::EncryptionKey _outerKey;
|
||||
DerivedKeyConfig _keyConfig;
|
||||
|
||||
static const std::string HEADER;
|
||||
|
@ -12,26 +12,21 @@ using std::string;
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
template<class Cipher>
|
||||
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));
|
||||
}
|
||||
constexpr size_t CryConfigEncryptorFactory::OuterKeySize;
|
||||
|
||||
optional<unique_ref<CryConfigEncryptor>> CryConfigEncryptorFactory::loadKey(const Data &ciphertext,
|
||||
const string &password) {
|
||||
using Cipher = blockstore::encrypted::AES256_GCM; //TODO Allow other ciphers
|
||||
Deserializer deserializer(&ciphertext);
|
||||
try {
|
||||
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>(
|
||||
make_unique_ref<ConcreteInnerEncryptor<blockstore::encrypted::AES256_GCM>>(key.moveOutKey()), //TODO Allow other ciphers
|
||||
key.moveOutConfig()
|
||||
make_unique_ref<ConcreteInnerEncryptor<Cipher>>(innerKey),
|
||||
outerKey,
|
||||
derivedKey.moveOutConfig()
|
||||
);
|
||||
} catch (const std::exception &e) {
|
||||
LOG(ERROR) << "Error loading configuration: " << e.what();
|
||||
|
@ -18,19 +18,40 @@ namespace cryfs {
|
||||
const std::string &password);
|
||||
|
||||
private:
|
||||
static constexpr size_t OuterKeySize = CryConfigEncryptor::OuterCipher::EncryptionKey::BINARY_LENGTH;
|
||||
template<class Cipher> static constexpr size_t TotalKeySize();
|
||||
|
||||
template<class Cipher>
|
||||
static DerivedKey<Cipher::EncryptionKey::BINARY_LENGTH> _loadKey(cpputils::Deserializer *deserializer,
|
||||
const std::string &password);
|
||||
static DerivedKey<CryConfigEncryptor::OuterCipher::EncryptionKey::BINARY_LENGTH + Cipher::EncryptionKey::BINARY_LENGTH>
|
||||
_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>
|
||||
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>(
|
||||
cpputils::make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key.moveOutKey()),
|
||||
key.moveOutConfig()
|
||||
cpputils::make_unique_ref<ConcreteInnerEncryptor<Cipher>>(innerKey),
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user