Added test cases for CryConfigEncryptor
This commit is contained in:
parent
f90196826b
commit
10cbb06a4b
@ -13,9 +13,6 @@
|
||||
#include "../CryCipher.h"
|
||||
|
||||
namespace cryfs {
|
||||
//TODO Test
|
||||
//TODO Test that encrypted config data always has the same size, no matter how big the plaintext config data
|
||||
//TODO Test that specified inner cipher is used (e.g. can't be decrypted with other cipher)
|
||||
//TODO Use own exception for cpputils::Serializer/cpputils::Deserializer errors and only catch them
|
||||
class CryConfigEncryptor {
|
||||
public:
|
||||
|
@ -13,7 +13,7 @@ using namespace cpputils::logging;
|
||||
namespace cryfs {
|
||||
const string InnerConfig::HEADER = "cryfs.config.inner;0";
|
||||
|
||||
Data InnerConfig::serialize() {
|
||||
Data InnerConfig::serialize() const {
|
||||
try {
|
||||
Serializer serializer(Serializer::StringSize(HEADER)
|
||||
+ Serializer::StringSize(cipherName)
|
||||
|
@ -11,7 +11,7 @@ namespace cryfs {
|
||||
std::string cipherName;
|
||||
cpputils::Data encryptedConfig;
|
||||
|
||||
cpputils::Data serialize();
|
||||
cpputils::Data serialize() const;
|
||||
static boost::optional<InnerConfig> deserialize(const cpputils::Data &data);
|
||||
|
||||
private:
|
||||
|
@ -24,7 +24,7 @@ namespace cryfs {
|
||||
serializer->writeString(HEADER);
|
||||
}
|
||||
|
||||
Data OuterConfig::serialize() {
|
||||
Data OuterConfig::serialize() const {
|
||||
try {
|
||||
Serializer serializer(Serializer::StringSize(HEADER)
|
||||
+ keyConfig.serializedSize()
|
||||
|
@ -12,7 +12,7 @@ namespace cryfs {
|
||||
cpputils::DerivedKeyConfig keyConfig;
|
||||
cpputils::Data encryptedInnerConfig;
|
||||
|
||||
cpputils::Data serialize();
|
||||
cpputils::Data serialize() const;
|
||||
static boost::optional<OuterConfig> deserialize(const cpputils::Data &data);
|
||||
|
||||
private:
|
||||
|
135
test/config/crypto/CryConfigEncryptorTest.cpp
Normal file
135
test/config/crypto/CryConfigEncryptorTest.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
#include <google/gtest/gtest.h>
|
||||
#include <messmer/cpp-utils/data/DataFixture.h>
|
||||
#include <messmer/cpp-utils/crypto/symmetric/ciphers.h>
|
||||
#include <boost/optional/optional_io.hpp>
|
||||
#include "../../../src/config/crypto/CryConfigEncryptor.h"
|
||||
|
||||
using std::ostream;
|
||||
using cpputils::unique_ref;
|
||||
using cpputils::make_unique_ref;
|
||||
using cpputils::DataFixture;
|
||||
using cpputils::Data;
|
||||
using cpputils::DerivedKeyConfig;
|
||||
using cpputils::DerivedKey;
|
||||
using cpputils::AES128_CFB;
|
||||
using cpputils::AES256_GCM;
|
||||
using cpputils::Twofish256_GCM;
|
||||
using cpputils::Twofish128_CFB;
|
||||
using boost::none;
|
||||
using namespace cryfs;
|
||||
|
||||
// This is needed for google test
|
||||
namespace boost {
|
||||
inline ostream &operator<<(ostream &stream, const CryConfigEncryptor::Decrypted &) {
|
||||
return stream << "CryConfigEncryptor::Decrypted()";
|
||||
}
|
||||
}
|
||||
|
||||
class CryConfigEncryptorTest: public ::testing::Test {
|
||||
public:
|
||||
|
||||
unique_ref<CryConfigEncryptor> makeEncryptor() {
|
||||
return make_unique_ref<CryConfigEncryptor>(_derivedKey());
|
||||
}
|
||||
|
||||
Data changeInnerCipherFieldTo(Data data, const string &newCipherName) {
|
||||
InnerConfig innerConfig = _decryptInnerConfig(data);
|
||||
innerConfig.cipherName = newCipherName;
|
||||
return _encryptInnerConfig(innerConfig);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
unique_ref<OuterEncryptor> _outerEncryptor() {
|
||||
auto outerKey = _derivedKey().key().take<CryConfigEncryptor::OuterKeySize>();
|
||||
return make_unique_ref<OuterEncryptor>(outerKey, _derivedKey().config());
|
||||
}
|
||||
|
||||
InnerConfig _decryptInnerConfig(const Data &data) {
|
||||
OuterConfig outerConfig = OuterConfig::deserialize(data).value();
|
||||
Data serializedInnerConfig = _outerEncryptor()->decrypt(outerConfig).value();
|
||||
return InnerConfig::deserialize(serializedInnerConfig).value();
|
||||
}
|
||||
|
||||
Data _encryptInnerConfig(const InnerConfig &innerConfig) {
|
||||
Data serializedInnerConfig = innerConfig.serialize();
|
||||
OuterConfig outerConfig = _outerEncryptor()->encrypt(serializedInnerConfig);
|
||||
return outerConfig.serialize();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(CryConfigEncryptorTest, EncryptAndDecrypt_Data_AES) {
|
||||
auto encryptor = makeEncryptor();
|
||||
Data encrypted = encryptor->encrypt(DataFixture::generate(400), AES256_GCM::NAME);
|
||||
auto decrypted = encryptor->decrypt(encrypted).value();
|
||||
EXPECT_EQ(DataFixture::generate(400), decrypted.data);
|
||||
}
|
||||
|
||||
TEST_F(CryConfigEncryptorTest, EncryptAndDecrypt_Data_Twofish) {
|
||||
auto encryptor = makeEncryptor();
|
||||
Data encrypted = encryptor->encrypt(DataFixture::generate(400), Twofish128_CFB::NAME);
|
||||
auto decrypted = encryptor->decrypt(encrypted).value();
|
||||
EXPECT_EQ(DataFixture::generate(400), decrypted.data);
|
||||
}
|
||||
|
||||
TEST_F(CryConfigEncryptorTest, EncryptAndDecrypt_Cipher_AES) {
|
||||
auto encryptor = makeEncryptor();
|
||||
Data encrypted = encryptor->encrypt(DataFixture::generate(400), AES256_GCM::NAME);
|
||||
auto decrypted = encryptor->decrypt(encrypted).value();
|
||||
EXPECT_EQ(AES256_GCM::NAME, decrypted.cipherName);
|
||||
}
|
||||
|
||||
TEST_F(CryConfigEncryptorTest, EncryptAndDecrypt_Cipher_Twofish) {
|
||||
auto encryptor = makeEncryptor();
|
||||
Data encrypted = encryptor->encrypt(DataFixture::generate(400), Twofish128_CFB::NAME);
|
||||
auto decrypted = encryptor->decrypt(encrypted).value();
|
||||
EXPECT_EQ(Twofish128_CFB::NAME, decrypted.cipherName);
|
||||
}
|
||||
|
||||
TEST_F(CryConfigEncryptorTest, EncryptAndDecrypt_EmptyData) {
|
||||
auto encryptor = makeEncryptor();
|
||||
Data encrypted = encryptor->encrypt(Data(0), AES256_GCM::NAME);
|
||||
auto decrypted = encryptor->decrypt(encrypted).value();
|
||||
EXPECT_EQ(Data(0), decrypted.data);
|
||||
}
|
||||
|
||||
TEST_F(CryConfigEncryptorTest, InvalidCiphertext) {
|
||||
auto encryptor = makeEncryptor();
|
||||
Data encrypted = encryptor->encrypt(DataFixture::generate(400), AES256_GCM::NAME);
|
||||
*(char*)encrypted.data() = *(char*)encrypted.data()+1; //Modify ciphertext
|
||||
auto decrypted = encryptor->decrypt(encrypted);
|
||||
EXPECT_EQ(none, decrypted);
|
||||
}
|
||||
|
||||
TEST_F(CryConfigEncryptorTest, DoesntEncryptWhenTooLarge) {
|
||||
auto encryptor = makeEncryptor();
|
||||
EXPECT_THROW(
|
||||
encryptor->encrypt(DataFixture::generate(2000), AES256_GCM::NAME),
|
||||
std::runtime_error
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CryConfigEncryptorTest, EncryptionIsFixedSize) {
|
||||
auto encryptor = makeEncryptor();
|
||||
Data encrypted1 = encryptor->encrypt(DataFixture::generate(100), AES128_CFB::NAME);
|
||||
Data encrypted2 = encryptor->encrypt(DataFixture::generate(200), Twofish256_GCM::NAME);
|
||||
Data encrypted3 = encryptor->encrypt(Data(0), AES256_GCM::NAME);
|
||||
|
||||
EXPECT_EQ(encrypted1.size(), encrypted2.size());
|
||||
EXPECT_EQ(encrypted1.size(), encrypted3.size());
|
||||
}
|
||||
|
||||
TEST_F(CryConfigEncryptorTest, SpecifiedInnerCipherIsUsed) {
|
||||
//Tests that it can't be decrypted if the inner cipher field stores the wrong cipher
|
||||
auto encryptor = makeEncryptor();
|
||||
Data encrypted = encryptor->encrypt(DataFixture::generate(400), AES256_GCM::NAME);
|
||||
encrypted = changeInnerCipherFieldTo(std::move(encrypted), Twofish256_GCM::NAME);
|
||||
auto decrypted = encryptor->decrypt(encrypted);
|
||||
EXPECT_EQ(none, decrypted);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user