Make test cases faster by using SCrypt::TestSettings

This commit is contained in:
Sebastian Messmer 2015-11-03 20:27:00 -08:00
parent 2f5d28440e
commit 0b7182f095
13 changed files with 71 additions and 65 deletions

View File

@ -39,6 +39,9 @@ using cpputils::make_unique_ref;
using cpputils::Random; using cpputils::Random;
using cpputils::IOStreamConsole; using cpputils::IOStreamConsole;
using cpputils::TempFile; using cpputils::TempFile;
using cpputils::RandomGenerator;
using cpputils::unique_ref;
using cpputils::SCryptSettings;
using std::cout; using std::cout;
using std::string; using std::string;
using std::endl; using std::endl;
@ -52,11 +55,12 @@ using boost::none;
//TODO Did deadlock in bonnie++ second run (in the create files sequentially) - maybe also in a later run or different step? //TODO Did deadlock in bonnie++ second run (in the create files sequentially) - maybe also in a later run or different step?
//TODO Improve error message when root blob wasn't found. //TODO Improve error message when root blob wasn't found.
//TODO Replace ASSERTs with other error handling when it is not a programming error but an environment influence (e.g. a block is missing) //TODO Replace ASSERTs with other error handling when it is not a programming error but an environment influence (e.g. a block is missing)
//TODO Fuse error messages like "fuse: bad mount point `...': Transport endpoint is not connected" go missing when running in background //TODO Test cases fail indeterministically. Fix!
namespace cryfs { namespace cryfs {
Cli::Cli(cpputils::RandomGenerator &keyGenerator): _keyGenerator(keyGenerator) {} Cli::Cli(RandomGenerator &keyGenerator, const SCryptSettings &scryptSettings):
_keyGenerator(keyGenerator), _scryptSettings(scryptSettings) {}
void Cli::_showVersion() { void Cli::_showVersion() {
cout << "CryFS Version " << version::VERSION_STRING << endl; cout << "CryFS Version " << version::VERSION_STRING << endl;
@ -122,7 +126,7 @@ namespace cryfs {
auto configFile = _determineConfigFile(options); auto configFile = _determineConfigFile(options);
auto console = make_unique_ref<IOStreamConsole>(); auto console = make_unique_ref<IOStreamConsole>();
std::cout << "Loading config file..." << std::endl; std::cout << "Loading config file..." << std::endl;
auto config = CryConfigLoader(std::move(console), _keyGenerator, std::bind(&Cli::_getPassword, this, std::cref(options)), options.cipher()).loadOrCreate(configFile); auto config = CryConfigLoader(std::move(console), _keyGenerator, _scryptSettings, std::bind(&Cli::_getPassword, this, std::cref(options)), options.cipher()).loadOrCreate(configFile);
std::cout << "Loading config file...done" << std::endl; std::cout << "Loading config file...done" << std::endl;
if (config == none) { if (config == none) {
std::cerr << "Could not load config file. Did you enter the correct password?" << std::endl; std::cerr << "Could not load config file. Did you enter the correct password?" << std::endl;

View File

@ -11,7 +11,7 @@
namespace cryfs { namespace cryfs {
class Cli final { class Cli final {
public: public:
Cli(cpputils::RandomGenerator &keyGenerator); Cli(cpputils::RandomGenerator &keyGenerator, const cpputils::SCryptSettings &scryptSettings);
int main(int argc, char *argv[]); int main(int argc, char *argv[]);
private: private:
@ -31,6 +31,7 @@ namespace cryfs {
void _checkDirReadable(const boost::filesystem::path &dir, std::shared_ptr<cpputils::TempFile> tempfile, const std::string &name); void _checkDirReadable(const boost::filesystem::path &dir, std::shared_ptr<cpputils::TempFile> tempfile, const std::string &name);
cpputils::RandomGenerator &_keyGenerator; cpputils::RandomGenerator &_keyGenerator;
cpputils::SCryptSettings _scryptSettings;
}; };
} }

View File

@ -15,6 +15,7 @@ using std::stringstream;
using std::istream; using std::istream;
using cpputils::Data; using cpputils::Data;
using cpputils::unique_ref; using cpputils::unique_ref;
using cpputils::SCryptSettings;
namespace bf = boost::filesystem; namespace bf = boost::filesystem;
using namespace cpputils::logging; using namespace cpputils::logging;
@ -42,6 +43,16 @@ optional<CryConfigFile> CryConfigFile::load(const bf::path &path, const string &
return CryConfigFile(path, std::move(config), std::move(*encryptor)); return CryConfigFile(path, std::move(config), std::move(*encryptor));
} }
CryConfigFile CryConfigFile::create(const bf::path &path, CryConfig config, const string &password, const SCryptSettings &scryptSettings) {
using ConfigCipher = cpputils::AES256_GCM; // TODO Take cipher from config instead
if (bf::exists(path)) {
throw std::runtime_error("Config file exists already.");
}
auto result = CryConfigFile(path, std::move(config), CryConfigEncryptorFactory::deriveKey<ConfigCipher>(password, scryptSettings));
result.save();
return result;
}
CryConfigFile::CryConfigFile(const bf::path &path, CryConfig config, unique_ref<CryConfigEncryptor> encryptor) CryConfigFile::CryConfigFile(const bf::path &path, CryConfig config, unique_ref<CryConfigEncryptor> encryptor)
: _path (path), _config(std::move(config)), _encryptor(std::move(encryptor)) { : _path (path), _config(std::move(config)), _encryptor(std::move(encryptor)) {
} }

View File

@ -14,8 +14,7 @@ namespace cryfs {
CryConfigFile(CryConfigFile &&rhs) = default; CryConfigFile(CryConfigFile &&rhs) = default;
~CryConfigFile(); ~CryConfigFile();
template<class SCryptConfig> static CryConfigFile create(const boost::filesystem::path &path, CryConfig config, const std::string &password, const cpputils::SCryptSettings &scryptSettings);
static CryConfigFile create(const boost::filesystem::path &path, CryConfig config, const std::string &password);
static boost::optional<CryConfigFile> load(const boost::filesystem::path &path, const std::string &password); static boost::optional<CryConfigFile> load(const boost::filesystem::path &path, const std::string &password);
void save() const; void save() const;
@ -30,17 +29,6 @@ namespace cryfs {
DISALLOW_COPY_AND_ASSIGN(CryConfigFile); DISALLOW_COPY_AND_ASSIGN(CryConfigFile);
}; };
template<class SCryptSettings>
CryConfigFile CryConfigFile::create(const boost::filesystem::path &path, CryConfig config, const std::string &password) {
using ConfigCipher = cpputils::AES256_GCM; // TODO Take cipher from config instead
if (boost::filesystem::exists(path)) {
throw std::runtime_error("Config file exists already.");
}
auto result = CryConfigFile(path, std::move(config), CryConfigEncryptorFactory::deriveKey<ConfigCipher, SCryptSettings>(password));
result.save();
return result;
}
} }
#endif #endif

View File

@ -11,17 +11,19 @@ using cpputils::Console;
using cpputils::IOStreamConsole; using cpputils::IOStreamConsole;
using cpputils::Random; using cpputils::Random;
using cpputils::RandomGenerator; using cpputils::RandomGenerator;
using cpputils::SCryptSettings;
using boost::optional; using boost::optional;
using boost::none; using boost::none;
using std::vector; using std::vector;
using std::string; using std::string;
using std::function; using std::function;
using std::shared_ptr;
using namespace cpputils::logging; using namespace cpputils::logging;
namespace cryfs { namespace cryfs {
CryConfigLoader::CryConfigLoader(unique_ref<Console> console, RandomGenerator &keyGenerator, function<string()> askPassword, const optional<string> &cipher) CryConfigLoader::CryConfigLoader(unique_ref<Console> console, RandomGenerator &keyGenerator, const SCryptSettings &scryptSettings, function<string()> askPassword, const optional<string> &cipher)
: _creator(std::move(console), keyGenerator), _askPassword(askPassword), _cipher(cipher) { : _creator(std::move(console), keyGenerator), _scryptSettings(scryptSettings), _askPassword(askPassword), _cipher(cipher) {
} }
optional<CryConfigFile> CryConfigLoader::_loadConfig(const bf::path &filename) { optional<CryConfigFile> CryConfigLoader::_loadConfig(const bf::path &filename) {
@ -37,4 +39,20 @@ optional<CryConfigFile> CryConfigLoader::_loadConfig(const bf::path &filename) {
return std::move(*config); return std::move(*config);
} }
optional<CryConfigFile> CryConfigLoader::loadOrCreate(const bf::path &filename) {
if (bf::exists(filename)) {
return _loadConfig(filename);
} else {
return _createConfig(filename);
}
}
CryConfigFile CryConfigLoader::_createConfig(const bf::path &filename) {
auto config = _creator.create(_cipher);
//TODO Ask confirmation if using insecure password (<8 characters)
string password = _askPassword();
return CryConfigFile::create(filename, std::move(config), password, _scryptSettings);
}
} }

View File

@ -13,41 +13,23 @@ namespace cryfs {
class CryConfigLoader { class CryConfigLoader {
public: public:
CryConfigLoader(cpputils::unique_ref<cpputils::Console> console, cpputils::RandomGenerator &keyGenerator, std::function<std::string()> askPassword, const boost::optional<std::string> &cipher); CryConfigLoader(cpputils::unique_ref<cpputils::Console> console, cpputils::RandomGenerator &keyGenerator, const cpputils::SCryptSettings &scryptSettings, std::function<std::string()> askPassword, const boost::optional<std::string> &cipher);
CryConfigLoader(CryConfigLoader &&rhs) = default; CryConfigLoader(CryConfigLoader &&rhs) = default;
template<class SCryptSettings = cpputils::SCryptDefaultSettings>
boost::optional<CryConfigFile> loadOrCreate(const boost::filesystem::path &filename); boost::optional<CryConfigFile> loadOrCreate(const boost::filesystem::path &filename);
private: private:
boost::optional<CryConfigFile> _loadConfig(const boost::filesystem::path &filename); boost::optional<CryConfigFile> _loadConfig(const boost::filesystem::path &filename);
template<class SCryptSettings>
CryConfigFile _createConfig(const boost::filesystem::path &filename); CryConfigFile _createConfig(const boost::filesystem::path &filename);
CryConfigCreator _creator; CryConfigCreator _creator;
cpputils::SCryptSettings _scryptSettings;
std::function<std::string()> _askPassword; std::function<std::string()> _askPassword;
boost::optional<std::string> _cipher; boost::optional<std::string> _cipher;
DISALLOW_COPY_AND_ASSIGN(CryConfigLoader); DISALLOW_COPY_AND_ASSIGN(CryConfigLoader);
}; };
template<class SCryptSettings>
boost::optional<CryConfigFile> CryConfigLoader::loadOrCreate(const boost::filesystem::path &filename) {
if (boost::filesystem::exists(filename)) {
return _loadConfig(filename);
} else {
return _createConfig<SCryptSettings>(filename);
}
}
template<class SCryptSettings>
CryConfigFile CryConfigLoader::_createConfig(const boost::filesystem::path &filename) {
auto config = _creator.create(_cipher);
//TODO Ask confirmation if using insecure password (<8 characters)
std::string password = _askPassword();
return CryConfigFile::create<SCryptSettings>(filename, std::move(config), password);
}
} }
#endif #endif

View File

@ -11,8 +11,8 @@ namespace cryfs {
//TODO Test //TODO Test
class CryConfigEncryptorFactory { class CryConfigEncryptorFactory {
public: public:
template<class Cipher, class SCryptConfig> template<class Cipher>
static cpputils::unique_ref<CryConfigEncryptor> deriveKey(const std::string &password); static cpputils::unique_ref<CryConfigEncryptor> deriveKey(const std::string &password, const cpputils::SCryptSettings &scryptSettings);
static boost::optional <cpputils::unique_ref<CryConfigEncryptor>> loadKey(const cpputils::Data &ciphertext, static boost::optional <cpputils::unique_ref<CryConfigEncryptor>> loadKey(const cpputils::Data &ciphertext,
const std::string &password); const std::string &password);
@ -30,9 +30,9 @@ namespace cryfs {
return OuterKeySize + Cipher::EncryptionKey::BINARY_LENGTH; return OuterKeySize + Cipher::EncryptionKey::BINARY_LENGTH;
} }
template<class Cipher, class SCryptConfig> template<class Cipher>
cpputils::unique_ref<CryConfigEncryptor> CryConfigEncryptorFactory::deriveKey(const std::string &password) { cpputils::unique_ref<CryConfigEncryptor> CryConfigEncryptorFactory::deriveKey(const std::string &password, const cpputils::SCryptSettings &scryptSettings) {
auto derivedKey = cpputils::SCrypt().generateKey<TotalKeySize<Cipher>(), SCryptConfig>(password); auto derivedKey = cpputils::SCrypt().generateKey<TotalKeySize<Cipher>()>(password, scryptSettings);
auto outerKey = derivedKey.key().template take<OuterKeySize>(); auto outerKey = derivedKey.key().template take<OuterKeySize>();
auto innerKey = derivedKey.key().template drop<OuterKeySize>(); auto innerKey = derivedKey.key().template drop<OuterKeySize>();
return cpputils::make_unique_ref<CryConfigEncryptor>( return cpputils::make_unique_ref<CryConfigEncryptor>(

View File

@ -1,9 +1,12 @@
#include "Cli.h" #include "Cli.h"
#include <messmer/cpp-utils/random/Random.h> #include <messmer/cpp-utils/random/Random.h>
#include <messmer/cpp-utils/crypto/kdf/Scrypt.h>
using namespace cryfs; using namespace cryfs;
using cpputils::Random;
using cpputils::SCrypt;
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
auto &keyGenerator = cpputils::Random::OSRandom(); auto &keyGenerator = Random::OSRandom();
return Cli(keyGenerator).main(argc, argv); return Cli(keyGenerator, SCrypt::DefaultSettings).main(argc, argv);
} }

View File

@ -29,7 +29,7 @@ public:
_args.push_back(const_cast<char*>(arg)); _args.push_back(const_cast<char*>(arg));
} }
auto &keyGenerator = cpputils::Random::PseudoRandom(); auto &keyGenerator = cpputils::Random::PseudoRandom();
cryfs::Cli(keyGenerator).main(_args.size(), _args.data()); cryfs::Cli(keyGenerator, cpputils::SCrypt::TestSettings).main(_args.size(), _args.data());
} }
void EXPECT_EXIT_WITH_HELP_MESSAGE(std::vector<const char*> args) { void EXPECT_EXIT_WITH_HELP_MESSAGE(std::vector<const char*> args) {
@ -54,10 +54,10 @@ public:
std::this_thread::sleep_for(std::chrono::milliseconds(50)); // TODO Is this the test case duration? Does a shorter interval make the test case faster? std::this_thread::sleep_for(std::chrono::milliseconds(50)); // TODO Is this the test case duration? Does a shorter interval make the test case faster?
} }
}); });
//testing::internal::CaptureStdout(); testing::internal::CaptureStdout();
run(args); run(args);
unmountThread.join(); unmountThread.join();
//EXPECT_THAT(testing::internal::GetCapturedStdout(), testing::MatchesRegex(".*Mounting filesystem.*")); EXPECT_THAT(testing::internal::GetCapturedStdout(), testing::MatchesRegex(".*Mounting filesystem.*"));
} }
}; };

