Encrypt config file twice - with an inner and an outer key

This commit is contained in:
Sebastian Messmer 2015-10-27 17:33:31 +01:00
parent 635349d636
commit d9eaac5f75
4 changed files with 48 additions and 23 deletions

View File

@ -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);
} }
} }

View File

@ -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;

View File

@ -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();

View File

@ -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