From 635349d6366f53a50f60ba5fe8a56efe82239baf Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Tue, 27 Oct 2015 15:28:11 +0100 Subject: [PATCH] Separate CryConfigEncryptor from InnerEncryptor. This is the first step to do two layers of encryption. --- .../crypto/ConcreteCryConfigEncryptor.cpp | 1 - .../crypto/ConcreteCryConfigEncryptor.h | 92 ------------------- src/config/crypto/ConcreteInnerEncryptor.cpp | 1 + src/config/crypto/ConcreteInnerEncryptor.h | 53 +++++++++++ src/config/crypto/CryConfigEncryptor.cpp | 53 ++++++++++- src/config/crypto/CryConfigEncryptor.h | 20 ++-- .../crypto/CryConfigEncryptorFactory.cpp | 14 +-- src/config/crypto/CryConfigEncryptorFactory.h | 10 +- src/config/crypto/InnerEncryptor.cpp | 1 + src/config/crypto/InnerEncryptor.h | 17 ++++ src/config/crypto/kdf/DerivedKey.h | 8 ++ src/config/crypto/kdf/DerivedKeyConfig.h | 2 - 12 files changed, 156 insertions(+), 116 deletions(-) delete mode 100644 src/config/crypto/ConcreteCryConfigEncryptor.cpp delete mode 100644 src/config/crypto/ConcreteCryConfigEncryptor.h create mode 100644 src/config/crypto/ConcreteInnerEncryptor.cpp create mode 100644 src/config/crypto/ConcreteInnerEncryptor.h create mode 100644 src/config/crypto/InnerEncryptor.cpp create mode 100644 src/config/crypto/InnerEncryptor.h diff --git a/src/config/crypto/ConcreteCryConfigEncryptor.cpp b/src/config/crypto/ConcreteCryConfigEncryptor.cpp deleted file mode 100644 index accdf1e0..00000000 --- a/src/config/crypto/ConcreteCryConfigEncryptor.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "ConcreteCryConfigEncryptor.h" diff --git a/src/config/crypto/ConcreteCryConfigEncryptor.h b/src/config/crypto/ConcreteCryConfigEncryptor.h deleted file mode 100644 index f5702b25..00000000 --- a/src/config/crypto/ConcreteCryConfigEncryptor.h +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once -#ifndef MESSMER_CRYFS_SRC_CONFIG_CRYPTO_CONCRETECRYCONFIGENCRYPTOR_H -#define MESSMER_CRYFS_SRC_CONFIG_CRYPTO_CONCRETECRYCONFIGENCRYPTOR_H - -#include -#include -#include "RandomPadding.h" -#include "CryConfigEncryptor.h" - -namespace cryfs { - //TODO Test - template - class ConcreteCryConfigEncryptor: public CryConfigEncryptor { - public: - using ConfigEncryptionKey = DerivedKey; - 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 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 - ConcreteCryConfigEncryptor::ConcreteCryConfigEncryptor(ConfigEncryptionKey key): _key(std::move(key)) { - } - - template - boost::optional ConcreteCryConfigEncryptor::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 - void ConcreteCryConfigEncryptor::_ignoreKey(cpputils::Deserializer *deserializer) { - DerivedKeyConfig::load(deserializer); - } - - template - cpputils::Data ConcreteCryConfigEncryptor::_loadAndDecryptConfigData(cpputils::Deserializer *deserializer) { - auto ciphertext = deserializer->readData(); - auto decrypted = Cipher::decrypt(static_cast(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 - cpputils::Data ConcreteCryConfigEncryptor::encrypt(const cpputils::Data &plaintext) { - auto paddedPlaintext = RandomPadding::add(plaintext, CONFIG_SIZE); - auto ciphertext = Cipher::encrypt(static_cast(paddedPlaintext.data()), paddedPlaintext.size(), _key.key()); - return _serialize(ciphertext); - } - - template - cpputils::Data ConcreteCryConfigEncryptor::_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 diff --git a/src/config/crypto/ConcreteInnerEncryptor.cpp b/src/config/crypto/ConcreteInnerEncryptor.cpp new file mode 100644 index 00000000..ef411bf1 --- /dev/null +++ b/src/config/crypto/ConcreteInnerEncryptor.cpp @@ -0,0 +1 @@ +#include "ConcreteInnerEncryptor.h" diff --git a/src/config/crypto/ConcreteInnerEncryptor.h b/src/config/crypto/ConcreteInnerEncryptor.h new file mode 100644 index 00000000..6f5f1c92 --- /dev/null +++ b/src/config/crypto/ConcreteInnerEncryptor.h @@ -0,0 +1,53 @@ +#pragma once +#ifndef MESSMER_CRYFS_SRC_CONFIG_CRYPTO_CONCRETECRYCONFIGENCRYPTOR_H +#define MESSMER_CRYFS_SRC_CONFIG_CRYPTO_CONCRETECRYCONFIGENCRYPTOR_H + +#include +#include +#include "RandomPadding.h" +#include "InnerEncryptor.h" +#include "kdf/DerivedKey.h" + +namespace cryfs { + //TODO Test + template + 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 decrypt(const cpputils::Data &ciphertext) const override; + private: + + typename Cipher::EncryptionKey _key; + }; + + + + template + ConcreteInnerEncryptor::ConcreteInnerEncryptor(typename Cipher::EncryptionKey key): _key(std::move(key)) { + } + + template + boost::optional ConcreteInnerEncryptor::decrypt(const cpputils::Data &ciphertext) const { + auto decrypted = Cipher::decrypt(static_cast(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 + cpputils::Data ConcreteInnerEncryptor::encrypt(const cpputils::Data &plaintext) const { + auto paddedPlaintext = RandomPadding::add(plaintext, CONFIG_SIZE); + return Cipher::encrypt(static_cast(paddedPlaintext.data()), paddedPlaintext.size(), _key); + } +} + +#endif diff --git a/src/config/crypto/CryConfigEncryptor.cpp b/src/config/crypto/CryConfigEncryptor.cpp index 6d4320da..8c058fe7 100644 --- a/src/config/crypto/CryConfigEncryptor.cpp +++ b/src/config/crypto/CryConfigEncryptor.cpp @@ -1,13 +1,20 @@ #include "CryConfigEncryptor.h" -#include 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, 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); } -} \ No newline at end of file + 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 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 CryConfigEncryptor::_loadAndDecryptConfigData(Deserializer *deserializer) { + auto ciphertext = deserializer->readData(); + return _innerEncryptor->decrypt(ciphertext); + } +} diff --git a/src/config/crypto/CryConfigEncryptor.h b/src/config/crypto/CryConfigEncryptor.h index 5da28090..6d324e81 100644 --- a/src/config/crypto/CryConfigEncryptor.h +++ b/src/config/crypto/CryConfigEncryptor.h @@ -2,13 +2,11 @@ #ifndef MESSMER_CRYFS_SRC_CONFIG_CRYPTO_CRYCONFIGENCRYPTOR_H #define MESSMER_CRYFS_SRC_CONFIG_CRYPTO_CRYCONFIGENCRYPTOR_H -#include #include #include #include -#include "kdf/DerivedKey.h" -#include -#include +#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, DerivedKeyConfig keyConfig); - virtual boost::optional decrypt(const cpputils::Data &plaintext) = 0; + cpputils::Data encrypt(const cpputils::Data &plaintext); + boost::optional decrypt(const cpputils::Data &plaintext); static void checkHeader(cpputils::Deserializer *deserializer); static void writeHeader(cpputils::Serializer *serializer); private: - template - static DerivedKey _loadKey(cpputils::Deserializer *deserializer, - const std::string &password); + void _ignoreKey(cpputils::Deserializer *deserializer); + boost::optional _loadAndDecryptConfigData(cpputils::Deserializer *deserializer); + cpputils::Data _serialize(const cpputils::Data &ciphertext); + + cpputils::unique_ref _innerEncryptor; + DerivedKeyConfig _keyConfig; static const std::string HEADER; }; diff --git a/src/config/crypto/CryConfigEncryptorFactory.cpp b/src/config/crypto/CryConfigEncryptorFactory.cpp index 81712b58..fc3a9416 100644 --- a/src/config/crypto/CryConfigEncryptorFactory.cpp +++ b/src/config/crypto/CryConfigEncryptorFactory.cpp @@ -23,19 +23,19 @@ namespace cryfs { return DerivedKey(std::move(keyConfig), std::move(key)); } - optional > CryConfigEncryptorFactory::loadKey(const Data &ciphertext, - const string &password) { + optional> CryConfigEncryptorFactory::loadKey(const Data &ciphertext, + const string &password) { Deserializer deserializer(&ciphertext); try { CryConfigEncryptor::checkHeader(&deserializer); auto key = _loadKey(&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( + make_unique_ref>(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. } } - -} \ No newline at end of file +} diff --git a/src/config/crypto/CryConfigEncryptorFactory.h b/src/config/crypto/CryConfigEncryptorFactory.h index 50a7c186..c0dce1ef 100644 --- a/src/config/crypto/CryConfigEncryptorFactory.h +++ b/src/config/crypto/CryConfigEncryptorFactory.h @@ -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 #include "kdf/Scrypt.h" @@ -11,7 +12,7 @@ namespace cryfs { class CryConfigEncryptorFactory { public: template - static cpputils::unique_ref deriveKey(const std::string &password); + static cpputils::unique_ref deriveKey(const std::string &password); static boost::optional > loadKey(const cpputils::Data &ciphertext, const std::string &password); @@ -25,7 +26,10 @@ namespace cryfs { template cpputils::unique_ref CryConfigEncryptorFactory::deriveKey(const std::string &password) { auto key = SCrypt().generateKey(password); - return cpputils::make_unique_ref>(std::move(key)); + return cpputils::make_unique_ref( + cpputils::make_unique_ref>(key.moveOutKey()), + key.moveOutConfig() + ); } } diff --git a/src/config/crypto/InnerEncryptor.cpp b/src/config/crypto/InnerEncryptor.cpp new file mode 100644 index 00000000..b9a12c2c --- /dev/null +++ b/src/config/crypto/InnerEncryptor.cpp @@ -0,0 +1 @@ +#include "InnerEncryptor.h" \ No newline at end of file diff --git a/src/config/crypto/InnerEncryptor.h b/src/config/crypto/InnerEncryptor.h new file mode 100644 index 00000000..38935328 --- /dev/null +++ b/src/config/crypto/InnerEncryptor.h @@ -0,0 +1,17 @@ +#pragma once +#ifndef MESSMER_CRYFS_SRC_CONFIG_CRYPTO_INNERENCRYPTOR_H +#define MESSMER_CRYFS_SRC_CONFIG_CRYPTO_INNERENCRYPTOR_H + +#include +#include +#include + +namespace cryfs { + class InnerEncryptor { + public: + virtual cpputils::Data encrypt(const cpputils::Data &plaintext) const = 0; + virtual boost::optional decrypt(const cpputils::Data &plaintext) const = 0; + }; +} + +#endif diff --git a/src/config/crypto/kdf/DerivedKey.h b/src/config/crypto/kdf/DerivedKey.h index 9c1e1981..62909d1a 100644 --- a/src/config/crypto/kdf/DerivedKey.h +++ b/src/config/crypto/kdf/DerivedKey.h @@ -17,9 +17,17 @@ namespace cryfs { return _config; } + DerivedKeyConfig moveOutConfig() { + return std::move(_config); + } + const cpputils::FixedSizeData &key() const { return _key; } + + cpputils::FixedSizeData moveOutKey() { + return std::move(_key); + } private: DerivedKeyConfig _config; cpputils::FixedSizeData _key; diff --git a/src/config/crypto/kdf/DerivedKeyConfig.h b/src/config/crypto/kdf/DerivedKeyConfig.h index 5b4b289e..247d92a5 100644 --- a/src/config/crypto/kdf/DerivedKeyConfig.h +++ b/src/config/crypto/kdf/DerivedKeyConfig.h @@ -44,8 +44,6 @@ namespace cryfs { uint64_t _N; uint32_t _r; uint32_t _p; - - DISALLOW_COPY_AND_ASSIGN(DerivedKeyConfig); }; }