Refactor interface for key derivation functions. This allows easily adding new (password based) key derivation functions.
This commit is contained in:
parent
7d9d72d82a
commit
d5a0b725fe
@ -2,9 +2,9 @@ project (cpp-utils)
|
||||
|
||||
set(SOURCES
|
||||
crypto/symmetric/ciphers.cpp
|
||||
crypto/kdf/DerivedKey.cpp
|
||||
crypto/kdf/Scrypt.cpp
|
||||
crypto/kdf/DerivedKeyConfig.cpp
|
||||
crypto/kdf/SCryptParameters.cpp
|
||||
crypto/kdf/PasswordBasedKDF.cpp
|
||||
crypto/RandomPadding.cpp
|
||||
process/daemonize.cpp
|
||||
process/subprocess.cpp
|
||||
|
@ -1 +0,0 @@
|
||||
#include "DerivedKey.h"
|
@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef MESSMER_CPPUTILS_CRYPTO_KDF_DERIVEDKEY_H
|
||||
#define MESSMER_CPPUTILS_CRYPTO_KDF_DERIVEDKEY_H
|
||||
|
||||
#include "../../data/FixedSizeData.h"
|
||||
#include "DerivedKeyConfig.h"
|
||||
|
||||
namespace cpputils {
|
||||
|
||||
template<size_t KEY_LENGTH>
|
||||
class DerivedKey final {
|
||||
public:
|
||||
DerivedKey(DerivedKeyConfig config, const FixedSizeData<KEY_LENGTH> &key): _config(std::move(config)), _key(key) {}
|
||||
DerivedKey(DerivedKey &&rhs) = default;
|
||||
|
||||
const DerivedKeyConfig &config() const {
|
||||
return _config;
|
||||
}
|
||||
|
||||
DerivedKeyConfig moveOutConfig() {
|
||||
return std::move(_config);
|
||||
}
|
||||
|
||||
const FixedSizeData<KEY_LENGTH> &key() const {
|
||||
return _key;
|
||||
}
|
||||
|
||||
FixedSizeData<KEY_LENGTH> moveOutKey() {
|
||||
return std::move(_key);
|
||||
}
|
||||
private:
|
||||
DerivedKeyConfig _config;
|
||||
FixedSizeData<KEY_LENGTH> _key;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DerivedKey);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,27 +0,0 @@
|
||||
#include "DerivedKeyConfig.h"
|
||||
|
||||
using std::istream;
|
||||
using std::ostream;
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
|
||||
namespace cpputils {
|
||||
void DerivedKeyConfig::serialize(Serializer *target) const {
|
||||
target->writeUint64(_N);
|
||||
target->writeUint32(_r);
|
||||
target->writeUint32(_p);
|
||||
target->writeData(_salt);
|
||||
}
|
||||
|
||||
size_t DerivedKeyConfig::serializedSize() const {
|
||||
return Serializer::DataSize(_salt) + sizeof(uint64_t) + sizeof(uint32_t) + sizeof(uint32_t);
|
||||
}
|
||||
|
||||
DerivedKeyConfig DerivedKeyConfig::deserialize(Deserializer *source) {
|
||||
uint64_t N = source->readUint64();
|
||||
uint32_t r = source->readUint32();
|
||||
uint32_t p = source->readUint32();
|
||||
Data salt = source->readData();
|
||||
return DerivedKeyConfig(std::move(salt), N, r, p);
|
||||
}
|
||||
}
|
1
src/cpp-utils/crypto/kdf/PasswordBasedKDF.cpp
Normal file
1
src/cpp-utils/crypto/kdf/PasswordBasedKDF.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "PasswordBasedKDF.h"
|
31
src/cpp-utils/crypto/kdf/PasswordBasedKDF.h
Normal file
31
src/cpp-utils/crypto/kdf/PasswordBasedKDF.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#ifndef MESSMER_CPPUTILS_CRYPTO_KDF_PASSWORDBASEDKDF_H
|
||||
#define MESSMER_CPPUTILS_CRYPTO_KDF_PASSWORDBASEDKDF_H
|
||||
|
||||
#include "../../data/FixedSizeData.h"
|
||||
#include "../../data/Data.h"
|
||||
|
||||
namespace cpputils {
|
||||
|
||||
class PasswordBasedKDF {
|
||||
public:
|
||||
virtual ~PasswordBasedKDF() {}
|
||||
|
||||
template<size_t KEYSIZE> FixedSizeData<KEYSIZE> deriveKey(const std::string &password);
|
||||
virtual const Data &kdfParameters() const = 0;
|
||||
|
||||
protected:
|
||||
virtual void derive(void *destination, size_t size, const std::string &password) = 0;
|
||||
};
|
||||
|
||||
template<size_t KEYSIZE> FixedSizeData<KEYSIZE>
|
||||
inline PasswordBasedKDF::deriveKey(const std::string &password) {
|
||||
auto result = FixedSizeData<KEYSIZE>::Null();
|
||||
derive(result.data(), result.BINARY_LENGTH, password);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
42
src/cpp-utils/crypto/kdf/SCryptParameters.cpp
Normal file
42
src/cpp-utils/crypto/kdf/SCryptParameters.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include "SCryptParameters.h"
|
||||
|
||||
using std::istream;
|
||||
using std::ostream;
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
using cpputils::Data;
|
||||
|
||||
namespace cpputils {
|
||||
Data SCryptParameters::serialize() const {
|
||||
Serializer serializer(_serializedSize());
|
||||
serializer.writeUint64(_N);
|
||||
serializer.writeUint32(_r);
|
||||
serializer.writeUint32(_p);
|
||||
serializer.writeTailData(_salt);
|
||||
return serializer.finished();
|
||||
}
|
||||
|
||||
size_t SCryptParameters::_serializedSize() const {
|
||||
return _salt.size() + sizeof(uint64_t) + sizeof(uint32_t) + sizeof(uint32_t);
|
||||
}
|
||||
|
||||
SCryptParameters SCryptParameters::deserialize(const cpputils::Data &data) {
|
||||
Deserializer deserializer(&data);
|
||||
uint64_t N = deserializer.readUint64();
|
||||
uint32_t r = deserializer.readUint32();
|
||||
uint32_t p = deserializer.readUint32();
|
||||
Data salt = deserializer.readTailData();
|
||||
deserializer.finished();
|
||||
return SCryptParameters(std::move(salt), N, r, p);
|
||||
}
|
||||
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
SCryptParameters SCryptParameters::deserializeOldFormat(Deserializer *source) {
|
||||
uint64_t N = source->readUint64();
|
||||
uint32_t r = source->readUint32();
|
||||
uint32_t p = source->readUint32();
|
||||
Data salt = source->readData();
|
||||
return SCryptParameters(std::move(salt), N, r, p);
|
||||
}
|
||||
#endif
|
||||
}
|
@ -13,19 +13,19 @@ namespace cpputils {
|
||||
//TODO Test operator==/!=
|
||||
//TODO Use SCryptSettings as a member here instead of storing _N, _r, _p.
|
||||
|
||||
class DerivedKeyConfig final {
|
||||
class SCryptParameters final {
|
||||
public:
|
||||
DerivedKeyConfig(Data salt, uint64_t N, uint32_t r, uint32_t p)
|
||||
SCryptParameters(Data salt, uint64_t N, uint32_t r, uint32_t p)
|
||||
: _salt(std::move(salt)),
|
||||
_N(N), _r(r), _p(p) { }
|
||||
|
||||
DerivedKeyConfig(const DerivedKeyConfig &rhs)
|
||||
SCryptParameters(const SCryptParameters &rhs)
|
||||
:_salt(rhs._salt.copy()),
|
||||
_N(rhs._N), _r(rhs._r), _p(rhs._p) { }
|
||||
|
||||
DerivedKeyConfig(DerivedKeyConfig &&rhs) = default;
|
||||
SCryptParameters(SCryptParameters &&rhs) = default;
|
||||
|
||||
DerivedKeyConfig &operator=(const DerivedKeyConfig &rhs) {
|
||||
SCryptParameters &operator=(const SCryptParameters &rhs) {
|
||||
_salt = rhs._salt.copy();
|
||||
_N = rhs._N;
|
||||
_r = rhs._r;
|
||||
@ -33,7 +33,7 @@ namespace cpputils {
|
||||
return *this;
|
||||
}
|
||||
|
||||
DerivedKeyConfig &operator=(DerivedKeyConfig &&rhs) = default;
|
||||
SCryptParameters &operator=(SCryptParameters &&rhs) = default;
|
||||
|
||||
const Data &salt() const {
|
||||
return _salt;
|
||||
@ -51,24 +51,31 @@ namespace cpputils {
|
||||
return _p;
|
||||
}
|
||||
|
||||
void serialize(Serializer *destination) const;
|
||||
cpputils::Data serialize() const;
|
||||
|
||||
size_t serializedSize() const;
|
||||
static SCryptParameters deserialize(const cpputils::Data &data);
|
||||
|
||||
static DerivedKeyConfig deserialize(Deserializer *source);
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
static SCryptParameters deserializeOldFormat(cpputils::Deserializer *deserializer);
|
||||
size_t serializedSize() const {
|
||||
return _serializedSize();
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
size_t _serializedSize() const;
|
||||
|
||||
Data _salt;
|
||||
uint64_t _N;
|
||||
uint32_t _r;
|
||||
uint32_t _p;
|
||||
};
|
||||
|
||||
inline bool operator==(const DerivedKeyConfig &lhs, const DerivedKeyConfig &rhs) {
|
||||
inline bool operator==(const SCryptParameters &lhs, const SCryptParameters &rhs) {
|
||||
return lhs.salt() == rhs.salt() && lhs.N() == rhs.N() && lhs.r() == rhs.r() && lhs.p() == rhs.p();
|
||||
}
|
||||
|
||||
inline bool operator!=(const DerivedKeyConfig &lhs, const DerivedKeyConfig &rhs) {
|
||||
inline bool operator!=(const SCryptParameters &lhs, const SCryptParameters &rhs) {
|
||||
return !operator==(lhs, rhs);
|
||||
}
|
||||
|
@ -1,7 +1,45 @@
|
||||
#include "Scrypt.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace cpputils {
|
||||
|
||||
constexpr SCryptSettings SCrypt::ParanoidSettings;
|
||||
constexpr SCryptSettings SCrypt::DefaultSettings;
|
||||
constexpr SCryptSettings SCrypt::TestSettings;
|
||||
|
||||
unique_ref<SCrypt> SCrypt::forNewKey(const SCryptSettings &settings) {
|
||||
SCryptParameters kdfParameters(Random::PseudoRandom().get(settings.SALT_LEN), settings.N, settings.r, settings.p);
|
||||
return make_unique_ref<SCrypt>(std::move(kdfParameters));
|
||||
}
|
||||
|
||||
unique_ref<SCrypt> SCrypt::forExistingKey(const Data ¶meters) {
|
||||
return make_unique_ref<SCrypt>(SCryptParameters::deserialize(parameters));
|
||||
}
|
||||
|
||||
SCrypt::SCrypt(SCryptParameters config)
|
||||
:_config(std::move(config)), _serializedConfig(_config.serialize()), _wasGeneratedBefore(false) {
|
||||
}
|
||||
|
||||
void SCrypt::derive(void *destination, size_t size, const string &password) {
|
||||
_checkCallOnlyOnce();
|
||||
int errorcode = crypto_scrypt(reinterpret_cast<const uint8_t*>(password.c_str()), password.size(),
|
||||
reinterpret_cast<const uint8_t*>(_config.salt().data()), _config.salt().size(),
|
||||
_config.N(), _config.r(), _config.p(),
|
||||
static_cast<uint8_t*>(destination), size);
|
||||
if (errorcode != 0) {
|
||||
throw std::runtime_error("Error running scrypt key derivation.");
|
||||
}
|
||||
}
|
||||
|
||||
const Data &SCrypt::kdfParameters() const {
|
||||
return _serializedConfig;
|
||||
}
|
||||
|
||||
void SCrypt::_checkCallOnlyOnce() {
|
||||
if (_wasGeneratedBefore) {
|
||||
throw std::runtime_error("An SCrypt instance can only generate exactly one key. Generating multiple keys would be insecure because we would use the same salt.");
|
||||
}
|
||||
_wasGeneratedBefore = true;
|
||||
}
|
||||
}
|
@ -4,11 +4,14 @@
|
||||
|
||||
#include "../../macros.h"
|
||||
#include "../../random/Random.h"
|
||||
#include "../../pointer/unique_ref.h"
|
||||
#include "PasswordBasedKDF.h"
|
||||
|
||||
extern "C" {
|
||||
#include <scrypt/lib/crypto/crypto_scrypt.h>
|
||||
}
|
||||
#include <stdexcept>
|
||||
#include "DerivedKey.h"
|
||||
#include "SCryptParameters.h"
|
||||
|
||||
namespace cpputils {
|
||||
|
||||
@ -19,36 +22,29 @@ namespace cpputils {
|
||||
uint32_t p;
|
||||
};
|
||||
|
||||
class SCrypt final {
|
||||
class SCrypt final : public PasswordBasedKDF {
|
||||
public:
|
||||
static constexpr SCryptSettings ParanoidSettings = SCryptSettings {32, 1048576, 8, 16};
|
||||
static constexpr SCryptSettings DefaultSettings = SCryptSettings {32, 1048576, 4, 1};
|
||||
static constexpr SCryptSettings TestSettings = SCryptSettings {32, 1024, 1, 1};
|
||||
|
||||
SCrypt() {}
|
||||
static unique_ref<SCrypt> forNewKey(const SCryptSettings &settings);
|
||||
static unique_ref<SCrypt> forExistingKey(const Data ¶meters);
|
||||
|
||||
template<size_t KEYSIZE>
|
||||
DerivedKey<KEYSIZE> generateKey(const std::string &password, const SCryptSettings &settings) {
|
||||
auto salt = 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);
|
||||
}
|
||||
const Data &kdfParameters() const override;
|
||||
|
||||
template<size_t KEYSIZE>
|
||||
FixedSizeData<KEYSIZE> generateKeyFromConfig(const std::string &password, const DerivedKeyConfig &config) {
|
||||
auto key = FixedSizeData<KEYSIZE>::Null();
|
||||
int errorcode = crypto_scrypt(reinterpret_cast<const uint8_t*>(password.c_str()), password.size(),
|
||||
reinterpret_cast<const uint8_t*>(config.salt().data()), config.salt().size(),
|
||||
config.N(), config.r(), config.p(),
|
||||
static_cast<uint8_t*>(key.data()), KEYSIZE);
|
||||
if (errorcode != 0) {
|
||||
throw std::runtime_error("Error running scrypt key derivation.");
|
||||
}
|
||||
return key;
|
||||
}
|
||||
SCrypt(SCryptParameters config);
|
||||
|
||||
protected:
|
||||
void derive(void *destination, size_t size, const std::string &password) override;
|
||||
|
||||
private:
|
||||
void _checkCallOnlyOnce();
|
||||
|
||||
SCryptParameters _config;
|
||||
Data _serializedConfig;
|
||||
bool _wasGeneratedBefore;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SCrypt);
|
||||
};
|
||||
}
|
||||
|
@ -44,7 +44,12 @@ optional<CryConfigFile> CryConfigFile::load(const bf::path &path, const string &
|
||||
LOG(ERROR) << "Inner cipher algorithm used to encrypt config file doesn't match config value";
|
||||
return none;
|
||||
}
|
||||
return CryConfigFile(path, std::move(config), std::move(*encryptor));
|
||||
auto configFile = CryConfigFile(path, std::move(config), std::move(*encryptor));
|
||||
if (decrypted->wasInDeprecatedConfigFormat) {
|
||||
// Migrate it to new format
|
||||
configFile.save();
|
||||
}
|
||||
return configFile;
|
||||
}
|
||||
|
||||
CryConfigFile CryConfigFile::create(const bf::path &path, CryConfig config, const string &password, const SCryptSettings &scryptSettings) {
|
||||
|
@ -6,8 +6,6 @@ using cpputils::unique_ref;
|
||||
using cpputils::make_unique_ref;
|
||||
using cpputils::Data;
|
||||
using cpputils::RandomPadding;
|
||||
using cpputils::DerivedKeyConfig;
|
||||
using cpputils::DerivedKey;
|
||||
using cpputils::FixedSizeData;
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
@ -17,8 +15,8 @@ namespace cryfs {
|
||||
constexpr size_t CryConfigEncryptor::OuterKeySize;
|
||||
constexpr size_t CryConfigEncryptor::MaxTotalKeySize;
|
||||
|
||||
CryConfigEncryptor::CryConfigEncryptor(DerivedKey<MaxTotalKeySize> derivedKey)
|
||||
: _derivedKey(std::move(derivedKey)) {
|
||||
CryConfigEncryptor::CryConfigEncryptor(FixedSizeData<MaxTotalKeySize> derivedKey, cpputils::Data kdfParameters)
|
||||
: _derivedKey(std::move(derivedKey)), _kdfParameters(std::move(kdfParameters)) {
|
||||
}
|
||||
|
||||
Data CryConfigEncryptor::encrypt(const Data &plaintext, const string &cipherName) const {
|
||||
@ -29,18 +27,6 @@ namespace cryfs {
|
||||
}
|
||||
|
||||
optional<CryConfigEncryptor::Decrypted> CryConfigEncryptor::decrypt(const Data &data) const {
|
||||
auto innerConfig = _loadInnerConfig(data);
|
||||
if (innerConfig == none) {
|
||||
return none;
|
||||
}
|
||||
auto plaintext = _innerEncryptor(innerConfig->cipherName)->decrypt(*innerConfig);
|
||||
if (plaintext == none) {
|
||||
return none;
|
||||
}
|
||||
return Decrypted{std::move(*plaintext), innerConfig->cipherName};
|
||||
}
|
||||
|
||||
optional<InnerConfig> CryConfigEncryptor::_loadInnerConfig(const Data &data) const {
|
||||
auto outerConfig = OuterConfig::deserialize(data);
|
||||
if (outerConfig == none) {
|
||||
return none;
|
||||
@ -49,16 +35,24 @@ namespace cryfs {
|
||||
if(serializedInnerConfig == none) {
|
||||
return none;
|
||||
}
|
||||
return InnerConfig::deserialize(*serializedInnerConfig);
|
||||
auto innerConfig = InnerConfig::deserialize(*serializedInnerConfig);
|
||||
if (innerConfig == none) {
|
||||
return none;
|
||||
}
|
||||
auto plaintext = _innerEncryptor(innerConfig->cipherName)->decrypt(*innerConfig);
|
||||
if (plaintext == none) {
|
||||
return none;
|
||||
}
|
||||
return Decrypted{std::move(*plaintext), innerConfig->cipherName, outerConfig->wasInDeprecatedConfigFormat};
|
||||
}
|
||||
|
||||
unique_ref<OuterEncryptor> CryConfigEncryptor::_outerEncryptor() const {
|
||||
auto outerKey = _derivedKey.key().take<OuterKeySize>();
|
||||
return make_unique_ref<OuterEncryptor>(outerKey, _derivedKey.config());
|
||||
auto outerKey = _derivedKey.take<OuterKeySize>();
|
||||
return make_unique_ref<OuterEncryptor>(outerKey, _kdfParameters.copy());
|
||||
}
|
||||
|
||||
unique_ref<InnerEncryptor> CryConfigEncryptor::_innerEncryptor(const string &cipherName) const {
|
||||
auto innerKey = _derivedKey.key().drop<OuterKeySize>();
|
||||
auto innerKey = _derivedKey.drop<OuterKeySize>();
|
||||
return CryCiphers::find(cipherName).createInnerConfigEncryptor(innerKey);
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,6 @@
|
||||
#include <cpp-utils/pointer/unique_ref.h>
|
||||
#include <cpp-utils/data/Deserializer.h>
|
||||
#include <cpp-utils/data/Serializer.h>
|
||||
#include <cpp-utils/crypto/kdf/DerivedKeyConfig.h>
|
||||
#include <cpp-utils/crypto/kdf/DerivedKey.h>
|
||||
#include <cpp-utils/crypto/symmetric/ciphers.h>
|
||||
#include "inner/InnerEncryptor.h"
|
||||
#include "outer/OuterEncryptor.h"
|
||||
@ -22,19 +20,20 @@ namespace cryfs {
|
||||
struct Decrypted {
|
||||
cpputils::Data data;
|
||||
std::string cipherName;
|
||||
bool wasInDeprecatedConfigFormat;
|
||||
};
|
||||
|
||||
CryConfigEncryptor(cpputils::DerivedKey<MaxTotalKeySize> derivedKey);
|
||||
CryConfigEncryptor(cpputils::FixedSizeData<MaxTotalKeySize> derivedKey, cpputils::Data _kdfParameters);
|
||||
|
||||
cpputils::Data encrypt(const cpputils::Data &plaintext, const std::string &cipherName) const;
|
||||
boost::optional<Decrypted> decrypt(const cpputils::Data &data) const;
|
||||
|
||||
private:
|
||||
boost::optional<InnerConfig> _loadInnerConfig(const cpputils::Data &data) const;
|
||||
cpputils::unique_ref<OuterEncryptor> _outerEncryptor() const;
|
||||
cpputils::unique_ref<InnerEncryptor> _innerEncryptor(const std::string &cipherName) const;
|
||||
|
||||
cpputils::DerivedKey<MaxTotalKeySize> _derivedKey;
|
||||
cpputils::FixedSizeData<MaxTotalKeySize> _derivedKey;
|
||||
cpputils::Data _kdfParameters;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CryConfigEncryptor);
|
||||
};
|
||||
|
@ -8,8 +8,8 @@ using boost::none;
|
||||
using cpputils::unique_ref;
|
||||
using cpputils::make_unique_ref;
|
||||
using cpputils::Data;
|
||||
using cpputils::DerivedKey;
|
||||
using cpputils::DerivedKeyConfig;
|
||||
using cpputils::FixedSizeData;
|
||||
using cpputils::SCryptParameters;
|
||||
using cpputils::SCrypt;
|
||||
using cpputils::SCryptSettings;
|
||||
using std::string;
|
||||
@ -22,21 +22,20 @@ namespace cryfs {
|
||||
if (outerConfig == none) {
|
||||
return none;
|
||||
}
|
||||
auto derivedKey = _deriveKey(outerConfig->keyConfig, password);
|
||||
return make_unique_ref<CryConfigEncryptor>(std::move(derivedKey));
|
||||
}
|
||||
|
||||
DerivedKey<CryConfigEncryptor::MaxTotalKeySize>
|
||||
CryConfigEncryptorFactory::_deriveKey(const DerivedKeyConfig &keyConfig, const std::string &password) {
|
||||
//TODO It would be better, not to generate a MaxTotalKeySize key here, but to generate the outer key first, and then
|
||||
// (once we know which inner cipher was used) only generate as many key bytes as we need for the inner cipher.
|
||||
// This would need a change in the scrypt interface though, because right now we can't continue past key computations.
|
||||
auto key = SCrypt().generateKeyFromConfig<CryConfigEncryptor::MaxTotalKeySize>(password, keyConfig);
|
||||
return DerivedKey<CryConfigEncryptor::MaxTotalKeySize>(keyConfig, std::move(key));
|
||||
return _deriveKey(SCrypt::forExistingKey(outerConfig->kdfParameters), password);
|
||||
}
|
||||
|
||||
unique_ref<CryConfigEncryptor> CryConfigEncryptorFactory::deriveKey(const string &password, const SCryptSettings &scryptSettings) {
|
||||
auto derivedKey = cpputils::SCrypt().generateKey<CryConfigEncryptor::MaxTotalKeySize>(password, scryptSettings);
|
||||
return make_unique_ref<CryConfigEncryptor>(std::move(derivedKey));
|
||||
return _deriveKey(SCrypt::forNewKey(scryptSettings), password);
|
||||
}
|
||||
|
||||
unique_ref<CryConfigEncryptor>
|
||||
CryConfigEncryptorFactory::_deriveKey(cpputils::unique_ref<SCrypt> kdf, const string &password) {
|
||||
//TODO It would be better, not to generate a MaxTotalKeySize key here, but to generate the outer key first, and then
|
||||
// (once we know which inner cipher was used) only generate as many key bytes as we need for the inner cipher.
|
||||
// This would need a change in the scrypt interface though, because right now we can't continue past key computations.
|
||||
//TODO I might be able to know the actual key size here (at runtime) and switch the SCrypt deriveKey() interface to getting a dynamic size.
|
||||
auto key = kdf->deriveKey<CryConfigEncryptor::MaxTotalKeySize>(password);
|
||||
return make_unique_ref<CryConfigEncryptor>(std::move(key), kdf->kdfParameters().copy());
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,7 @@ namespace cryfs {
|
||||
|
||||
private:
|
||||
|
||||
static cpputils::DerivedKey<CryConfigEncryptor::MaxTotalKeySize> _deriveKey(const cpputils::DerivedKeyConfig &keyConfig, const std::string &password);
|
||||
static boost::optional<std::string> _loadCipherName(const OuterEncryptor &outerEncryptor, const OuterConfig &outerConfig);
|
||||
static cpputils::unique_ref<CryConfigEncryptor> _deriveKey(cpputils::unique_ref<cpputils::SCrypt> kdf, const std::string &password);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
#define MESSMER_CRYFS_SRC_CONFIG_CRYPTO_INNER_CONCRETECRYCONFIGENCRYPTOR_H
|
||||
|
||||
#include <cpp-utils/crypto/RandomPadding.h>
|
||||
#include <cpp-utils/crypto/kdf/DerivedKey.h>
|
||||
|
||||
#include "InnerEncryptor.h"
|
||||
#include "InnerConfig.h"
|
||||
|
@ -1,17 +1,21 @@
|
||||
#include "OuterConfig.h"
|
||||
#include <cpp-utils/crypto/kdf/SCryptParameters.h>
|
||||
|
||||
using std::string;
|
||||
using std::exception;
|
||||
using cpputils::Data;
|
||||
using cpputils::Serializer;
|
||||
using cpputils::Deserializer;
|
||||
using cpputils::DerivedKeyConfig;
|
||||
using cpputils::SCryptParameters;
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
using namespace cpputils::logging;
|
||||
|
||||
namespace cryfs {
|
||||
const string OuterConfig::HEADER = "cryfs.config;0;scrypt";
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
const string OuterConfig::OLD_HEADER = "cryfs.config;0;scrypt";
|
||||
#endif
|
||||
const string OuterConfig::HEADER = "cryfs.config;1;scrypt";
|
||||
|
||||
void OuterConfig::_checkHeader(Deserializer *deserializer) {
|
||||
string header = deserializer->readString();
|
||||
@ -27,10 +31,10 @@ namespace cryfs {
|
||||
Data OuterConfig::serialize() const {
|
||||
try {
|
||||
Serializer serializer(Serializer::StringSize(HEADER)
|
||||
+ keyConfig.serializedSize()
|
||||
+ Serializer::DataSize(kdfParameters)
|
||||
+ encryptedInnerConfig.size());
|
||||
_writeHeader(&serializer);
|
||||
keyConfig.serialize(&serializer);
|
||||
serializer.writeData(kdfParameters);
|
||||
serializer.writeTailData(encryptedInnerConfig);
|
||||
return serializer.finished();
|
||||
} catch (const exception &e) {
|
||||
@ -42,14 +46,37 @@ namespace cryfs {
|
||||
optional<OuterConfig> OuterConfig::deserialize(const Data &data) {
|
||||
Deserializer deserializer(&data);
|
||||
try {
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
string header = deserializer.readString();
|
||||
if (header == OLD_HEADER) {
|
||||
return _deserializeOldFormat(&deserializer);
|
||||
} else if (header == HEADER) {
|
||||
return _deserializeNewFormat(&deserializer);
|
||||
} else {
|
||||
throw std::runtime_error("Invalid header");
|
||||
}
|
||||
#else
|
||||
_checkHeader(&deserializer);
|
||||
auto keyConfig = DerivedKeyConfig::deserialize(&deserializer);
|
||||
auto encryptedInnerConfig = deserializer.readTailData();
|
||||
deserializer.finished();
|
||||
return OuterConfig {std::move(keyConfig), std::move(encryptedInnerConfig)};
|
||||
_deserializeNewFormat(&deserializer);
|
||||
#endif
|
||||
} catch (const exception &e) {
|
||||
LOG(ERROR) << "Error deserializing outer configuration: " << e.what();
|
||||
return none; // This can be caused by invalid input data and does not have to be a programming error. Don't throw exception.
|
||||
}
|
||||
}
|
||||
|
||||
OuterConfig OuterConfig::_deserializeOldFormat(Deserializer *deserializer) {
|
||||
auto kdfParameters = SCryptParameters::deserializeOldFormat(deserializer);
|
||||
auto kdfParametersSerialized = kdfParameters.serialize();
|
||||
auto encryptedInnerConfig = deserializer->readTailData();
|
||||
deserializer->finished();
|
||||
return OuterConfig {std::move(kdfParametersSerialized), std::move(encryptedInnerConfig), true};
|
||||
}
|
||||
|
||||
OuterConfig OuterConfig::_deserializeNewFormat(Deserializer *deserializer) {
|
||||
auto kdfParameters = deserializer->readData();
|
||||
auto encryptedInnerConfig = deserializer->readTailData();
|
||||
deserializer->finished();
|
||||
return OuterConfig {std::move(kdfParameters), std::move(encryptedInnerConfig), false};
|
||||
}
|
||||
}
|
||||
|
@ -2,15 +2,15 @@
|
||||
#ifndef MESSMER_CRYFS_SRC_CONFIG_CRYPTO_OUTER_OUTERCONFIG_H
|
||||
#define MESSMER_CRYFS_SRC_CONFIG_CRYPTO_OUTER_OUTERCONFIG_H
|
||||
|
||||
#include <cpp-utils/crypto/kdf/DerivedKeyConfig.h>
|
||||
#include <cpp-utils/data/Data.h>
|
||||
#include <cpp-utils/data/Serializer.h>
|
||||
#include <cpp-utils/data/Deserializer.h>
|
||||
|
||||
namespace cryfs {
|
||||
struct OuterConfig final {
|
||||
cpputils::DerivedKeyConfig keyConfig;
|
||||
cpputils::Data kdfParameters;
|
||||
cpputils::Data encryptedInnerConfig;
|
||||
bool wasInDeprecatedConfigFormat;
|
||||
|
||||
cpputils::Data serialize() const;
|
||||
static boost::optional<OuterConfig> deserialize(const cpputils::Data &data);
|
||||
@ -18,8 +18,13 @@ namespace cryfs {
|
||||
private:
|
||||
static void _checkHeader(cpputils::Deserializer *deserializer);
|
||||
static void _writeHeader(cpputils::Serializer *serializer);
|
||||
static OuterConfig _deserializeNewFormat(cpputils::Deserializer *deserializer);
|
||||
|
||||
static const std::string HEADER;
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
static const std::string OLD_HEADER;
|
||||
static OuterConfig _deserializeOldFormat(cpputils::Deserializer *deserializer);
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -6,24 +6,23 @@ using std::string;
|
||||
using cpputils::unique_ref;
|
||||
using cpputils::Data;
|
||||
using cpputils::RandomPadding;
|
||||
using cpputils::DerivedKeyConfig;
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
using namespace cpputils::logging;
|
||||
|
||||
namespace cryfs {
|
||||
OuterEncryptor::OuterEncryptor(Cipher::EncryptionKey key, const cpputils::DerivedKeyConfig &keyConfig)
|
||||
: _key(std::move(key)), _keyConfig(std::move(keyConfig)) {
|
||||
OuterEncryptor::OuterEncryptor(Cipher::EncryptionKey key, cpputils::Data kdfParameters)
|
||||
: _key(std::move(key)), _kdfParameters(std::move(kdfParameters)) {
|
||||
}
|
||||
|
||||
OuterConfig OuterEncryptor::encrypt(const Data &plaintext) const {
|
||||
auto padded = RandomPadding::add(plaintext, CONFIG_SIZE);
|
||||
auto ciphertext = Cipher::encrypt(static_cast<const uint8_t*>(padded.data()), padded.size(), _key);
|
||||
return OuterConfig{_keyConfig, std::move(ciphertext)};
|
||||
return OuterConfig{_kdfParameters.copy(), std::move(ciphertext), false};
|
||||
}
|
||||
|
||||
optional<Data> OuterEncryptor::decrypt(const OuterConfig &outerConfig) const {
|
||||
ASSERT(outerConfig.keyConfig == _keyConfig, "OuterEncryptor was initialized with wrong key config");
|
||||
ASSERT(outerConfig.kdfParameters == _kdfParameters, "OuterEncryptor was initialized with wrong key config");
|
||||
auto inner = Cipher::decrypt(static_cast<const uint8_t*>(outerConfig.encryptedInnerConfig.data()), outerConfig.encryptedInnerConfig.size(), _key);
|
||||
if(inner == none) {
|
||||
return none;
|
||||
|
@ -14,7 +14,7 @@ namespace cryfs {
|
||||
using Cipher = cpputils::AES256_GCM;
|
||||
static constexpr size_t CONFIG_SIZE = 1024; // Config data is grown to this size before encryption to hide its actual size
|
||||
|
||||
OuterEncryptor(Cipher::EncryptionKey key, const cpputils::DerivedKeyConfig &keyConfig);
|
||||
OuterEncryptor(Cipher::EncryptionKey key, cpputils::Data kdfParameters);
|
||||
|
||||
OuterConfig encrypt(const cpputils::Data &encryptedInnerConfig) const;
|
||||
boost::optional<cpputils::Data> decrypt(const OuterConfig &outerConfig) const;
|
||||
@ -22,7 +22,7 @@ namespace cryfs {
|
||||
private:
|
||||
|
||||
Cipher::EncryptionKey _key;
|
||||
cpputils::DerivedKeyConfig _keyConfig;
|
||||
cpputils::Data _kdfParameters;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(OuterEncryptor);
|
||||
};
|
||||
|
@ -5,8 +5,7 @@ set(SOURCES
|
||||
crypto/symmetric/CipherTest.cpp
|
||||
crypto/symmetric/testutils/FakeAuthenticatedCipher.cpp
|
||||
crypto/kdf/SCryptTest.cpp
|
||||
crypto/kdf/DerivedKeyTest.cpp
|
||||
crypto/kdf/DerivedKeyConfigTest.cpp
|
||||
crypto/kdf/SCryptParametersTest.cpp
|
||||
MacrosIncludeTest.cpp
|
||||
pointer/unique_ref_test.cpp
|
||||
pointer/cast_include_test.cpp
|
||||
|
@ -1,86 +0,0 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "cpp-utils/crypto/kdf/DerivedKeyConfig.h"
|
||||
#include "cpp-utils/data/DataFixture.h"
|
||||
#include <sstream>
|
||||
|
||||
using namespace cpputils;
|
||||
|
||||
class DerivedKeyConfigTest : public ::testing::Test {
|
||||
public:
|
||||
DerivedKeyConfig SaveAndLoad(const DerivedKeyConfig &source) {
|
||||
Serializer serializer(source.serializedSize());
|
||||
source.serialize(&serializer);
|
||||
Data serialized = serializer.finished();
|
||||
Deserializer deserializer(&serialized);
|
||||
return DerivedKeyConfig::deserialize(&deserializer);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(DerivedKeyConfigTest, Salt) {
|
||||
DerivedKeyConfig cfg(DataFixture::generate(32), 0, 0, 0);
|
||||
EXPECT_EQ(DataFixture::generate(32), cfg.salt());
|
||||
}
|
||||
|
||||
TEST_F(DerivedKeyConfigTest, Salt_Move) {
|
||||
DerivedKeyConfig cfg(DataFixture::generate(32), 0, 0, 0);
|
||||
DerivedKeyConfig moved = std::move(cfg);
|
||||
EXPECT_EQ(DataFixture::generate(32), moved.salt());
|
||||
}
|
||||
|
||||
TEST_F(DerivedKeyConfigTest, Salt_SaveAndLoad) {
|
||||
DerivedKeyConfig cfg(DataFixture::generate(32), 0, 0, 0);
|
||||
DerivedKeyConfig loaded = SaveAndLoad(cfg);
|
||||
EXPECT_EQ(DataFixture::generate(32), loaded.salt());
|
||||
}
|
||||
|
||||
TEST_F(DerivedKeyConfigTest, N) {
|
||||
DerivedKeyConfig cfg(Data(0), 1024, 0, 0);
|
||||
EXPECT_EQ(1024u, cfg.N());
|
||||
}
|
||||
|
||||
TEST_F(DerivedKeyConfigTest, N_Move) {
|
||||
DerivedKeyConfig cfg(Data(0), 1024, 0, 0);
|
||||
DerivedKeyConfig moved = std::move(cfg);
|
||||
EXPECT_EQ(1024u, moved.N());
|
||||
}
|
||||
|
||||
TEST_F(DerivedKeyConfigTest, N_SaveAndLoad) {
|
||||
DerivedKeyConfig cfg(Data(0), 1024, 0, 0);
|
||||
DerivedKeyConfig loaded = SaveAndLoad(cfg);
|
||||
EXPECT_EQ(1024u, loaded.N());
|
||||
}
|
||||
|
||||
TEST_F(DerivedKeyConfigTest, r) {
|
||||
DerivedKeyConfig cfg(Data(0), 0, 8, 0);
|
||||
EXPECT_EQ(8u, cfg.r());
|
||||
}
|
||||
|
||||
TEST_F(DerivedKeyConfigTest, r_Move) {
|
||||
DerivedKeyConfig cfg(Data(0), 0, 8, 0);
|
||||
DerivedKeyConfig moved = std::move(cfg);
|
||||
EXPECT_EQ(8u, moved.r());
|
||||
}
|
||||
|
||||
TEST_F(DerivedKeyConfigTest, r_SaveAndLoad) {
|
||||
DerivedKeyConfig cfg(Data(0), 0, 8, 0);
|
||||
DerivedKeyConfig loaded = SaveAndLoad(cfg);
|
||||
EXPECT_EQ(8u, loaded.r());
|
||||
}
|
||||
|
||||
TEST_F(DerivedKeyConfigTest, p) {
|
||||
DerivedKeyConfig cfg(Data(0), 0, 0, 16);
|
||||
EXPECT_EQ(16u, cfg.p());
|
||||
}
|
||||
|
||||
TEST_F(DerivedKeyConfigTest, p_Move) {
|
||||
DerivedKeyConfig cfg(Data(0), 0, 0, 16);
|
||||
DerivedKeyConfig moved = std::move(cfg);
|
||||
EXPECT_EQ(16u, moved.p());
|
||||
}
|
||||
|
||||
|
||||
TEST_F(DerivedKeyConfigTest, p_SaveAndLoad) {
|
||||
DerivedKeyConfig cfg(Data(0), 0, 0, 16);
|
||||
DerivedKeyConfig loaded = SaveAndLoad(cfg);
|
||||
EXPECT_EQ(16u, loaded.p());
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "cpp-utils/crypto/kdf/DerivedKey.h"
|
||||
#include "cpp-utils/data/DataFixture.h"
|
||||
|
||||
using namespace cpputils;
|
||||
|
||||
TEST(DerivedKeyTest, Config) {
|
||||
DerivedKey<32> key(DerivedKeyConfig(DataFixture::generate(32, 1), 1024, 8, 16), DataFixture::generateFixedSize<32>(2));
|
||||
EXPECT_EQ(DataFixture::generate(32, 1), key.config().salt());
|
||||
EXPECT_EQ(1024u, key.config().N());
|
||||
EXPECT_EQ(8u, key.config().r());
|
||||
EXPECT_EQ(16u, key.config().p());
|
||||
}
|
||||
|
||||
TEST(DerivedKeyTest, Key) {
|
||||
DerivedKey<32> key(DerivedKeyConfig(DataFixture::generate(32, 1), 1024, 8, 16), DataFixture::generateFixedSize<32>(2));
|
||||
EXPECT_EQ(DataFixture::generateFixedSize<32>(2), key.key());
|
||||
}
|
83
test/cpp-utils/crypto/kdf/SCryptParametersTest.cpp
Normal file
83
test/cpp-utils/crypto/kdf/SCryptParametersTest.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <cpp-utils/crypto/kdf/SCryptParameters.h>
|
||||
#include <cpp-utils/data/DataFixture.h>
|
||||
#include <sstream>
|
||||
|
||||
using namespace cpputils;
|
||||
|
||||
class SCryptParametersTest : public ::testing::Test {
|
||||
public:
|
||||
SCryptParameters SaveAndLoad(const SCryptParameters &source) {
|
||||
Data serialized = source.serialize();
|
||||
return SCryptParameters::deserialize(serialized);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(SCryptParametersTest, Salt) {
|
||||
SCryptParameters cfg(DataFixture::generate(32), 0, 0, 0);
|
||||
EXPECT_EQ(DataFixture::generate(32), cfg.salt());
|
||||
}
|
||||
|
||||
TEST_F(SCryptParametersTest, Salt_Move) {
|
||||
SCryptParameters cfg(DataFixture::generate(32), 0, 0, 0);
|
||||
SCryptParameters moved = std::move(cfg);
|
||||
EXPECT_EQ(DataFixture::generate(32), moved.salt());
|
||||
}
|
||||
|
||||
TEST_F(SCryptParametersTest, Salt_SaveAndLoad) {
|
||||
SCryptParameters cfg(DataFixture::generate(32), 0, 0, 0);
|
||||
SCryptParameters loaded = SaveAndLoad(cfg);
|
||||
EXPECT_EQ(DataFixture::generate(32), loaded.salt());
|
||||
}
|
||||
|
||||
TEST_F(SCryptParametersTest, N) {
|
||||
SCryptParameters cfg(Data(0), 1024, 0, 0);
|
||||
EXPECT_EQ(1024u, cfg.N());
|
||||
}
|
||||
|
||||
TEST_F(SCryptParametersTest, N_Move) {
|
||||
SCryptParameters cfg(Data(0), 1024, 0, 0);
|
||||
SCryptParameters moved = std::move(cfg);
|
||||
EXPECT_EQ(1024u, moved.N());
|
||||
}
|
||||
|
||||
TEST_F(SCryptParametersTest, N_SaveAndLoad) {
|
||||
SCryptParameters cfg(Data(0), 1024, 0, 0);
|
||||
SCryptParameters loaded = SaveAndLoad(cfg);
|
||||
EXPECT_EQ(1024u, loaded.N());
|
||||
}
|
||||
|
||||
TEST_F(SCryptParametersTest, r) {
|
||||
SCryptParameters cfg(Data(0), 0, 8, 0);
|
||||
EXPECT_EQ(8u, cfg.r());
|
||||
}
|
||||
|
||||
TEST_F(SCryptParametersTest, r_Move) {
|
||||
SCryptParameters cfg(Data(0), 0, 8, 0);
|
||||
SCryptParameters moved = std::move(cfg);
|
||||
EXPECT_EQ(8u, moved.r());
|
||||
}
|
||||
|
||||
TEST_F(SCryptParametersTest, r_SaveAndLoad) {
|
||||
SCryptParameters cfg(Data(0), 0, 8, 0);
|
||||
SCryptParameters loaded = SaveAndLoad(cfg);
|
||||
EXPECT_EQ(8u, loaded.r());
|
||||
}
|
||||
|
||||
TEST_F(SCryptParametersTest, p) {
|
||||
SCryptParameters cfg(Data(0), 0, 0, 16);
|
||||
EXPECT_EQ(16u, cfg.p());
|
||||
}
|
||||
|
||||
TEST_F(SCryptParametersTest, p_Move) {
|
||||
SCryptParameters cfg(Data(0), 0, 0, 16);
|
||||
SCryptParameters moved = std::move(cfg);
|
||||
EXPECT_EQ(16u, moved.p());
|
||||
}
|
||||
|
||||
|
||||
TEST_F(SCryptParametersTest, p_SaveAndLoad) {
|
||||
SCryptParameters cfg(Data(0), 0, 0, 16);
|
||||
SCryptParameters loaded = SaveAndLoad(cfg);
|
||||
EXPECT_EQ(16u, loaded.p());
|
||||
}
|
@ -2,49 +2,65 @@
|
||||
#include "cpp-utils/crypto/kdf/Scrypt.h"
|
||||
|
||||
using namespace cpputils;
|
||||
using std::string;
|
||||
|
||||
TEST(SCryptTest, GeneratedKeyIsReproductible_448) {
|
||||
auto created = SCrypt().generateKey<56>("mypassword", SCrypt::TestSettings);
|
||||
auto recreated = SCrypt().generateKeyFromConfig<56>("mypassword", created.config());
|
||||
EXPECT_EQ(created.key(), recreated);
|
||||
class SCryptTest : public ::testing::Test {
|
||||
public:
|
||||
unique_ref<SCrypt> scryptForNewKey = SCrypt::forNewKey(SCrypt::TestSettings);
|
||||
unique_ref<SCrypt> scryptForExistingKey = SCrypt::forExistingKey(scryptForNewKey->kdfParameters());
|
||||
|
||||
SCryptParameters kdfParameters(const SCrypt &scrypt) {
|
||||
SCryptParameters result = SCryptParameters::deserialize(scrypt.kdfParameters());
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(SCryptTest, GeneratedKeyIsReproductible_448) {
|
||||
auto derivedKey = scryptForNewKey->deriveKey<56>("mypassword");
|
||||
auto rederivedKey = scryptForExistingKey->deriveKey<56>("mypassword");
|
||||
EXPECT_EQ(derivedKey, rederivedKey);
|
||||
}
|
||||
|
||||
TEST(SCryptTest, GeneratedKeyIsReproductible_256) {
|
||||
auto created = SCrypt().generateKey<32>("mypassword", SCrypt::TestSettings);
|
||||
auto recreated = SCrypt().generateKeyFromConfig<32>("mypassword", created.config());
|
||||
EXPECT_EQ(created.key(), recreated);
|
||||
TEST_F(SCryptTest, GeneratedKeyIsReproductible_256) {
|
||||
auto derivedKey = scryptForNewKey->deriveKey<32>("mypassword");
|
||||
auto rederivedKey = scryptForExistingKey->deriveKey<32>("mypassword");
|
||||
EXPECT_EQ(derivedKey, rederivedKey);
|
||||
}
|
||||
|
||||
TEST(SCryptTest, GeneratedKeyIsReproductible_128) {
|
||||
auto created = SCrypt().generateKey<16>("mypassword", SCrypt::TestSettings);
|
||||
auto recreated = SCrypt().generateKeyFromConfig<16>("mypassword", created.config());
|
||||
EXPECT_EQ(created.key(), recreated);
|
||||
TEST_F(SCryptTest, GeneratedKeyIsReproductible_128) {
|
||||
auto derivedKey = scryptForNewKey->deriveKey<16>("mypassword");
|
||||
auto rederivedKey = scryptForExistingKey->deriveKey<16>("mypassword");
|
||||
EXPECT_EQ(derivedKey, rederivedKey);
|
||||
}
|
||||
|
||||
TEST(SCryptTest, GeneratedKeyIsReproductible_DefaultSettings) {
|
||||
auto created = SCrypt().generateKey<16>("mypassword", SCrypt::DefaultSettings);
|
||||
auto recreated = SCrypt().generateKeyFromConfig<16>("mypassword", created.config());
|
||||
EXPECT_EQ(created.key(), recreated);
|
||||
TEST_F(SCryptTest, GeneratedKeyIsReproductible_DefaultSettings) {
|
||||
auto derivedKey = scryptForNewKey->deriveKey<16>("mypassword");
|
||||
auto rederivedKey = scryptForExistingKey->deriveKey<16>("mypassword");
|
||||
EXPECT_EQ(derivedKey, rederivedKey);
|
||||
}
|
||||
|
||||
TEST(SCryptTest, DifferentPasswordResultsInDifferentKey) {
|
||||
auto created = SCrypt().generateKey<16>("mypassword", SCrypt::TestSettings);
|
||||
auto recreated = SCrypt().generateKeyFromConfig<16>("mypassword2", created.config());
|
||||
EXPECT_NE(created.key(), recreated);
|
||||
TEST_F(SCryptTest, DifferentPasswordResultsInDifferentKey) {
|
||||
auto derivedKey = scryptForNewKey->deriveKey<16>("mypassword");
|
||||
auto rederivedKey = scryptForExistingKey->deriveKey<16>("mypassword2");
|
||||
EXPECT_NE(derivedKey, rederivedKey);
|
||||
}
|
||||
|
||||
TEST(SCryptTest, UsesCorrectSettings) {
|
||||
auto created = SCrypt().generateKey<16>("mypassword", SCrypt::TestSettings);
|
||||
EXPECT_EQ(SCrypt::TestSettings.SALT_LEN, created.config().salt().size());
|
||||
EXPECT_EQ(SCrypt::TestSettings.N, created.config().N());
|
||||
EXPECT_EQ(SCrypt::TestSettings.r, created.config().r());
|
||||
EXPECT_EQ(SCrypt::TestSettings.p, created.config().p());
|
||||
TEST_F(SCryptTest, UsesCorrectSettings) {
|
||||
auto scrypt = SCrypt::forNewKey(SCrypt::TestSettings);
|
||||
auto derivedKey = scrypt->deriveKey<16>("mypassword");
|
||||
SCryptParameters parameters = kdfParameters(*scrypt);
|
||||
EXPECT_EQ(SCrypt::TestSettings.SALT_LEN, parameters.salt().size());
|
||||
EXPECT_EQ(SCrypt::TestSettings.N, parameters.N());
|
||||
EXPECT_EQ(SCrypt::TestSettings.r, parameters.r());
|
||||
EXPECT_EQ(SCrypt::TestSettings.p, parameters.p());
|
||||
}
|
||||
|
||||
TEST(SCryptTest, UsesCorrectDefaultSettings) {
|
||||
auto created = SCrypt().generateKey<16>("mypassword", SCrypt::DefaultSettings);
|
||||
EXPECT_EQ(SCrypt::DefaultSettings.SALT_LEN, created.config().salt().size());
|
||||
EXPECT_EQ(SCrypt::DefaultSettings.N, created.config().N());
|
||||
EXPECT_EQ(SCrypt::DefaultSettings.r, created.config().r());
|
||||
EXPECT_EQ(SCrypt::DefaultSettings.p, created.config().p());
|
||||
TEST_F(SCryptTest, UsesCorrectDefaultSettings) {
|
||||
auto scrypt = SCrypt::forNewKey(SCrypt::DefaultSettings);
|
||||
auto derivedKey = scrypt->deriveKey<16>("mypassword");
|
||||
SCryptParameters parameters = kdfParameters(*scrypt);
|
||||
EXPECT_EQ(SCrypt::DefaultSettings.SALT_LEN, parameters.salt().size());
|
||||
EXPECT_EQ(SCrypt::DefaultSettings.N, parameters.N());
|
||||
EXPECT_EQ(SCrypt::DefaultSettings.r, parameters.r());
|
||||
EXPECT_EQ(SCrypt::DefaultSettings.p, parameters.p());
|
||||
}
|
||||
|
@ -8,8 +8,7 @@ using cpputils::unique_ref;
|
||||
using cpputils::make_unique_ref;
|
||||
using cpputils::DataFixture;
|
||||
using cpputils::Data;
|
||||
using cpputils::DerivedKeyConfig;
|
||||
using cpputils::DerivedKey;
|
||||
using cpputils::FixedSizeData;
|
||||
using cpputils::AES128_CFB;
|
||||
using cpputils::AES256_GCM;
|
||||
using cpputils::Twofish256_GCM;
|
||||
@ -29,7 +28,7 @@ class CryConfigEncryptorTest: public ::testing::Test {
|
||||
public:
|
||||
|
||||
unique_ref<CryConfigEncryptor> makeEncryptor() {
|
||||
return make_unique_ref<CryConfigEncryptor>(_derivedKey());
|
||||
return make_unique_ref<CryConfigEncryptor>(_derivedKey(), _kdfParameters());
|
||||
}
|
||||
|
||||
Data changeInnerCipherFieldTo(Data data, const string &newCipherName) {
|
||||
@ -39,16 +38,17 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
DerivedKey<CryConfigEncryptor::MaxTotalKeySize> _derivedKey() {
|
||||
auto salt = DataFixture::generate(128, 2);
|
||||
auto keyConfig = DerivedKeyConfig(std::move(salt), 1024, 1, 2);
|
||||
auto key = DataFixture::generateFixedSize<CryConfigEncryptor::MaxTotalKeySize>(3);
|
||||
return DerivedKey<CryConfigEncryptor::MaxTotalKeySize>(std::move(keyConfig), std::move(key));
|
||||
FixedSizeData<CryConfigEncryptor::MaxTotalKeySize> _derivedKey() {
|
||||
return DataFixture::generateFixedSize<CryConfigEncryptor::MaxTotalKeySize>(3);
|
||||
}
|
||||
|
||||
Data _kdfParameters() {
|
||||
return DataFixture::generate(128, 2);
|
||||
}
|
||||
|
||||
unique_ref<OuterEncryptor> _outerEncryptor() {
|
||||
auto outerKey = _derivedKey().key().take<CryConfigEncryptor::OuterKeySize>();
|
||||
return make_unique_ref<OuterEncryptor>(outerKey, _derivedKey().config());
|
||||
auto outerKey = _derivedKey().take<CryConfigEncryptor::OuterKeySize>();
|
||||
return make_unique_ref<OuterEncryptor>(outerKey, _kdfParameters());
|
||||
}
|
||||
|
||||
InnerConfig _decryptInnerConfig(const Data &data) {
|
||||
|
@ -4,7 +4,8 @@
|
||||
|
||||
using cpputils::Data;
|
||||
using cpputils::DataFixture;
|
||||
using cpputils::DerivedKeyConfig;
|
||||
using cpputils::Deserializer;
|
||||
using cpputils::Serializer;
|
||||
using boost::none;
|
||||
using std::ostream;
|
||||
using namespace cryfs;
|
||||
@ -19,39 +20,36 @@ namespace boost {
|
||||
|
||||
class OuterConfigTest: public ::testing::Test {
|
||||
public:
|
||||
Data salt() {
|
||||
Data kdfParameters() {
|
||||
return DataFixture::generate(128, 2);
|
||||
}
|
||||
uint64_t N = 1024;
|
||||
uint8_t r = 1;
|
||||
uint8_t p = 2;
|
||||
};
|
||||
|
||||
TEST_F(OuterConfigTest, SomeValues) {
|
||||
Data serialized = OuterConfig{DerivedKeyConfig(salt(), N, r, p), DataFixture::generate(1024)}.serialize();
|
||||
Data serialized = OuterConfig{kdfParameters(), DataFixture::generate(1024), false}.serialize();
|
||||
OuterConfig deserialized = OuterConfig::deserialize(serialized).value();
|
||||
EXPECT_EQ(DerivedKeyConfig(salt(), N, r, p), deserialized.keyConfig);
|
||||
EXPECT_EQ(kdfParameters(), deserialized.kdfParameters);
|
||||
EXPECT_EQ(DataFixture::generate(1024), deserialized.encryptedInnerConfig);
|
||||
}
|
||||
|
||||
TEST_F(OuterConfigTest, DataEmpty) {
|
||||
Data serialized = OuterConfig{DerivedKeyConfig(salt(), N, r, p), Data(0)}.serialize();
|
||||
Data serialized = OuterConfig{kdfParameters(), Data(0), false}.serialize();
|
||||
OuterConfig deserialized = OuterConfig::deserialize(serialized).value();
|
||||
EXPECT_EQ(DerivedKeyConfig(salt(), N, r, p), deserialized.keyConfig);
|
||||
EXPECT_EQ(kdfParameters(), deserialized.kdfParameters);
|
||||
EXPECT_EQ(Data(0), deserialized.encryptedInnerConfig);
|
||||
}
|
||||
|
||||
TEST_F(OuterConfigTest, KeyConfigEmpty) {
|
||||
Data serialized = OuterConfig{DerivedKeyConfig(Data(0), 0, 0, 0), DataFixture::generate(1024)}.serialize();
|
||||
Data serialized = OuterConfig{Data(0), DataFixture::generate(1024), false}.serialize();
|
||||
OuterConfig deserialized = OuterConfig::deserialize(serialized).value();
|
||||
EXPECT_EQ(DerivedKeyConfig(Data(0), 0, 0, 0), deserialized.keyConfig);
|
||||
EXPECT_EQ(Data(0), deserialized.kdfParameters);
|
||||
EXPECT_EQ(DataFixture::generate(1024), deserialized.encryptedInnerConfig);
|
||||
}
|
||||
|
||||
TEST_F(OuterConfigTest, DataAndKeyConfigEmpty) {
|
||||
Data serialized = OuterConfig{DerivedKeyConfig(Data(0), 0, 0, 0), Data(0)}.serialize();
|
||||
Data serialized = OuterConfig{Data(0), Data(0), false}.serialize();
|
||||
OuterConfig deserialized = OuterConfig::deserialize(serialized).value();
|
||||
EXPECT_EQ(DerivedKeyConfig(Data(0), 0, 0, 0), deserialized.keyConfig);
|
||||
EXPECT_EQ(Data(0), deserialized.kdfParameters);
|
||||
EXPECT_EQ(Data(0), deserialized.encryptedInnerConfig);
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,6 @@ using cpputils::Data;
|
||||
using cpputils::DataFixture;
|
||||
using cpputils::unique_ref;
|
||||
using cpputils::make_unique_ref;
|
||||
using cpputils::DerivedKeyConfig;
|
||||
using namespace cryfs;
|
||||
|
||||
// This is needed for google test
|
||||
@ -22,10 +21,13 @@ namespace boost {
|
||||
|
||||
class OuterEncryptorTest : public ::testing::Test {
|
||||
public:
|
||||
Data kdfParameters() {
|
||||
return DataFixture::generate(128);
|
||||
}
|
||||
|
||||
unique_ref<OuterEncryptor> makeOuterEncryptor() {
|
||||
auto key = DataFixture::generateFixedSize<OuterEncryptor::Cipher::EncryptionKey::BINARY_LENGTH>();
|
||||
auto salt = DataFixture::generate(128);
|
||||
return make_unique_ref<OuterEncryptor>(key, DerivedKeyConfig(std::move(salt), 1024, 1, 2));
|
||||
return make_unique_ref<OuterEncryptor>(key, kdfParameters());
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user