View File

@ -3,13 +3,13 @@
#include "../../src/config/CryConfigFile.h" #include "../../src/config/CryConfigFile.h"
#include <messmer/cpp-utils/tempfile/TempFile.h> #include <messmer/cpp-utils/tempfile/TempFile.h>
#include <boost/optional/optional_io.hpp> #include <boost/optional/optional_io.hpp>
#include <messmer/cpp-utils/test/crypto/kdf/testutils/SCryptTestSettings.h>
using namespace cryfs; using namespace cryfs;
using cpputils::TempFile; using cpputils::TempFile;
using std::string; using std::string;
using boost::optional; using boost::optional;
using boost::none; using boost::none;
using cpputils::SCrypt;
namespace bf = boost::filesystem; namespace bf = boost::filesystem;
//gtest/boost::optional workaround for working with optional<CryConfigFile> //gtest/boost::optional workaround for working with optional<CryConfigFile>
@ -33,7 +33,7 @@ public:
} }
void Create(CryConfig cfg, const string &password = "mypassword") { void Create(CryConfig cfg, const string &password = "mypassword") {
CryConfigFile::create<SCryptTestSettings>(file.path(), std::move(cfg), password); CryConfigFile::create(file.path(), std::move(cfg), password, SCrypt::TestSettings);
} }
optional<CryConfigFile> Load(const string &password = "mypassword") { optional<CryConfigFile> Load(const string &password = "mypassword") {
@ -43,7 +43,7 @@ public:
void CreateWithCipher(const string &cipher, const TempFile &tempFile) { void CreateWithCipher(const string &cipher, const TempFile &tempFile) {
CryConfig cfg; CryConfig cfg;
cfg.SetCipher(cipher); cfg.SetCipher(cipher);
CryConfigFile::create<SCryptTestSettings>(tempFile.path(), std::move(cfg), "mypassword"); CryConfigFile::create(tempFile.path(), std::move(cfg), "mypassword", SCrypt::TestSettings);
} }
}; };

