Simplify: key size is only known at runtime, not a template parameter anymore

This commit is contained in:
Sebastian Messmer 2018-10-21 22:53:53 +02:00
parent 42f0b00828
commit 954d6662f6
22 changed files with 119 additions and 95 deletions

View File

@ -9,22 +9,12 @@ namespace cpputils {
class PasswordBasedKDF { class PasswordBasedKDF {
public: public:
virtual ~PasswordBasedKDF() {} virtual ~PasswordBasedKDF() = default;
template<size_t KEYSIZE> EncryptionKey<KEYSIZE> deriveKey(const std::string &password); virtual EncryptionKey deriveKey(size_t keySize, const std::string &password) = 0;
virtual const Data &kdfParameters() const = 0; virtual const Data &kdfParameters() const = 0;
protected:
virtual void derive(void *destination, size_t size, const std::string &password) = 0;
}; };
template<size_t KEYSIZE> EncryptionKey<KEYSIZE>
inline PasswordBasedKDF::deriveKey(const std::string &password) {
auto result = EncryptionKey<KEYSIZE>::Null();
derive(result.data(), result.BINARY_LENGTH, password);
return result;
}
} }

View File

@ -22,11 +22,13 @@ namespace cpputils {
:_config(std::move(config)), _serializedConfig(_config.serialize()), _wasGeneratedBefore(false) { :_config(std::move(config)), _serializedConfig(_config.serialize()), _wasGeneratedBefore(false) {
} }
void SCrypt::derive(void *destination, size_t size, const string &password) { EncryptionKey SCrypt::deriveKey(size_t keySize, const std::string &password) {
_checkCallOnlyOnce(); _checkCallOnlyOnce();
auto result = EncryptionKey::Null(keySize);
size_t status = CryptoPP::Scrypt().DeriveKey( size_t status = CryptoPP::Scrypt().DeriveKey(
static_cast<uint8_t*>(destination), size, static_cast<uint8_t*>(result.data()), result.binaryLength(),
reinterpret_cast<const uint8_t*>(password.c_str()), password.size(), reinterpret_cast<const uint8_t*>(password.c_str()), password.size(),
static_cast<const uint8_t*>(_config.salt().data()), _config.salt().size(), static_cast<const uint8_t*>(_config.salt().data()), _config.salt().size(),
_config.N(), _config.r(), _config.p() _config.N(), _config.r(), _config.p()
@ -34,6 +36,8 @@ namespace cpputils {
if (status != 1) { if (status != 1) {
throw std::runtime_error("Error running scrypt key derivation. Error code: "+std::to_string(status)); throw std::runtime_error("Error running scrypt key derivation. Error code: "+std::to_string(status));
} }
return result;
} }
const Data &SCrypt::kdfParameters() const { const Data &SCrypt::kdfParameters() const {

View File

@ -32,8 +32,7 @@ namespace cpputils {
SCrypt(SCryptParameters config); SCrypt(SCryptParameters config);
protected: EncryptionKey deriveKey(size_t keySize, const std::string &password) override;
void derive(void *destination, size_t size, const std::string &password) override;
private: private:
void _checkCallOnlyOnce(); void _checkCallOnlyOnce();

View File

@ -16,7 +16,10 @@ namespace cpputils {
template<typename BlockCipher, unsigned int KeySize> template<typename BlockCipher, unsigned int KeySize>
class CFB_Cipher { class CFB_Cipher {
public: public:
using EncryptionKey = cpputils::EncryptionKey<KeySize>; using EncryptionKey = cpputils::EncryptionKey;
static constexpr unsigned int KEYSIZE = KeySize;
static constexpr unsigned int STRING_KEYSIZE = 2 * KEYSIZE;
static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) { static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) {
return plaintextBlockSize + IV_SIZE; return plaintextBlockSize + IV_SIZE;
@ -33,10 +36,17 @@ private:
static constexpr unsigned int IV_SIZE = BlockCipher::BLOCKSIZE; static constexpr unsigned int IV_SIZE = BlockCipher::BLOCKSIZE;
}; };
template<class BlockCipher, unsigned int KeySize>
constexpr unsigned int CFB_Cipher<BlockCipher, KeySize>::KEYSIZE;
template<class BlockCipher, unsigned int KeySize>
constexpr unsigned int CFB_Cipher<BlockCipher, KeySize>::STRING_KEYSIZE;
template<typename BlockCipher, unsigned int KeySize> template<typename BlockCipher, unsigned int KeySize>
Data CFB_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) { Data CFB_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) {
ASSERT(encKey.binaryLength() == KeySize, "Wrong key size");
FixedSizeData<IV_SIZE> iv = Random::PseudoRandom().getFixedSize<IV_SIZE>(); FixedSizeData<IV_SIZE> iv = Random::PseudoRandom().getFixedSize<IV_SIZE>();
auto encryption = typename CryptoPP::CFB_Mode<BlockCipher>::Encryption(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.BINARY_LENGTH, iv.data()); auto encryption = typename CryptoPP::CFB_Mode<BlockCipher>::Encryption(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.binaryLength(), iv.data());
Data ciphertext(ciphertextSize(plaintextSize)); Data ciphertext(ciphertextSize(plaintextSize));
iv.ToBinary(ciphertext.data()); iv.ToBinary(ciphertext.data());
if (plaintextSize > 0) { if (plaintextSize > 0) {
@ -47,13 +57,15 @@ Data CFB_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext,
template<typename BlockCipher, unsigned int KeySize> template<typename BlockCipher, unsigned int KeySize>
boost::optional<Data> CFB_Cipher<BlockCipher, KeySize>::decrypt(const CryptoPP::byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) { boost::optional<Data> CFB_Cipher<BlockCipher, KeySize>::decrypt(const CryptoPP::byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) {
ASSERT(encKey.binaryLength() == KeySize, "Wrong key size");
if (ciphertextSize < IV_SIZE) { if (ciphertextSize < IV_SIZE) {
return boost::none; return boost::none;
} }
const CryptoPP::byte *ciphertextIV = ciphertext; const CryptoPP::byte *ciphertextIV = ciphertext;
const CryptoPP::byte *ciphertextData = ciphertext + IV_SIZE; const CryptoPP::byte *ciphertextData = ciphertext + IV_SIZE;
auto decryption = typename CryptoPP::CFB_Mode<BlockCipher>::Decryption(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.BINARY_LENGTH, ciphertextIV); auto decryption = typename CryptoPP::CFB_Mode<BlockCipher>::Decryption(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.binaryLength(), ciphertextIV);
Data plaintext(plaintextSize(ciphertextSize)); Data plaintext(plaintextSize(ciphertextSize));
if (plaintext.size() > 0) { if (plaintext.size() > 0) {
// TODO Shouldn't we pass in ciphertextSize instead of plaintext.size() here as last argument (and also in the if above)? // TODO Shouldn't we pass in ciphertextSize instead of plaintext.size() here as last argument (and also in the if above)?

View File

@ -17,7 +17,9 @@ public:
BOOST_CONCEPT_USAGE(CipherConcept) { BOOST_CONCEPT_USAGE(CipherConcept) {
same_type(UINT32_C(0), X::ciphertextSize(UINT32_C(5))); same_type(UINT32_C(0), X::ciphertextSize(UINT32_C(5)));
same_type(UINT32_C(0), X::plaintextSize(UINT32_C(5))); same_type(UINT32_C(0), X::plaintextSize(UINT32_C(5)));
typename X::EncryptionKey key = X::EncryptionKey::CreateKey(Random::OSRandom()); same_type(UINT32_C(0), X::KEYSIZE);
same_type(UINT32_C(0), X::STRING_KEYSIZE);
typename X::EncryptionKey key = X::EncryptionKey::CreateKey(Random::OSRandom(), X::KEYSIZE);
same_type(Data(0), X::encrypt(static_cast<uint8_t*>(nullptr), UINT32_C(0), key)); same_type(Data(0), X::encrypt(static_cast<uint8_t*>(nullptr), UINT32_C(0), key));
same_type(boost::optional<Data>(Data(0)), X::decrypt(static_cast<uint8_t*>(nullptr), UINT32_C(0), key)); same_type(boost::optional<Data>(Data(0)), X::decrypt(static_cast<uint8_t*>(nullptr), UINT32_C(0), key));
string name = X::NAME; string name = X::NAME;

View File

@ -19,14 +19,11 @@ namespace cpputils {
* that there aren't any copies made to different memory regions. However, these other memory regions should be short-lived * that there aren't any copies made to different memory regions. However, these other memory regions should be short-lived
* and therefore much less likely to swap. * and therefore much less likely to swap.
*/ */
template<size_t KeySize>
class EncryptionKey final { class EncryptionKey final {
private: private:
explicit EncryptionKey(std::shared_ptr<Data> keyData) explicit EncryptionKey(std::shared_ptr<Data> keyData)
: _keyData(std::move(keyData)) { : _keyData(std::move(keyData)) {
ASSERT(_keyData->size() == KeySize, "Wrong key data size");
} }
template<size_t OtherKeySize> friend class EncryptionKey;
public: public:
EncryptionKey(const EncryptionKey& rhs) = default; EncryptionKey(const EncryptionKey& rhs) = default;
@ -34,12 +31,17 @@ public:
EncryptionKey& operator=(const EncryptionKey& rhs) = default; EncryptionKey& operator=(const EncryptionKey& rhs) = default;
EncryptionKey& operator=(EncryptionKey&& rhs) = default; EncryptionKey& operator=(EncryptionKey&& rhs) = default;
static constexpr size_t BINARY_LENGTH = KeySize; size_t binaryLength() const {
static constexpr size_t STRING_LENGTH = 2 * BINARY_LENGTH; return _keyData->size();
}
static EncryptionKey Null() { size_t stringLength() const {
return 2 * binaryLength();
}
static EncryptionKey Null(size_t keySize) {
auto data = std::make_shared<Data>( auto data = std::make_shared<Data>(
KeySize, keySize,
make_unique_ref<UnswappableAllocator>() make_unique_ref<UnswappableAllocator>()
); );
data->FillWithZeroes(); data->FillWithZeroes();
@ -47,28 +49,27 @@ public:
} }
static EncryptionKey FromString(const std::string& keyData) { static EncryptionKey FromString(const std::string& keyData) {
ASSERT(keyData.size() == STRING_LENGTH, "Wrong input size or EncryptionKey::FromString()");
auto data = std::make_shared<Data>( auto data = std::make_shared<Data>(
Data::FromString(keyData, make_unique_ref<UnswappableAllocator>()) Data::FromString(keyData, make_unique_ref<UnswappableAllocator>())
); );
ASSERT(data->size() == KeySize, "Wrong input size for EncryptionKey::FromString()"); EncryptionKey key(std::move(data));
ASSERT(key.stringLength() == keyData.size(), "Wrong input size for EncryptionKey::FromString()");
return EncryptionKey(std::move(data)); return key;
} }
std::string ToString() const { std::string ToString() const {
auto result = _keyData->ToString(); auto result = _keyData->ToString();
ASSERT(result.size() == STRING_LENGTH, "Wrong string length"); ASSERT(result.size() == stringLength(), "Wrong string length");
return result; return result;
} }
static EncryptionKey CreateKey(RandomGenerator &randomGenerator) { static EncryptionKey CreateKey(RandomGenerator &randomGenerator, size_t keySize) {
EncryptionKey result(std::make_shared<Data>( EncryptionKey result(std::make_shared<Data>(
KeySize, keySize,
make_unique_ref<UnswappableAllocator>() // the allocator makes sure key data is never swapped to disk make_unique_ref<UnswappableAllocator>() // the allocator makes sure key data is never swapped to disk
)); ));
randomGenerator.write(result._keyData->data(), KeySize); randomGenerator.write(result._keyData->data(), keySize);
return result; return result;
} }
@ -82,29 +83,25 @@ public:
// TODO Test take/drop // TODO Test take/drop
template<size_t NumTaken> EncryptionKey take(size_t numTaken) const {
EncryptionKey<NumTaken> take() const { ASSERT(numTaken <= _keyData->size(), "Out of bounds");
static_assert(NumTaken <= KeySize, "Out of bounds"); auto result = std::make_shared<Data>(numTaken, make_unique_ref<UnswappableAllocator>());
auto result = std::make_shared<Data>(NumTaken, make_unique_ref<UnswappableAllocator>()); std::memcpy(result->data(), _keyData->data(), numTaken);
std::memcpy(result->data(), _keyData->data(), NumTaken); return EncryptionKey(std::move(result));
return EncryptionKey<NumTaken>(std::move(result));
} }
template<size_t NumDropped> EncryptionKey drop(size_t numDropped) const {
EncryptionKey<KeySize - NumDropped> drop() const { ASSERT(numDropped <= _keyData->size(), "Out of bounds");
static_assert(NumDropped <= KeySize, "Out of bounds"); const size_t resultSize = _keyData->size() - numDropped;
auto result = std::make_shared<Data>(KeySize - NumDropped, make_unique_ref<UnswappableAllocator>()); auto result = std::make_shared<Data>(resultSize, make_unique_ref<UnswappableAllocator>());
std::memcpy(result->data(), _keyData->dataOffset(NumDropped), KeySize - NumDropped); std::memcpy(result->data(), _keyData->dataOffset(numDropped), resultSize);
return EncryptionKey<KeySize - NumDropped>(std::move(result)); return EncryptionKey(std::move(result));
} }
private: private:
std::shared_ptr<Data> _keyData; std::shared_ptr<Data> _keyData;
}; };
template<size_t KeySize> constexpr size_t EncryptionKey<KeySize>::BINARY_LENGTH;
template<size_t KeySize> constexpr size_t EncryptionKey<KeySize>::STRING_LENGTH;
} }
#endif #endif

View File

@ -15,7 +15,10 @@ namespace cpputils {
template<typename BlockCipher, unsigned int KeySize> template<typename BlockCipher, unsigned int KeySize>
class GCM_Cipher { class GCM_Cipher {
public: public:
using EncryptionKey = cpputils::EncryptionKey<KeySize>; using EncryptionKey = cpputils::EncryptionKey;
static constexpr unsigned int KEYSIZE = KeySize;
static constexpr unsigned int STRING_KEYSIZE = 2 * KEYSIZE;
static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) { static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) {
return plaintextBlockSize + IV_SIZE + TAG_SIZE; return plaintextBlockSize + IV_SIZE + TAG_SIZE;
@ -33,11 +36,18 @@ private:
static constexpr unsigned int TAG_SIZE = 16; static constexpr unsigned int TAG_SIZE = 16;
}; };
template<class BlockCipher, unsigned int KeySize>
constexpr unsigned int GCM_Cipher<BlockCipher, KeySize>::KEYSIZE;
template<class BlockCipher, unsigned int KeySize>
constexpr unsigned int GCM_Cipher<BlockCipher, KeySize>::STRING_KEYSIZE;
template<typename BlockCipher, unsigned int KeySize> template<typename BlockCipher, unsigned int KeySize>
Data GCM_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) { Data GCM_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) {
ASSERT(encKey.binaryLength() == KeySize, "Wrong key size");
FixedSizeData<IV_SIZE> iv = Random::PseudoRandom().getFixedSize<IV_SIZE>(); FixedSizeData<IV_SIZE> iv = Random::PseudoRandom().getFixedSize<IV_SIZE>();
typename CryptoPP::GCM<BlockCipher, CryptoPP::GCM_64K_Tables>::Encryption encryption; typename CryptoPP::GCM<BlockCipher, CryptoPP::GCM_64K_Tables>::Encryption encryption;
encryption.SetKeyWithIV(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.BINARY_LENGTH, iv.data(), IV_SIZE); encryption.SetKeyWithIV(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.binaryLength(), iv.data(), IV_SIZE);
Data ciphertext(ciphertextSize(plaintextSize)); Data ciphertext(ciphertextSize(plaintextSize));
iv.ToBinary(ciphertext.data()); iv.ToBinary(ciphertext.data());
@ -52,6 +62,8 @@ Data GCM_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext,
template<typename BlockCipher, unsigned int KeySize> template<typename BlockCipher, unsigned int KeySize>
boost::optional<Data> GCM_Cipher<BlockCipher, KeySize>::decrypt(const CryptoPP::byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) { boost::optional<Data> GCM_Cipher<BlockCipher, KeySize>::decrypt(const CryptoPP::byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) {
ASSERT(encKey.binaryLength() == KeySize, "Wrong key size");
if (ciphertextSize < IV_SIZE + TAG_SIZE) { if (ciphertextSize < IV_SIZE + TAG_SIZE) {
return boost::none; return boost::none;
} }
@ -59,7 +71,7 @@ boost::optional<Data> GCM_Cipher<BlockCipher, KeySize>::decrypt(const CryptoPP::
const CryptoPP::byte *ciphertextIV = ciphertext; const CryptoPP::byte *ciphertextIV = ciphertext;
const CryptoPP::byte *ciphertextData = ciphertext + IV_SIZE; const CryptoPP::byte *ciphertextData = ciphertext + IV_SIZE;
typename CryptoPP::GCM<BlockCipher, CryptoPP::GCM_64K_Tables>::Decryption decryption; typename CryptoPP::GCM<BlockCipher, CryptoPP::GCM_64K_Tables>::Decryption decryption;
decryption.SetKeyWithIV(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.BINARY_LENGTH, ciphertextIV, IV_SIZE); decryption.SetKeyWithIV(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.binaryLength(), ciphertextIV, IV_SIZE);
Data plaintext(plaintextSize(ciphertextSize)); Data plaintext(plaintextSize(ciphertextSize));
try { try {

View File

@ -1,7 +1,7 @@
#include "FakeAuthenticatedCipher.h" #include "FakeAuthenticatedCipher.h"
namespace cpputils { namespace cpputils {
constexpr unsigned int FakeKey::BINARY_LENGTH; constexpr unsigned int FakeAuthenticatedCipher::KEYSIZE;
constexpr unsigned int FakeAuthenticatedCipher::STRING_KEYSIZE;
std::random_device FakeAuthenticatedCipher::random_; std::random_device FakeAuthenticatedCipher::random_;
} }

View File

@ -17,9 +17,12 @@ namespace cpputils {
return FakeKey{static_cast<uint64_t>(std::strtol(keyData.c_str(), nullptr, 10))}; return FakeKey{static_cast<uint64_t>(std::strtol(keyData.c_str(), nullptr, 10))};
} }
static constexpr unsigned int BINARY_LENGTH = sizeof(uint64_t); size_t binaryLength() const {
return sizeof(uint64_t);
}
static FakeKey CreateKey(RandomGenerator &randomGenerator) { static FakeKey CreateKey(RandomGenerator &randomGenerator, size_t keySize) {
ASSERT(keySize == sizeof(uint64_t), "Wrong key size");
auto data = randomGenerator.getFixedSize<sizeof(uint64_t)>(); auto data = randomGenerator.getFixedSize<sizeof(uint64_t)>();
return FakeKey {*reinterpret_cast<uint64_t*>(data.data())}; return FakeKey {*reinterpret_cast<uint64_t*>(data.data())};
} }
@ -34,6 +37,9 @@ namespace cpputils {
using EncryptionKey = FakeKey; using EncryptionKey = FakeKey;
static constexpr unsigned int KEYSIZE = sizeof(uint64_t);
static constexpr unsigned int STRING_KEYSIZE = 2 * KEYSIZE;
static EncryptionKey Key1() { static EncryptionKey Key1() {
return FakeKey{5}; return FakeKey{5};
} }

View File

@ -25,7 +25,7 @@ class CryCipherInstance: public CryCipher {
public: public:
BOOST_CONCEPT_ASSERT((CipherConcept<Cipher>)); BOOST_CONCEPT_ASSERT((CipherConcept<Cipher>));
static_assert(Cipher::EncryptionKey::BINARY_LENGTH <= CryCiphers::MAX_KEY_SIZE, "The key size for this cipher is too large. Please modify CryCiphers::MAX_KEY_SIZE"); static_assert(Cipher::KEYSIZE <= CryCiphers::MAX_KEY_SIZE, "The key size for this cipher is too large. Please modify CryCiphers::MAX_KEY_SIZE");
CryCipherInstance(const optional<string> warning = none): _warning(warning) { CryCipherInstance(const optional<string> warning = none): _warning(warning) {
} }
@ -43,11 +43,12 @@ public:
} }
string createKey(cpputils::RandomGenerator &randomGenerator) const override { string createKey(cpputils::RandomGenerator &randomGenerator) const override {
return Cipher::EncryptionKey::CreateKey(randomGenerator).ToString(); return Cipher::EncryptionKey::CreateKey(randomGenerator, Cipher::KEYSIZE).ToString();
} }
unique_ref<InnerEncryptor> createInnerConfigEncryptor(const EncryptionKey<CryCiphers::MAX_KEY_SIZE>& key) const override { unique_ref<InnerEncryptor> createInnerConfigEncryptor(const EncryptionKey& key) const override {
return make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key.take<Cipher::EncryptionKey::BINARY_LENGTH>()); ASSERT(key.binaryLength() == CryCiphers::MAX_KEY_SIZE, "Wrong key size");
return make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key.take(Cipher::KEYSIZE));
} }
private: private:

View File

@ -41,7 +41,7 @@ public:
virtual const boost::optional<std::string> &warning() const = 0; virtual const boost::optional<std::string> &warning() const = 0;
virtual cpputils::unique_ref<blockstore::BlockStore2> createEncryptedBlockstore(cpputils::unique_ref<blockstore::BlockStore2> baseBlockStore, const std::string &encKey) const = 0; virtual cpputils::unique_ref<blockstore::BlockStore2> createEncryptedBlockstore(cpputils::unique_ref<blockstore::BlockStore2> baseBlockStore, const std::string &encKey) const = 0;
virtual std::string createKey(cpputils::RandomGenerator &randomGenerator) const = 0; virtual std::string createKey(cpputils::RandomGenerator &randomGenerator) const = 0;
virtual cpputils::unique_ref<InnerEncryptor> createInnerConfigEncryptor(const cpputils::EncryptionKey<CryCiphers::MAX_KEY_SIZE> &key) const = 0; virtual cpputils::unique_ref<InnerEncryptor> createInnerConfigEncryptor(const cpputils::EncryptionKey &key) const = 0;
}; };

View File

@ -13,8 +13,9 @@ namespace cryfs {
constexpr size_t CryConfigEncryptor::OuterKeySize; constexpr size_t CryConfigEncryptor::OuterKeySize;
constexpr size_t CryConfigEncryptor::MaxTotalKeySize; constexpr size_t CryConfigEncryptor::MaxTotalKeySize;
CryConfigEncryptor::CryConfigEncryptor(cpputils::EncryptionKey<MaxTotalKeySize> derivedKey, cpputils::Data kdfParameters) CryConfigEncryptor::CryConfigEncryptor(cpputils::EncryptionKey derivedKey, cpputils::Data kdfParameters)
: _derivedKey(std::move(derivedKey)), _kdfParameters(std::move(kdfParameters)) { : _derivedKey(std::move(derivedKey)), _kdfParameters(std::move(kdfParameters)) {
ASSERT(_derivedKey.binaryLength() == MaxTotalKeySize, "Wrong key size");
} }
Data CryConfigEncryptor::encrypt(const Data &plaintext, const string &cipherName) const { Data CryConfigEncryptor::encrypt(const Data &plaintext, const string &cipherName) const {
@ -45,12 +46,12 @@ namespace cryfs {
} }
unique_ref<OuterEncryptor> CryConfigEncryptor::_outerEncryptor() const { unique_ref<OuterEncryptor> CryConfigEncryptor::_outerEncryptor() const {
auto outerKey = _derivedKey.take<OuterKeySize>(); auto outerKey = _derivedKey.take(OuterKeySize);
return make_unique_ref<OuterEncryptor>(std::move(outerKey), _kdfParameters.copy()); return make_unique_ref<OuterEncryptor>(std::move(outerKey), _kdfParameters.copy());
} }
unique_ref<InnerEncryptor> CryConfigEncryptor::_innerEncryptor(const string &cipherName) const { unique_ref<InnerEncryptor> CryConfigEncryptor::_innerEncryptor(const string &cipherName) const {
auto innerKey = _derivedKey.drop<OuterKeySize>(); auto innerKey = _derivedKey.drop(OuterKeySize);
return CryCiphers::find(cipherName).createInnerConfigEncryptor(std::move(innerKey)); return CryCiphers::find(cipherName).createInnerConfigEncryptor(std::move(innerKey));
} }
} }

View File

@ -14,7 +14,7 @@ namespace cryfs {
//TODO Use own exception for cpputils::Serializer/cpputils::Deserializer errors and only catch them //TODO Use own exception for cpputils::Serializer/cpputils::Deserializer errors and only catch them
class CryConfigEncryptor final { class CryConfigEncryptor final {
public: public:
static constexpr size_t OuterKeySize = OuterEncryptor::Cipher::EncryptionKey::BINARY_LENGTH; static constexpr size_t OuterKeySize = OuterEncryptor::Cipher::KEYSIZE;
static constexpr size_t MaxTotalKeySize = OuterKeySize + CryCiphers::MAX_KEY_SIZE; static constexpr size_t MaxTotalKeySize = OuterKeySize + CryCiphers::MAX_KEY_SIZE;
struct Decrypted { struct Decrypted {
@ -23,7 +23,7 @@ namespace cryfs {
bool wasInDeprecatedConfigFormat; bool wasInDeprecatedConfigFormat;
}; };
CryConfigEncryptor(cpputils::EncryptionKey<MaxTotalKeySize> derivedKey, cpputils::Data _kdfParameters); CryConfigEncryptor(cpputils::EncryptionKey derivedKey, cpputils::Data _kdfParameters);
cpputils::Data encrypt(const cpputils::Data &plaintext, const std::string &cipherName) const; cpputils::Data encrypt(const cpputils::Data &plaintext, const std::string &cipherName) const;
boost::optional<Decrypted> decrypt(const cpputils::Data &data) const; boost::optional<Decrypted> decrypt(const cpputils::Data &data) const;
@ -32,7 +32,7 @@ namespace cryfs {
cpputils::unique_ref<OuterEncryptor> _outerEncryptor() const; cpputils::unique_ref<OuterEncryptor> _outerEncryptor() const;
cpputils::unique_ref<InnerEncryptor> _innerEncryptor(const std::string &cipherName) const; cpputils::unique_ref<InnerEncryptor> _innerEncryptor(const std::string &cipherName) const;
cpputils::EncryptionKey<MaxTotalKeySize> _derivedKey; cpputils::EncryptionKey _derivedKey;
cpputils::Data _kdfParameters; cpputils::Data _kdfParameters;
DISALLOW_COPY_AND_ASSIGN(CryConfigEncryptor); DISALLOW_COPY_AND_ASSIGN(CryConfigEncryptor);

View File

@ -33,7 +33,7 @@ namespace cryfs {
// (once we know which inner cipher was used) only generate as many key bytes as we need for the inner cipher. // (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. // 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. //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); auto key = kdf->deriveKey(CryConfigEncryptor::MaxTotalKeySize, password);
return make_unique_ref<CryConfigEncryptor>(key, kdf->kdfParameters().copy()); return make_unique_ref<CryConfigEncryptor>(key, kdf->kdfParameters().copy());
} }
} }

View File

@ -36,7 +36,7 @@ public:
private: private:
static typename Cipher::EncryptionKey createKeyFixture(int seed = 0) { static typename Cipher::EncryptionKey createKeyFixture(int seed = 0) {
return Cipher::EncryptionKey::FromString( return Cipher::EncryptionKey::FromString(
DataFixture::generate(Cipher::EncryptionKey::BINARY_LENGTH, seed).ToString() DataFixture::generate(Cipher::KEYSIZE, seed).ToString()
); );
} }
}; };
@ -55,7 +55,7 @@ public:
private: private:
static typename Cipher::EncryptionKey createKeyFixture(int seed = 0) { static typename Cipher::EncryptionKey createKeyFixture(int seed = 0) {
return Cipher::EncryptionKey::FromString( return Cipher::EncryptionKey::FromString(
DataFixture::generate(Cipher::EncryptionKey::BINARY_LENGTH, seed).ToString() DataFixture::generate(Cipher::KEYSIZE, seed).ToString()
); );
} }
}; };

View File

@ -14,39 +14,39 @@ public:
return result; return result;
} }
template<size_t SIZE> bool keyEquals(const EncryptionKey& lhs, const EncryptionKey& rhs) {
bool keyEquals(const EncryptionKey<SIZE>& lhs, const EncryptionKey<SIZE>& rhs) { ASSERT(lhs.binaryLength() == rhs.binaryLength(), "Keys must have equal size to be comparable");
return 0 == std::memcmp(lhs.data(), rhs.data(), SIZE); return 0 == std::memcmp(lhs.data(), rhs.data(), lhs.binaryLength());
} }
}; };
TEST_F(SCryptTest, GeneratedKeyIsReproductible_448) { TEST_F(SCryptTest, GeneratedKeyIsReproductible_448) {
auto derivedKey = scryptForNewKey->deriveKey<56>("mypassword"); auto derivedKey = scryptForNewKey->deriveKey(56, "mypassword");
auto rederivedKey = scryptForExistingKey->deriveKey<56>("mypassword"); auto rederivedKey = scryptForExistingKey->deriveKey(56, "mypassword");
EXPECT_TRUE(keyEquals(derivedKey, rederivedKey)); EXPECT_TRUE(keyEquals(derivedKey, rederivedKey));
} }
TEST_F(SCryptTest, GeneratedKeyIsReproductible_256) { TEST_F(SCryptTest, GeneratedKeyIsReproductible_256) {
auto derivedKey = scryptForNewKey->deriveKey<32>("mypassword"); auto derivedKey = scryptForNewKey->deriveKey(32, "mypassword");
auto rederivedKey = scryptForExistingKey->deriveKey<32>("mypassword"); auto rederivedKey = scryptForExistingKey->deriveKey(32, "mypassword");
EXPECT_TRUE(keyEquals(derivedKey, rederivedKey)); EXPECT_TRUE(keyEquals(derivedKey, rederivedKey));
} }
TEST_F(SCryptTest, GeneratedKeyIsReproductible_128) { TEST_F(SCryptTest, GeneratedKeyIsReproductible_128) {
auto derivedKey = scryptForNewKey->deriveKey<16>("mypassword"); auto derivedKey = scryptForNewKey->deriveKey(16, "mypassword");
auto rederivedKey = scryptForExistingKey->deriveKey<16>("mypassword"); auto rederivedKey = scryptForExistingKey->deriveKey(16, "mypassword");
EXPECT_TRUE(keyEquals(derivedKey, rederivedKey)); EXPECT_TRUE(keyEquals(derivedKey, rederivedKey));
} }
TEST_F(SCryptTest, GeneratedKeyIsReproductible_DefaultSettings) { TEST_F(SCryptTest, GeneratedKeyIsReproductible_DefaultSettings) {
auto derivedKey = scryptForNewKey->deriveKey<16>("mypassword"); auto derivedKey = scryptForNewKey->deriveKey(16, "mypassword");
auto rederivedKey = scryptForExistingKey->deriveKey<16>("mypassword"); auto rederivedKey = scryptForExistingKey->deriveKey(16, "mypassword");
EXPECT_TRUE(keyEquals(derivedKey, rederivedKey)); EXPECT_TRUE(keyEquals(derivedKey, rederivedKey));
} }
TEST_F(SCryptTest, DifferentPasswordResultsInDifferentKey) { TEST_F(SCryptTest, DifferentPasswordResultsInDifferentKey) {
auto derivedKey = scryptForNewKey->deriveKey<16>("mypassword"); auto derivedKey = scryptForNewKey->deriveKey(16, "mypassword");
auto rederivedKey = scryptForExistingKey->deriveKey<16>("mypassword2"); auto rederivedKey = scryptForExistingKey->deriveKey(16, "mypassword2");
EXPECT_FALSE(keyEquals(derivedKey, rederivedKey)); EXPECT_FALSE(keyEquals(derivedKey, rederivedKey));
} }

View File

@ -18,7 +18,7 @@ public:
typename Cipher::EncryptionKey encKey = createKeyFixture(); typename Cipher::EncryptionKey encKey = createKeyFixture();
static typename Cipher::EncryptionKey createKeyFixture(int seed = 0) { static typename Cipher::EncryptionKey createKeyFixture(int seed = 0) {
Data data = DataFixture::generate(Cipher::EncryptionKey::BINARY_LENGTH, seed); Data data = DataFixture::generate(Cipher::KEYSIZE, seed);
return Cipher::EncryptionKey::FromString(data.ToString()); return Cipher::EncryptionKey::FromString(data.ToString());
} }

View File

@ -37,7 +37,7 @@ public:
void EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE(const string &cipherName) { void EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE(const string &cipherName) {
const auto &actualCipher = CryCiphers::find(cipherName); const auto &actualCipher = CryCiphers::find(cipherName);
Data dataFixture = DataFixture::generate(1024); Data dataFixture = DataFixture::generate(1024);
string encKey = ExpectedCipher::EncryptionKey::CreateKey(Random::PseudoRandom()).ToString(); string encKey = ExpectedCipher::EncryptionKey::CreateKey(Random::PseudoRandom(), ExpectedCipher::KEYSIZE).ToString();
_EXPECT_ENCRYPTS_WITH_ACTUAL_BLOCKSTORE_DECRYPTS_CORRECTLY_WITH_EXPECTED_BLOCKSTORE<ExpectedCipher>(actualCipher, encKey, std::move(dataFixture)); _EXPECT_ENCRYPTS_WITH_ACTUAL_BLOCKSTORE_DECRYPTS_CORRECTLY_WITH_EXPECTED_BLOCKSTORE<ExpectedCipher>(actualCipher, encKey, std::move(dataFixture));
} }
@ -125,14 +125,14 @@ TEST_F(CryCipherTest, ThereIsACipherWithIntegrityWarning) {
#if CRYPTOPP_VERSION != 564 #if CRYPTOPP_VERSION != 564
TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_448) { TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_448) {
EXPECT_EQ(Mars448_GCM::EncryptionKey::STRING_LENGTH, CryCiphers::find("mars-448-gcm").createKey(Random::PseudoRandom()).size()); EXPECT_EQ(Mars448_GCM::STRING_KEYSIZE, CryCiphers::find("mars-448-gcm").createKey(Random::PseudoRandom()).size());
} }
#endif #endif
TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_256) { TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_256) {
EXPECT_EQ(AES256_GCM::EncryptionKey::STRING_LENGTH, CryCiphers::find("aes-256-gcm").createKey(Random::PseudoRandom()).size()); EXPECT_EQ(AES256_GCM::STRING_KEYSIZE, CryCiphers::find("aes-256-gcm").createKey(Random::PseudoRandom()).size());
} }
TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_128) { TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_128) {
EXPECT_EQ(AES128_GCM::EncryptionKey::STRING_LENGTH, CryCiphers::find("aes-128-gcm").createKey(Random::PseudoRandom()).size()); EXPECT_EQ(AES128_GCM::STRING_KEYSIZE, CryCiphers::find("aes-128-gcm").createKey(Random::PseudoRandom()).size());
} }

View File

@ -40,8 +40,8 @@ public:
} }
private: private:
EncryptionKey<CryConfigEncryptor::MaxTotalKeySize> _derivedKey() { EncryptionKey _derivedKey() {
return EncryptionKey<CryConfigEncryptor::MaxTotalKeySize>::FromString( return EncryptionKey::FromString(
DataFixture::generateFixedSize<CryConfigEncryptor::MaxTotalKeySize>(3).ToString() DataFixture::generateFixedSize<CryConfigEncryptor::MaxTotalKeySize>(3).ToString()
); );
} }
@ -51,7 +51,7 @@ private:
} }
unique_ref<OuterEncryptor> _outerEncryptor() { unique_ref<OuterEncryptor> _outerEncryptor() {
auto outerKey = _derivedKey().take<CryConfigEncryptor::OuterKeySize>(); auto outerKey = _derivedKey().take(CryConfigEncryptor::OuterKeySize);
return make_unique_ref<OuterEncryptor>(outerKey, _kdfParameters()); return make_unique_ref<OuterEncryptor>(outerKey, _kdfParameters());
} }

View File

@ -29,7 +29,7 @@ public:
template<class Cipher> template<class Cipher>
unique_ref<InnerEncryptor> makeInnerEncryptor() { unique_ref<InnerEncryptor> makeInnerEncryptor() {
auto key = Cipher::EncryptionKey::FromString( auto key = Cipher::EncryptionKey::FromString(
DataFixture::generateFixedSize<Cipher::EncryptionKey::BINARY_LENGTH>().ToString() DataFixture::generateFixedSize<Cipher::KEYSIZE>().ToString()
); );
return make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key); return make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key);
} }

