diff --git a/src/config/crypto/CryConfigEncryptor.cpp b/src/config/crypto/CryConfigEncryptor.cpp index 8c058fe7..76af0995 100644 --- a/src/config/crypto/CryConfigEncryptor.cpp +++ b/src/config/crypto/CryConfigEncryptor.cpp @@ -11,8 +11,8 @@ using boost::none; namespace cryfs { const string CryConfigEncryptor::HEADER = "cryfs.config;0.8.1;scrypt"; - CryConfigEncryptor::CryConfigEncryptor(unique_ref innerEncryptor, DerivedKeyConfig keyConfig) - : _innerEncryptor(std::move(innerEncryptor)), _keyConfig(std::move(keyConfig)) { + CryConfigEncryptor::CryConfigEncryptor(unique_ref 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(inner.data()), inner.size(), _outerKey); return _serialize(ciphertext); } @@ -66,6 +67,10 @@ namespace cryfs { optional CryConfigEncryptor::_loadAndDecryptConfigData(Deserializer *deserializer) { auto ciphertext = deserializer->readData(); - return _innerEncryptor->decrypt(ciphertext); + auto inner = OuterCipher::decrypt(static_cast(ciphertext.data()), ciphertext.size(), _outerKey); + if(inner == none) { + return none; + } + return _innerEncryptor->decrypt(*inner); } } diff --git a/src/config/crypto/CryConfigEncryptor.h b/src/config/crypto/CryConfigEncryptor.h index 6d324e81..10cee471 100644 --- a/src/config/crypto/CryConfigEncryptor.h +++ b/src/config/crypto/CryConfigEncryptor.h @@ -7,6 +7,7 @@ #include #include "InnerEncryptor.h" #include "kdf/DerivedKeyConfig.h" +#include 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, DerivedKeyConfig keyConfig); + using OuterCipher = blockstore::encrypted::AES256_GCM; + + CryConfigEncryptor(cpputils::unique_ref innerEncryptor, OuterCipher::EncryptionKey outerKey, DerivedKeyConfig keyConfig); cpputils::Data encrypt(const cpputils::Data &plaintext); boost::optional decrypt(const cpputils::Data &plaintext); @@ -29,6 +32,7 @@ namespace cryfs { cpputils::Data _serialize(const cpputils::Data &ciphertext); cpputils::unique_ref _innerEncryptor; + OuterCipher::EncryptionKey _outerKey; DerivedKeyConfig _keyConfig; static const std::string HEADER; diff --git a/src/config/crypto/CryConfigEncryptorFactory.cpp b/src/config/crypto/CryConfigEncryptorFactory.cpp index fc3a9416..6aa5a89e 100644 --- a/src/config/crypto/CryConfigEncryptorFactory.cpp +++ b/src/config/crypto/CryConfigEncryptorFactory.cpp @@ -12,26 +12,21 @@ using std::string; namespace cryfs { - template - DerivedKey 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(password, keyConfig); - std::cout << "done" << std::endl; - return DerivedKey(std::move(keyConfig), std::move(key)); - } + constexpr size_t CryConfigEncryptorFactory::OuterKeySize; optional> 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(&deserializer, password); //TODO Allow other ciphers + auto derivedKey = _loadKey(&deserializer, password); + auto outerKey = derivedKey.key().take(); + auto innerKey = derivedKey.key().drop(); return make_unique_ref( - make_unique_ref>(key.moveOutKey()), //TODO Allow other ciphers - key.moveOutConfig() + make_unique_ref>(innerKey), + outerKey, + derivedKey.moveOutConfig() ); } catch (const std::exception &e) { LOG(ERROR) << "Error loading configuration: " << e.what(); diff --git a/src/config/crypto/CryConfigEncryptorFactory.h b/src/config/crypto/CryConfigEncryptorFactory.h index c0dce1ef..6afbe014 100644 --- a/src/config/crypto/CryConfigEncryptorFactory.h +++ b/src/config/crypto/CryConfigEncryptorFactory.h @@ -18,19 +18,40 @@ namespace cryfs { const std::string &password); private: + static constexpr size_t OuterKeySize = CryConfigEncryptor::OuterCipher::EncryptionKey::BINARY_LENGTH; + template static constexpr size_t TotalKeySize(); + template - static DerivedKey _loadKey(cpputils::Deserializer *deserializer, - const std::string &password); + static DerivedKey + _loadKey(cpputils::Deserializer *deserializer, const std::string &password); }; + template constexpr size_t CryConfigEncryptorFactory::TotalKeySize() { + return OuterKeySize + Cipher::EncryptionKey::BINARY_LENGTH; + } + template cpputils::unique_ref CryConfigEncryptorFactory::deriveKey(const std::string &password) { - auto key = SCrypt().generateKey(password); + auto derivedKey = SCrypt().generateKey(), SCryptConfig>(password); + auto outerKey = derivedKey.key().template take(); + auto innerKey = derivedKey.key().template drop(); return cpputils::make_unique_ref( - cpputils::make_unique_ref>(key.moveOutKey()), - key.moveOutConfig() + cpputils::make_unique_ref>(innerKey), + outerKey, + derivedKey.moveOutConfig() ); } + + template + DerivedKey + 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()>(password, keyConfig); + std::cout << "done" << std::endl; + return DerivedKey()>(std::move(keyConfig), std::move(key)); + } } #endif