View File

@ -4,11 +4,11 @@
#include <messmer/cpp-utils/tempfile/TempFile.h> #include <messmer/cpp-utils/tempfile/TempFile.h>
#include <messmer/cpp-utils/random/Random.h> #include <messmer/cpp-utils/random/Random.h>
#include <messmer/cpp-utils/crypto/symmetric/ciphers.h> #include <messmer/cpp-utils/crypto/symmetric/ciphers.h>
#include <messmer/cpp-utils/test/crypto/kdf/testutils/SCryptTestSettings.h>
using cpputils::unique_ref; using cpputils::unique_ref;
using cpputils::make_unique_ref; using cpputils::make_unique_ref;
using cpputils::TempFile; using cpputils::TempFile;
using cpputils::SCrypt;
using boost::optional; using boost::optional;
using boost::none; using boost::none;
using std::string; using std::string;
@ -24,33 +24,33 @@ public:
CryConfigLoaderTest(): file(false) {} CryConfigLoaderTest(): file(false) {}
CryConfigLoader loader(const string &password, const optional<string> &cipher = none) { CryConfigLoader loader(const string &password, const optional<string> &cipher = none) {
return CryConfigLoader(mockConsole(), cpputils::Random::PseudoRandom(), [password] {return password;}, cipher); return CryConfigLoader(mockConsole(), cpputils::Random::PseudoRandom(), SCrypt::TestSettings, [password] {return password;}, cipher);
} }
CryConfigFile Create(const string &password = "mypassword", const optional<string> &cipher = none) { CryConfigFile Create(const string &password = "mypassword", const optional<string> &cipher = none) {
EXPECT_FALSE(file.exists()); EXPECT_FALSE(file.exists());
return loader(password, cipher).loadOrCreate<SCryptTestSettings>(file.path()).value(); return loader(password, cipher).loadOrCreate(file.path()).value();
} }
optional<CryConfigFile> Load(const string &password = "mypassword", const optional<string> &cipher = none) { optional<CryConfigFile> Load(const string &password = "mypassword", const optional<string> &cipher = none) {
EXPECT_TRUE(file.exists()); EXPECT_TRUE(file.exists());
return loader(password, cipher).loadOrCreate<SCryptTestSettings>(file.path()); return loader(password, cipher).loadOrCreate(file.path());
} }
void CreateWithRootBlob(const string &rootBlob, const string &password = "mypassword") { void CreateWithRootBlob(const string &rootBlob, const string &password = "mypassword") {
auto cfg = loader(password).loadOrCreate<SCryptTestSettings>(file.path()).value(); auto cfg = loader(password).loadOrCreate(file.path()).value();
cfg.config()->SetRootBlob(rootBlob); cfg.config()->SetRootBlob(rootBlob);
cfg.save(); cfg.save();
} }
void CreateWithCipher(const string &cipher, const string &password = "mypassword") { void CreateWithCipher(const string &cipher, const string &password = "mypassword") {
auto cfg = loader(password).loadOrCreate<SCryptTestSettings>(file.path()).value(); auto cfg = loader(password).loadOrCreate(file.path()).value();
cfg.config()->SetCipher(cipher); cfg.config()->SetCipher(cipher);
cfg.save(); cfg.save();
} }
void CreateWithEncryptionKey(const string &encKey, const string &password = "mypassword") { void CreateWithEncryptionKey(const string &encKey, const string &password = "mypassword") {
auto cfg = loader(password).loadOrCreate<SCryptTestSettings>(file.path()).value(); auto cfg = loader(password).loadOrCreate(file.path()).value();
cfg.config()->SetEncryptionKey(encKey); cfg.config()->SetEncryptionKey(encKey);
cfg.save(); cfg.save();
} }