View File

@ -29,7 +29,7 @@ public:
unique_ref<OuterEncryptor> makeOuterEncryptor() { unique_ref<OuterEncryptor> makeOuterEncryptor() {
auto key = OuterEncryptor::Cipher::EncryptionKey::FromString( auto key = OuterEncryptor::Cipher::EncryptionKey::FromString(
DataFixture::generateFixedSize<OuterEncryptor::Cipher::EncryptionKey::BINARY_LENGTH>().ToString() DataFixture::generateFixedSize<OuterEncryptor::Cipher::KEYSIZE>().ToString()
); );
return make_unique_ref<OuterEncryptor>(key, kdfParameters()); return make_unique_ref<OuterEncryptor>(key, kdfParameters());
} }

View File

@ -17,7 +17,7 @@ public:
cryfs::CryConfigFile configFile() { cryfs::CryConfigFile configFile() {
cryfs::CryConfig config; cryfs::CryConfig config;
config.SetCipher("aes-256-gcm"); config.SetCipher("aes-256-gcm");
config.SetEncryptionKey(cpputils::AES256_GCM::EncryptionKey::CreateKey(cpputils::Random::PseudoRandom()).ToString()); config.SetEncryptionKey(cpputils::AES256_GCM::EncryptionKey::CreateKey(cpputils::Random::PseudoRandom(), cpputils::AES256_GCM::KEYSIZE).ToString());
config.SetBlocksizeBytes(10240); config.SetBlocksizeBytes(10240);
return cryfs::CryConfigFile::create(_configFile.path(), std::move(config), "mypassword", cpputils::SCrypt::TestSettings); return cryfs::CryConfigFile::create(_configFile.path(), std::move(config), "mypassword", cpputils::SCrypt::TestSettings);
} }