Make SCrypt config modifiable and speed up test cases by using a special test config
This commit is contained in:
parent
ed390108f4
commit
88262c3ef9
@ -8,7 +8,7 @@
|
||||
messmer/cmake: 3
|
||||
messmer/cpp-utils: 4
|
||||
messmer/fspp: 1
|
||||
messmer/gitversion: 5
|
||||
messmer/gitversion: 6
|
||||
messmer/parallelaccessstore: 1
|
||||
messmer/scrypt: 0
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <sstream>
|
||||
#include <messmer/cpp-utils/logging/logging.h>
|
||||
#include "crypto/CryConfigEncryptorFactory.h"
|
||||
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
@ -25,16 +24,6 @@ CryConfigFile::~CryConfigFile() {
|
||||
//We do not call save() here, because we do not want the config file to be re-encrypted on each filesystem run
|
||||
}
|
||||
|
||||
CryConfigFile CryConfigFile::create(const bf::path &path, CryConfig config, const string &password) {
|
||||
using ConfigCipher = blockstore::encrypted::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));
|
||||
result.save();
|
||||
return result;
|
||||
}
|
||||
|
||||
optional<CryConfigFile> CryConfigFile::load(const bf::path &path, const string &password) {
|
||||
auto encryptedConfigData = Data::LoadFromFile(path);
|
||||
if (encryptedConfigData == none) {
|
||||
|
@ -3,10 +3,11 @@
|
||||
#define MESSMER_CRYFS_SRC_CONFIG_CRYCONFIGFILE_H
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "CryConfig.h"
|
||||
#include "crypto/CryConfigEncryptor.h"
|
||||
#include "crypto/kdf/Scrypt.h"
|
||||
#include <messmer/blockstore/implementations/encrypted/ciphers/ciphers.h>
|
||||
#include "crypto/CryConfigEncryptorFactory.h"
|
||||
|
||||
namespace cryfs {
|
||||
class CryConfigFile final {
|
||||
@ -14,6 +15,7 @@ namespace cryfs {
|
||||
CryConfigFile(CryConfigFile &&rhs) = default;
|
||||
~CryConfigFile();
|
||||
|
||||
template<class SCryptConfig>
|
||||
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);
|
||||
void save() const;
|
||||
@ -29,6 +31,17 @@ namespace cryfs {
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CryConfigFile);
|
||||
};
|
||||
|
||||
template<class SCryptSettings>
|
||||
CryConfigFile CryConfigFile::create(const boost::filesystem::path &path, CryConfig config, const std::string &password) {
|
||||
using ConfigCipher = blockstore::encrypted::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
|
||||
|
@ -24,14 +24,6 @@ CryConfigLoader::CryConfigLoader(unique_ref<Console> console, RandomGenerator &k
|
||||
: _creator(std::move(console), keyGenerator), _askPassword(askPassword) {
|
||||
}
|
||||
|
||||
optional<CryConfigFile> CryConfigLoader::loadOrCreate(const bf::path &filename) {
|
||||
if (bf::exists(filename)) {
|
||||
return _loadConfig(filename);
|
||||
} else {
|
||||
return _createConfig(filename);
|
||||
}
|
||||
}
|
||||
|
||||
optional<CryConfigFile> CryConfigLoader::_loadConfig(const bf::path &filename) {
|
||||
string password = _askPassword();
|
||||
auto config = CryConfigFile::load(filename, password);
|
||||
@ -42,11 +34,4 @@ optional<CryConfigFile> CryConfigLoader::_loadConfig(const bf::path &filename) {
|
||||
return std::move(*config);
|
||||
}
|
||||
|
||||
CryConfigFile CryConfigLoader::_createConfig(const bf::path &filename) {
|
||||
auto config = _creator.create();
|
||||
//TODO Ask confirmation if using insecure password (<8 characters)
|
||||
string password = _askPassword();
|
||||
return CryConfigFile::create(filename, std::move(config), password);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,10 +3,11 @@
|
||||
#define MESSMER_CRYFS_SRC_CONFIG_CRYCONFIGLOADER_H_
|
||||
|
||||
#include <messmer/cpp-utils/pointer/unique_ref.h>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "CryConfigFile.h"
|
||||
#include "CryCipher.h"
|
||||
#include "CryConfigCreator.h"
|
||||
#include "crypto/kdf/Scrypt.h"
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
@ -15,10 +16,12 @@ public:
|
||||
CryConfigLoader(cpputils::unique_ref<cpputils::Console> console, cpputils::RandomGenerator &keyGenerator, std::function<std::string()> askPassword);
|
||||
CryConfigLoader(CryConfigLoader &&rhs) = default;
|
||||
|
||||
template<class SCryptSettings = SCryptDefaultSettings>
|
||||
boost::optional<CryConfigFile> loadOrCreate(const boost::filesystem::path &filename);
|
||||
|
||||
private:
|
||||
boost::optional<CryConfigFile> _loadConfig(const boost::filesystem::path &filename);
|
||||
template<class SCryptSettings>
|
||||
CryConfigFile _createConfig(const boost::filesystem::path &filename);
|
||||
|
||||
CryConfigCreator _creator;
|
||||
@ -27,6 +30,23 @@ private:
|
||||
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();
|
||||
//TODO Ask confirmation if using insecure password (<8 characters)
|
||||
std::string password = _askPassword();
|
||||
return CryConfigFile::create<SCryptSettings>(filename, std::move(config), password);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -10,7 +10,7 @@ namespace cryfs {
|
||||
//TODO Test
|
||||
class CryConfigEncryptorFactory {
|
||||
public:
|
||||
template<class Cipher>
|
||||
template<class Cipher, class SCryptConfig>
|
||||
static cpputils::unique_ref <CryConfigEncryptor> deriveKey(const std::string &password);
|
||||
|
||||
static boost::optional <cpputils::unique_ref<CryConfigEncryptor>> loadKey(const cpputils::Data &ciphertext,
|
||||
@ -22,12 +22,9 @@ namespace cryfs {
|
||||
const std::string &password);
|
||||
};
|
||||
|
||||
template<class Cipher>
|
||||
template<class Cipher, class SCryptConfig>
|
||||
cpputils::unique_ref<CryConfigEncryptor> CryConfigEncryptorFactory::deriveKey(const std::string &password) {
|
||||
//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().generateKey<Cipher::EncryptionKey::BINARY_LENGTH>(password);
|
||||
std::cout << "done" << std::endl;
|
||||
auto key = SCrypt().generateKey<Cipher::EncryptionKey::BINARY_LENGTH, SCryptConfig>(password);
|
||||
return cpputils::make_unique_ref<ConcreteCryConfigEncryptor<Cipher>>(std::move(key));
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,13 @@
|
||||
#include "Scrypt.h"
|
||||
|
||||
namespace cryfs {
|
||||
constexpr size_t SCrypt::SALT_LEN;
|
||||
constexpr uint64_t SCrypt::N;
|
||||
constexpr uint32_t SCrypt::r;
|
||||
constexpr uint32_t SCrypt::p;
|
||||
constexpr size_t SCryptDefaultSettings::SALT_LEN;
|
||||
constexpr uint64_t SCryptDefaultSettings::N;
|
||||
constexpr uint32_t SCryptDefaultSettings::r;
|
||||
constexpr uint32_t SCryptDefaultSettings::p;
|
||||
|
||||
constexpr size_t SCryptParanoidSettings::SALT_LEN;
|
||||
constexpr uint64_t SCryptParanoidSettings::N;
|
||||
constexpr uint32_t SCryptParanoidSettings::r;
|
||||
constexpr uint32_t SCryptParanoidSettings::p;
|
||||
}
|
@ -12,19 +12,27 @@ extern "C" {
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
class SCrypt {
|
||||
public:
|
||||
//TODO Make user-configurable. For sensitive storage, N=1048576, r=8 is recommended. For tests, we should use faster settings.
|
||||
struct SCryptParanoidSettings {
|
||||
constexpr static size_t SALT_LEN = 32; // Size of the salt
|
||||
constexpr static uint64_t N = 1048576; // CPU/Memory cost
|
||||
constexpr static uint32_t r = 8; // Blocksize
|
||||
constexpr static uint32_t p = 16; // Parallelization
|
||||
};
|
||||
|
||||
struct SCryptDefaultSettings {
|
||||
constexpr static size_t SALT_LEN = 32; // Size of the salt
|
||||
constexpr static uint64_t N = 524288; // CPU/Memory cost
|
||||
constexpr static uint32_t r = 1; // Blocksize
|
||||
constexpr static uint32_t p = 1; // Parallelization
|
||||
};
|
||||
|
||||
class SCrypt {
|
||||
public:
|
||||
SCrypt() {}
|
||||
|
||||
template<size_t KEYSIZE> DerivedKey<KEYSIZE> generateKey(const std::string &password) {
|
||||
auto salt = cpputils::Random::PseudoRandom().get(SALT_LEN);
|
||||
auto config = DerivedKeyConfig(std::move(salt), N, r, p);
|
||||
template<size_t KEYSIZE, class Settings = SCryptDefaultSettings> DerivedKey<KEYSIZE> generateKey(const std::string &password) {
|
||||
auto salt = cpputils::Random::PseudoRandom().get(Settings::SALT_LEN);
|
||||
auto config = DerivedKeyConfig(std::move(salt), Settings::N, Settings::r, Settings::p);
|
||||
auto key = generateKeyFromConfig<KEYSIZE>(password, config);
|
||||
return DerivedKey<KEYSIZE>(std::move(config), key);
|
||||
}
|
||||
|
@ -91,7 +91,9 @@ CryConfigFile loadOrCreateConfig(const ProgramOptions &options) {
|
||||
auto configFile = determineConfigFile(options);
|
||||
auto console = make_unique_ref<IOStreamConsole>();
|
||||
auto &keyGenerator = Random::OSRandom();
|
||||
std::cout << "Loading config file..." << std::flush;
|
||||
auto config = CryConfigLoader(std::move(console), keyGenerator, &askPassword).loadOrCreate(configFile);
|
||||
std::cout << "done" << std::endl;
|
||||
if (config == none) {
|
||||
std::cerr << "Could not load config file. Did you enter the correct password?" << std::endl;
|
||||
exit(1);
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "../../src/config/CryConfigFile.h"
|
||||
#include <messmer/cpp-utils/tempfile/TempFile.h>
|
||||
#include <boost/optional/optional_io.hpp>
|
||||
#include "testutils/SCryptTestSettings.h"
|
||||
|
||||
using namespace cryfs;
|
||||
using cpputils::TempFile;
|
||||
@ -32,7 +33,7 @@ public:
|
||||
}
|
||||
|
||||
void Create(CryConfig cfg, const string &password = "mypassword") {
|
||||
CryConfigFile::create(file.path(), std::move(cfg), password);
|
||||
CryConfigFile::create<SCryptTestSettings>(file.path(), std::move(cfg), password);
|
||||
}
|
||||
|
||||
optional<CryConfigFile> Load(const string &password = "mypassword") {
|
||||
@ -42,7 +43,7 @@ public:
|
||||
void CreateWithCipher(const string &cipher, const TempFile &tempFile) {
|
||||
CryConfig cfg;
|
||||
cfg.SetCipher(cipher);
|
||||
CryConfigFile::create(tempFile.path(), std::move(cfg), "mypassword");
|
||||
CryConfigFile::create<SCryptTestSettings>(tempFile.path(), std::move(cfg), "mypassword");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <messmer/cpp-utils/tempfile/TempFile.h>
|
||||
#include <messmer/cpp-utils/random/Random.h>
|
||||
#include <messmer/blockstore/implementations/encrypted/ciphers/ciphers.h>
|
||||
#include "testutils/SCryptTestSettings.h"
|
||||
|
||||
using cpputils::unique_ref;
|
||||
using cpputils::make_unique_ref;
|
||||
@ -26,28 +27,28 @@ public:
|
||||
|
||||
CryConfigFile Create(const string &password = "mypassword") {
|
||||
EXPECT_FALSE(file.exists());
|
||||
return loader(password).loadOrCreate(file.path()).value();
|
||||
return loader(password).loadOrCreate<SCryptTestSettings>(file.path()).value();
|
||||
}
|
||||
|
||||
optional<CryConfigFile> Load(const string &password = "mypassword") {
|
||||
EXPECT_TRUE(file.exists());
|
||||
return loader(password).loadOrCreate(file.path());
|
||||
return loader(password).loadOrCreate<SCryptTestSettings>(file.path());
|
||||
}
|
||||
|
||||
void CreateWithRootBlob(const string &rootBlob, const string &password = "mypassword") {
|
||||
auto cfg = loader(password).loadOrCreate(file.path()).value();
|
||||
auto cfg = loader(password).loadOrCreate<SCryptTestSettings>(file.path()).value();
|
||||
cfg.config()->SetRootBlob(rootBlob);
|
||||
cfg.save();
|
||||
}
|
||||
|
||||
void CreateWithCipher(const string &cipher, const string &password = "mypassword") {
|
||||
auto cfg = loader(password).loadOrCreate(file.path()).value();
|
||||
auto cfg = loader(password).loadOrCreate<SCryptTestSettings>(file.path()).value();
|
||||
cfg.config()->SetCipher(cipher);
|
||||
cfg.save();
|
||||
}
|
||||
|
||||
void CreateWithEncryptionKey(const string &encKey, const string &password = "mypassword") {
|
||||
auto cfg = loader(password).loadOrCreate(file.path()).value();
|
||||
auto cfg = loader(password).loadOrCreate<SCryptTestSettings>(file.path()).value();
|
||||
cfg.config()->SetEncryptionKey(encKey);
|
||||
cfg.save();
|
||||
}
|
||||
|
@ -1,36 +1,51 @@
|
||||
#include <google/gtest/gtest.h>
|
||||
#include "../../../../src/config/crypto/kdf/Scrypt.h"
|
||||
#include "../../testutils/SCryptTestSettings.h"
|
||||
|
||||
using namespace cryfs;
|
||||
|
||||
TEST(SCryptTest, GeneratedKeyIsReproductible_448) {
|
||||
auto created = SCrypt().generateKey<56>("mypassword");
|
||||
auto created = SCrypt().generateKey<56, SCryptTestSettings>("mypassword");
|
||||
auto recreated = SCrypt().generateKeyFromConfig<56>("mypassword", created.config());
|
||||
EXPECT_EQ(created.key(), recreated);
|
||||
}
|
||||
|
||||
TEST(SCryptTest, GeneratedKeyIsReproductible_256) {
|
||||
auto created = SCrypt().generateKey<32>("mypassword");
|
||||
auto created = SCrypt().generateKey<32, SCryptTestSettings>("mypassword");
|
||||
auto recreated = SCrypt().generateKeyFromConfig<32>("mypassword", created.config());
|
||||
EXPECT_EQ(created.key(), recreated);
|
||||
}
|
||||
|
||||
TEST(SCryptTest, GeneratedKeyIsReproductible_128) {
|
||||
auto created = SCrypt().generateKey<16, SCryptTestSettings>("mypassword");
|
||||
auto recreated = SCrypt().generateKeyFromConfig<16>("mypassword", created.config());
|
||||
EXPECT_EQ(created.key(), recreated);
|
||||
}
|
||||
|
||||
TEST(SCryptTest, GeneratedKeyIsReproductible_DefaultSettings) {
|
||||
auto created = SCrypt().generateKey<16>("mypassword");
|
||||
auto recreated = SCrypt().generateKeyFromConfig<16>("mypassword", created.config());
|
||||
EXPECT_EQ(created.key(), recreated);
|
||||
}
|
||||
|
||||
TEST(SCryptTest, DifferentPasswordResultsInDifferentKey) {
|
||||
auto created = SCrypt().generateKey<16>("mypassword");
|
||||
auto created = SCrypt().generateKey<16, SCryptTestSettings>("mypassword");
|
||||
auto recreated = SCrypt().generateKeyFromConfig<16>("mypassword2", created.config());
|
||||
EXPECT_NE(created.key(), recreated);
|
||||
}
|
||||
|
||||
TEST(SCryptTest, UsesCorrectDefaultParameters) {
|
||||
auto created = SCrypt().generateKey<16>("mypassword");
|
||||
EXPECT_EQ(SCrypt::SALT_LEN, created.config().salt().size());
|
||||
EXPECT_EQ(SCrypt::N, created.config().N());
|
||||
EXPECT_EQ(SCrypt::r, created.config().r());
|
||||
EXPECT_EQ(SCrypt::p, created.config().p());
|
||||
TEST(SCryptTest, UsesCorrectSettings) {
|
||||
auto created = SCrypt().generateKey<16, SCryptTestSettings>("mypassword");
|
||||
EXPECT_EQ(SCryptTestSettings::SALT_LEN, created.config().salt().size());
|
||||
EXPECT_EQ(SCryptTestSettings::N, created.config().N());
|
||||
EXPECT_EQ(SCryptTestSettings::r, created.config().r());
|
||||
EXPECT_EQ(SCryptTestSettings::p, created.config().p());
|
||||
}
|
||||
|
||||
TEST(SCryptTest, UsesCorrectDefaultSettings) {
|
||||
auto created = SCrypt().generateKey<16>("mypassword");
|
||||
EXPECT_EQ(SCryptDefaultSettings::SALT_LEN, created.config().salt().size());
|
||||
EXPECT_EQ(SCryptDefaultSettings::N, created.config().N());
|
||||
EXPECT_EQ(SCryptDefaultSettings::r, created.config().r());
|
||||
EXPECT_EQ(SCryptDefaultSettings::p, created.config().p());
|
||||
}
|
||||
|
6
test/config/testutils/SCryptTestSettings.cpp
Normal file
6
test/config/testutils/SCryptTestSettings.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "SCryptTestSettings.h"
|
||||
|
||||
constexpr size_t SCryptTestSettings::SALT_LEN;
|
||||
constexpr uint64_t SCryptTestSettings::N;
|
||||
constexpr uint32_t SCryptTestSettings::r;
|
||||
constexpr uint32_t SCryptTestSettings::p;
|
14
test/config/testutils/SCryptTestSettings.h
Normal file
14
test/config/testutils/SCryptTestSettings.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef MESSMER_CRYFS_TEST_CONFIG_CRYPTO_TESTUTILS_SCRYPTTESTSETTINGS_H
|
||||
#define MESSMER_CRYFS_TEST_CONFIG_CRYPTO_TESTUTILS_SCRYPTTESTSETTINGS_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
struct SCryptTestSettings {
|
||||
constexpr static size_t SALT_LEN = 32; // Size of the salt
|
||||
constexpr static uint64_t N = 1024; // CPU/Memory cost
|
||||
constexpr static uint32_t r = 1; // Blocksize
|
||||
constexpr static uint32_t p = 1; // Parallelization
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user