Refactor config file handling
This commit is contained in:
parent
03ad5cbe45
commit
2104a85e95
@ -8,33 +8,36 @@ namespace bf = boost::filesystem;
|
||||
|
||||
using boost::property_tree::ptree;
|
||||
using std::string;
|
||||
using std::istream;
|
||||
using std::ostream;
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
CryConfig::CryConfig(const bf::path &configfile)
|
||||
:_configfile(configfile), _rootBlob(""), _encKey(""), _cipher("") {
|
||||
if (bf::exists(_configfile)) {
|
||||
load();
|
||||
}
|
||||
CryConfig::CryConfig()
|
||||
: _rootBlob(""), _encKey(""), _cipher("") {
|
||||
}
|
||||
|
||||
void CryConfig::load() {
|
||||
CryConfig::CryConfig(CryConfig &&rhs)
|
||||
: _rootBlob(std::move(rhs._rootBlob)), _encKey(std::move(rhs._encKey)), _cipher(std::move(rhs._cipher)) {
|
||||
}
|
||||
|
||||
void CryConfig::load(istream &loadSource) {
|
||||
ptree pt;
|
||||
read_json(_configfile.native(), pt);
|
||||
read_json(loadSource, pt);
|
||||
|
||||
_rootBlob = pt.get("cryfs.rootblob", "");
|
||||
_encKey = pt.get("cryfs.key", "");
|
||||
_cipher = pt.get("cryfs.cipher", "");
|
||||
}
|
||||
|
||||
void CryConfig::save() const {
|
||||
void CryConfig::save(ostream &writeDestination) const {
|
||||
ptree pt;
|
||||
|
||||
pt.put("cryfs.rootblob", _rootBlob);
|
||||
pt.put("cryfs.key", _encKey);
|
||||
pt.put("cryfs.cipher", _cipher);
|
||||
|
||||
write_json(_configfile.native(), pt);
|
||||
write_json(writeDestination, pt);
|
||||
}
|
||||
|
||||
const std::string &CryConfig::RootBlob() const {
|
||||
@ -61,8 +64,4 @@ void CryConfig::SetCipher(const std::string &value) {
|
||||
_cipher = value;
|
||||
}
|
||||
|
||||
CryConfig::~CryConfig() {
|
||||
save();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,13 +5,14 @@
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include "messmer/cpp-utils/macros.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
class CryConfig {
|
||||
class CryConfig final {
|
||||
public:
|
||||
explicit CryConfig(const boost::filesystem::path &configfile);
|
||||
virtual ~CryConfig();
|
||||
CryConfig();
|
||||
CryConfig(CryConfig &&rhs);
|
||||
|
||||
const std::string &RootBlob() const;
|
||||
void SetRootBlob(const std::string &value);
|
||||
@ -22,13 +23,10 @@ public:
|
||||
const std::string &Cipher() const;
|
||||
void SetCipher(const std::string &value);
|
||||
|
||||
void save() const;
|
||||
void load(std::istream &loadSource);
|
||||
void save(std::ostream &destination) const;
|
||||
|
||||
private:
|
||||
boost::filesystem::path _configfile;
|
||||
|
||||
void load();
|
||||
|
||||
std::string _rootBlob;
|
||||
std::string _encKey;
|
||||
std::string _cipher;
|
||||
|
72
src/config/CryConfigCreator.cpp
Normal file
72
src/config/CryConfigCreator.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
#include "CryConfigCreator.h"
|
||||
#include "CryCipher.h"
|
||||
#include <messmer/blockstore/implementations/encrypted/ciphers/ciphers.h>
|
||||
|
||||
using cpputils::Console;
|
||||
using cpputils::unique_ref;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
CryConfigCreator::CryConfigCreator(unique_ref<Console> console)
|
||||
:_console(std::move(console)) {
|
||||
}
|
||||
|
||||
CryConfig CryConfigCreator::create() {
|
||||
CryConfig config;
|
||||
config.SetCipher(_generateCipher());
|
||||
config.SetEncryptionKey(_generateEncKey(config.Cipher()));
|
||||
config.SetRootBlob(_generateRootBlobKey());
|
||||
return config;
|
||||
}
|
||||
|
||||
CryConfig CryConfigCreator::createForTest() {
|
||||
CryConfig config;
|
||||
config.SetCipher(_generateCipherForTest());
|
||||
config.SetEncryptionKey(_generateEncKeyForTest(config.Cipher()));
|
||||
config.SetRootBlob(_generateRootBlobKey());
|
||||
return config;
|
||||
}
|
||||
|
||||
string CryConfigCreator::_generateCipher() {
|
||||
vector<string> ciphers = CryCiphers::supportedCipherNames();
|
||||
string cipherName = "";
|
||||
bool askAgain = true;
|
||||
while(askAgain) {
|
||||
int cipherIndex = _console->ask("Which block cipher do you want to use?", ciphers);
|
||||
cipherName = ciphers[cipherIndex];
|
||||
askAgain = !_showWarningForCipherAndReturnIfOk(cipherName);
|
||||
};
|
||||
return cipherName;
|
||||
}
|
||||
|
||||
bool CryConfigCreator::_showWarningForCipherAndReturnIfOk(const string &cipherName) {
|
||||
auto warning = CryCiphers::find(cipherName).warning();
|
||||
if (warning == boost::none) {
|
||||
return true;
|
||||
}
|
||||
return _console->askYesNo(string() + (*warning) + " Do you want to take this cipher nevertheless?");
|
||||
}
|
||||
|
||||
string CryConfigCreator::_generateEncKey(const std::string &cipher) {
|
||||
_console->print("\nGenerating secure encryption key...");
|
||||
auto key = CryCiphers::find(cipher).createKey();
|
||||
_console->print("done\n");
|
||||
return key;
|
||||
}
|
||||
|
||||
string CryConfigCreator::_generateCipherForTest() {
|
||||
return "aes-256-gcm";
|
||||
}
|
||||
|
||||
string CryConfigCreator::_generateEncKeyForTest(const std::string &) {
|
||||
return blockstore::encrypted::AES256_GCM::EncryptionKey::CreatePseudoRandom().ToString();
|
||||
}
|
||||
|
||||
string CryConfigCreator::_generateRootBlobKey() {
|
||||
//An empty root blob entry will tell CryDevice to create a new root blob
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
31
src/config/CryConfigCreator.h
Normal file
31
src/config/CryConfigCreator.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef CRYFS_SRC_CONFIG_CRYCONFIGCREATOR_H
|
||||
#define CRYFS_SRC_CONFIG_CRYCONFIGCREATOR_H
|
||||
|
||||
#include <messmer/cpp-utils/pointer/unique_ref.h>
|
||||
#include <messmer/cpp-utils/io/Console.h>
|
||||
#include "CryConfig.h"
|
||||
|
||||
namespace cryfs {
|
||||
class CryConfigCreator final {
|
||||
public:
|
||||
CryConfigCreator(cpputils::unique_ref<cpputils::Console> console);
|
||||
|
||||
CryConfig create();
|
||||
CryConfig createForTest();
|
||||
private:
|
||||
std::string _generateCipher();
|
||||
std::string _generateEncKey(const std::string &cipher);
|
||||
std::string _generateRootBlobKey();
|
||||
bool _showWarningForCipherAndReturnIfOk(const std::string &cipherName);
|
||||
|
||||
//TODO Don't have these functions here, but use a CryConfigCreator interface and mock it in the tests
|
||||
std::string _generateEncKeyForTest(const std::string &cipher);
|
||||
std::string _generateCipherForTest();
|
||||
|
||||
cpputils::unique_ref<cpputils::Console> _console;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CryConfigCreator);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
44
src/config/CryConfigFile.cpp
Normal file
44
src/config/CryConfigFile.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include "CryConfigFile.h"
|
||||
#include <fstream>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
using std::ifstream;
|
||||
using std::ofstream;
|
||||
namespace bf = boost::filesystem;
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
CryConfigFile CryConfigFile::create(const bf::path &path, CryConfig config) {
|
||||
return CryConfigFile(path, std::move(config));
|
||||
}
|
||||
|
||||
optional<CryConfigFile> CryConfigFile::load(const bf::path &path) {
|
||||
if (!bf::exists(path)) {
|
||||
return none;
|
||||
}
|
||||
ifstream file(path.native());
|
||||
CryConfig config;
|
||||
config.load(file);
|
||||
return CryConfigFile(path, std::move(config));
|
||||
}
|
||||
|
||||
CryConfigFile::CryConfigFile(const bf::path &path, CryConfig config)
|
||||
: _path (path), _config(std::move(config)) {
|
||||
}
|
||||
|
||||
CryConfigFile::CryConfigFile(CryConfigFile &&rhs)
|
||||
: _path(std::move(rhs._path)), _config(std::move(rhs._config)) {
|
||||
}
|
||||
|
||||
void CryConfigFile::save() const {
|
||||
ofstream file(_path.native(), ofstream::out|ofstream::binary|ofstream::trunc);
|
||||
_config.save(file);
|
||||
}
|
||||
|
||||
CryConfig *CryConfigFile::config() {
|
||||
return &_config;
|
||||
}
|
||||
|
||||
}
|
29
src/config/CryConfigFile.h
Normal file
29
src/config/CryConfigFile.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef CRYFS_SRC_CONFIG_CRYCONFIGFILE_H
|
||||
#define CRYFS_SRC_CONFIG_CRYCONFIGFILE_H
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include "CryConfig.h"
|
||||
|
||||
namespace cryfs {
|
||||
class CryConfigFile final {
|
||||
public:
|
||||
CryConfigFile(CryConfigFile &&rhs);
|
||||
|
||||
static CryConfigFile create(const boost::filesystem::path &path, CryConfig config);
|
||||
static boost::optional<CryConfigFile> load(const boost::filesystem::path &path);
|
||||
void save() const;
|
||||
|
||||
CryConfig *config();
|
||||
|
||||
private:
|
||||
CryConfigFile(const boost::filesystem::path &path, CryConfig config);
|
||||
|
||||
boost::filesystem::path _path;
|
||||
CryConfig _config;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CryConfigFile);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,4 +1,5 @@
|
||||
#include "CryConfigLoader.h"
|
||||
#include "CryConfigFile.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace bf = boost::filesystem;
|
||||
@ -15,95 +16,36 @@ namespace cryfs {
|
||||
|
||||
CryConfigLoader::CryConfigLoader(): CryConfigLoader(make_unique_ref<IOStreamConsole>()) {}
|
||||
|
||||
CryConfigLoader::CryConfigLoader(unique_ref<Console> console) : _console(std::move(console)) {}
|
||||
CryConfigLoader::CryConfigLoader(unique_ref<Console> console) : _creator(std::move(console)) {}
|
||||
|
||||
unique_ref<CryConfig> CryConfigLoader::loadOrCreate(const bf::path &filename) {
|
||||
auto config = loadExisting(filename);
|
||||
CryConfigFile CryConfigLoader::loadOrCreate(const bf::path &filename) {
|
||||
auto config = CryConfigFile::load(filename);
|
||||
if (config != none) {
|
||||
return std::move(*config);
|
||||
}
|
||||
return createNew(filename);
|
||||
}
|
||||
|
||||
unique_ref<CryConfig> CryConfigLoader::createNew(const bf::path &filename) {
|
||||
auto config = make_unique_ref<CryConfig>(filename);
|
||||
_initializeConfig(config.get());
|
||||
config->save();
|
||||
return config;
|
||||
CryConfigFile CryConfigLoader::createNew(const bf::path &filename) {
|
||||
auto config = _creator.create();
|
||||
auto configFile = CryConfigFile::create(filename, std::move(config));
|
||||
configFile.save();
|
||||
return configFile;
|
||||
}
|
||||
|
||||
void CryConfigLoader::_initializeConfig(CryConfig *config) {
|
||||
_generateCipher(config);
|
||||
_generateEncKey(config);
|
||||
_generateRootBlobKey(config);
|
||||
}
|
||||
|
||||
void CryConfigLoader::_initializeConfigWithWeakKey(CryConfig *config) {
|
||||
_generateTestCipher(config);
|
||||
_generateWeakEncKey(config);
|
||||
_generateRootBlobKey(config);
|
||||
}
|
||||
|
||||
void CryConfigLoader::_generateCipher(CryConfig *config) {
|
||||
vector<string> ciphers = CryCiphers::supportedCipherNames();
|
||||
string cipherName = "";
|
||||
bool askAgain = true;
|
||||
while(askAgain) {
|
||||
int cipherIndex = _console->ask("Which block cipher do you want to use?", ciphers);
|
||||
cipherName = ciphers[cipherIndex];
|
||||
askAgain = !_showWarningForCipherAndReturnIfOk(cipherName);
|
||||
};
|
||||
config->SetCipher(cipherName);
|
||||
}
|
||||
|
||||
bool CryConfigLoader::_showWarningForCipherAndReturnIfOk(const string &cipherName) {
|
||||
auto warning = CryCiphers::find(cipherName).warning();
|
||||
if (warning == boost::none) {
|
||||
return true;
|
||||
}
|
||||
return _console->askYesNo(string() + (*warning) + " Do you want to take this cipher nevertheless?");
|
||||
}
|
||||
|
||||
void CryConfigLoader::_generateEncKey(CryConfig *config) {
|
||||
_console->print("\nGenerating secure encryption key...");
|
||||
config->SetEncryptionKey(CryCiphers::find(config->Cipher()).createKey());
|
||||
_console->print("done\n");
|
||||
}
|
||||
|
||||
void CryConfigLoader::_generateTestCipher(CryConfig *config) {
|
||||
config->SetCipher("aes-256-gcm");
|
||||
}
|
||||
|
||||
void CryConfigLoader::_generateWeakEncKey(CryConfig *config) {
|
||||
auto new_key = blockstore::encrypted::AES256_GCM::EncryptionKey::CreatePseudoRandom();
|
||||
config->SetEncryptionKey(new_key.ToString());
|
||||
}
|
||||
|
||||
void CryConfigLoader::_generateRootBlobKey(CryConfig *config) {
|
||||
//An empty root blob entry will tell CryDevice to create a new root blob
|
||||
config->SetRootBlob("");
|
||||
}
|
||||
|
||||
optional<unique_ref<CryConfig>> CryConfigLoader::loadExisting(const bf::path &filename) {
|
||||
if (bf::exists(filename)) {
|
||||
return make_unique_ref<CryConfig>(filename);
|
||||
}
|
||||
return none;
|
||||
}
|
||||
|
||||
unique_ref<CryConfig> CryConfigLoader::loadOrCreateWithWeakKey(const bf::path &filename) {
|
||||
auto config = loadExisting(filename);
|
||||
CryConfigFile CryConfigLoader::loadOrCreateForTest(const bf::path &filename) {
|
||||
auto config = CryConfigFile::load(filename);
|
||||
if (config != none) {
|
||||
return std::move(*config);
|
||||
}
|
||||
return createNewWithWeakKey(filename);
|
||||
return createNewForTest(filename);
|
||||
}
|
||||
|
||||
unique_ref<CryConfig> CryConfigLoader::createNewWithWeakKey(const bf::path &filename) {
|
||||
auto config = make_unique_ref<CryConfig>(filename);
|
||||
_initializeConfigWithWeakKey(config.get());
|
||||
config->save();
|
||||
return config;
|
||||
CryConfigFile CryConfigLoader::createNewForTest(const bf::path &filename) {
|
||||
auto config = _creator.createForTest();
|
||||
auto configFile = CryConfigFile::create(filename, std::move(config));
|
||||
configFile.save();
|
||||
return configFile;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,10 +4,9 @@
|
||||
|
||||
#include <messmer/cpp-utils/pointer/unique_ref.h>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include "CryConfig.h"
|
||||
#include "CryConfigFile.h"
|
||||
#include "CryCipher.h"
|
||||
#include <messmer/blockstore/implementations/encrypted/ciphers/ciphers.h>
|
||||
#include <messmer/cpp-utils/io/Console.h>
|
||||
#include "CryConfigCreator.h"
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
@ -16,28 +15,15 @@ public:
|
||||
CryConfigLoader();
|
||||
explicit CryConfigLoader(cpputils::unique_ref<cpputils::Console> console);
|
||||
|
||||
cpputils::unique_ref<CryConfig> loadOrCreate(const boost::filesystem::path &filename);
|
||||
CryConfigFile loadOrCreate(const boost::filesystem::path &filename);
|
||||
CryConfigFile createNew(const boost::filesystem::path &filename);
|
||||
|
||||
cpputils::unique_ref<CryConfig> createNew(const boost::filesystem::path &filename);
|
||||
boost::optional<cpputils::unique_ref<CryConfig>> loadExisting(const boost::filesystem::path &filename);
|
||||
|
||||
//This method is only for testing purposes, because creating weak keys is much faster than creating strong keys.
|
||||
cpputils::unique_ref<CryConfig> loadOrCreateWithWeakKey(const boost::filesystem::path &filename);
|
||||
cpputils::unique_ref<CryConfig> createNewWithWeakKey(const boost::filesystem::path &filename);
|
||||
//This methods are only for testing purposes, because creating weak keys is much faster than creating strong keys.
|
||||
CryConfigFile loadOrCreateForTest(const boost::filesystem::path &filename);
|
||||
CryConfigFile createNewForTest(const boost::filesystem::path &filename);
|
||||
|
||||
private:
|
||||
void _initializeConfig(CryConfig *config);
|
||||
void _generateCipher(CryConfig *config);
|
||||
void _generateEncKey(CryConfig *config);
|
||||
void _generateRootBlobKey(CryConfig *config);
|
||||
|
||||
void _initializeConfigWithWeakKey(CryConfig *config); // TODO Rename to _initializeConfigForTest
|
||||
void _generateWeakEncKey(CryConfig *config); // TODO Rename to _generateTestEncKey
|
||||
void _generateTestCipher(CryConfig *config);
|
||||
|
||||
bool _showWarningForCipherAndReturnIfOk(const std::string &cipherName);
|
||||
|
||||
cpputils::unique_ref<cpputils::Console> _console;
|
||||
CryConfigCreator _creator;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -46,27 +46,24 @@ namespace cryfs {
|
||||
|
||||
constexpr uint32_t CryDevice::BLOCKSIZE_BYTES;
|
||||
|
||||
CryDevice::CryDevice(unique_ref<CryConfig> config, unique_ref<BlockStore> blockStore)
|
||||
CryDevice::CryDevice(CryConfigFile configFile, unique_ref<BlockStore> blockStore)
|
||||
: _fsBlobStore(
|
||||
make_unique_ref<ParallelAccessFsBlobStore>(
|
||||
make_unique_ref<CachingFsBlobStore>(
|
||||
make_unique_ref<FsBlobStore>(
|
||||
make_unique_ref<BlobStoreOnBlocks>(
|
||||
make_unique_ref<CachingBlockStore>(
|
||||
CreateEncryptedBlockStore(*config, std::move(blockStore))
|
||||
CreateEncryptedBlockStore(*configFile.config(), std::move(blockStore))
|
||||
), BLOCKSIZE_BYTES)))
|
||||
)
|
||||
),
|
||||
_rootKey(GetOrCreateRootKey(config.get())) {
|
||||
_rootKey(GetOrCreateRootKey(&configFile)) {
|
||||
}
|
||||
|
||||
Key CryDevice::CreateRootBlobAndReturnKey() {
|
||||
return _fsBlobStore->createDirBlob()->key();
|
||||
}
|
||||
|
||||
CryDevice::~CryDevice() {
|
||||
}
|
||||
|
||||
optional<unique_ref<fspp::Node>> CryDevice::Load(const bf::path &path) {
|
||||
ASSERT(path.is_absolute(), "Non absolute path given");
|
||||
|
||||
@ -149,12 +146,12 @@ void CryDevice::RemoveBlob(const blockstore::Key &key) {
|
||||
_fsBlobStore->remove(std::move(*blob));
|
||||
}
|
||||
|
||||
Key CryDevice::GetOrCreateRootKey(CryConfig *config) {
|
||||
string root_key = config->RootBlob();
|
||||
Key CryDevice::GetOrCreateRootKey(CryConfigFile *configFile) {
|
||||
string root_key = configFile->config()->RootBlob();
|
||||
if (root_key == "") {
|
||||
auto new_key = CreateRootBlobAndReturnKey();
|
||||
config->SetRootBlob(new_key.ToString());
|
||||
config->save();
|
||||
configFile->config()->SetRootBlob(new_key.ToString());
|
||||
configFile->save();
|
||||
return new_key;
|
||||
}
|
||||
|
||||
|
@ -15,12 +15,11 @@
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
class CryDevice: public fspp::Device {
|
||||
class CryDevice final: public fspp::Device {
|
||||
public:
|
||||
static constexpr uint32_t BLOCKSIZE_BYTES = 32 * 1024;
|
||||
|
||||
CryDevice(cpputils::unique_ref<CryConfig> config, cpputils::unique_ref<blockstore::BlockStore> blockStore);
|
||||
virtual ~CryDevice();
|
||||
CryDevice(CryConfigFile config, cpputils::unique_ref<blockstore::BlockStore> blockStore);
|
||||
|
||||
void statfs(const boost::filesystem::path &path, struct ::statvfs *fsstat) override;
|
||||
|
||||
@ -41,7 +40,7 @@ private:
|
||||
|
||||
blockstore::Key _rootKey;
|
||||
|
||||
blockstore::Key GetOrCreateRootKey(CryConfig *config);
|
||||
blockstore::Key GetOrCreateRootKey(CryConfigFile *config);
|
||||
blockstore::Key CreateRootBlobAndReturnKey();
|
||||
static cpputils::unique_ref<blockstore::BlockStore> CreateEncryptedBlockStore(const CryConfig &config, cpputils::unique_ref<blockstore::BlockStore> baseBlockStore);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user