View File

@ -9,7 +9,6 @@
#include "../../src/filesystem/CryOpenFile.h" #include "../../src/filesystem/CryOpenFile.h"
#include "../testutils/MockConsole.h" #include "../testutils/MockConsole.h"
#include "../../src/config/CryConfigLoader.h" #include "../../src/config/CryConfigLoader.h"
#include <messmer/cpp-utils/test/crypto/kdf/testutils/SCryptTestSettings.h>
//TODO (whole project) Make constructors explicit when implicit construction not needed //TODO (whole project) Make constructors explicit when implicit construction not needed
@ -23,6 +22,7 @@ using cpputils::make_unique_ref;
using cpputils::unique_ref; using cpputils::unique_ref;
using cpputils::Console; using cpputils::Console;
using cpputils::Random; using cpputils::Random;
using cpputils::SCrypt;
using blockstore::ondisk::OnDiskBlockStore; using blockstore::ondisk::OnDiskBlockStore;
using boost::none; using boost::none;
@ -35,7 +35,7 @@ public:
} }
CryConfigFile loadOrCreateConfig() { CryConfigFile loadOrCreateConfig() {
return CryConfigLoader(mockConsole(), Random::PseudoRandom(), [] {return "mypassword";}, none).loadOrCreate<SCryptTestSettings>(config.path()).value(); return CryConfigLoader(mockConsole(), Random::PseudoRandom(), SCrypt::TestSettings, [] {return "mypassword";}, none).loadOrCreate(config.path()).value();
} }
unique_ref<OnDiskBlockStore> blockStore() { unique_ref<OnDiskBlockStore> blockStore() {

View File

@ -5,12 +5,11 @@
#include "../../src/filesystem/CryDevice.h" #include "../../src/filesystem/CryDevice.h"
#include "../../src/config/CryConfigLoader.h" #include "../../src/config/CryConfigLoader.h"
#include "../testutils/MockConsole.h" #include "../testutils/MockConsole.h"
#include <messmer/cpp-utils/test/crypto/kdf/testutils/SCryptTestSettings.h>
using cpputils::unique_ref; using cpputils::unique_ref;
using cpputils::make_unique_ref; using cpputils::make_unique_ref;
using cpputils::Random; using cpputils::Random;
using cpputils::SCrypt;
using fspp::Device; using fspp::Device;
using ::testing::Return; using ::testing::Return;
using ::testing::_; using ::testing::_;
@ -28,8 +27,8 @@ public:
unique_ref<Device> createDevice() override { unique_ref<Device> createDevice() override {
auto blockStore = cpputils::make_unique_ref<FakeBlockStore>(); auto blockStore = cpputils::make_unique_ref<FakeBlockStore>();
auto config = CryConfigLoader(mockConsole(), Random::PseudoRandom(), [] {return "mypassword";}, none) auto config = CryConfigLoader(mockConsole(), Random::PseudoRandom(), SCrypt::TestSettings, [] {return "mypassword";}, none)
.loadOrCreate<SCryptTestSettings>(configFile.path()).value(); .loadOrCreate(configFile.path()).value();
return make_unique_ref<CryDevice>(std::move(config), std::move(blockStore)); return make_unique_ref<CryDevice>(std::move(config), std::move(blockStore));
} }