- Run test cases for EncryptedBlockStore with different ciphers
- Implement FakeAuthenticatedCipher for use with specific EncryptedBlockStoreTest - Write skeleton for specific EncryptedBlockStoreTest - Fix behavior of AES256_CFB when called with too small input - Add testcase that all ciphers (also non-authenticating ones) have to handle too small input correctly
This commit is contained in:
parent
a36ab8e2d7
commit
0042ae1cef
@ -21,6 +21,10 @@ Data AES256_CFB::encrypt(const byte *plaintext, unsigned int plaintextSize, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<Data> AES256_CFB::decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) {
|
boost::optional<Data> AES256_CFB::decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) {
|
||||||
|
if (ciphertextSize < IV_SIZE) {
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
|
|
||||||
const byte *ciphertextIV = ciphertext;
|
const byte *ciphertextIV = ciphertext;
|
||||||
const byte *ciphertextData = ciphertext + IV_SIZE;
|
const byte *ciphertextData = ciphertext + IV_SIZE;
|
||||||
auto decryption = CFB_Mode<AES>::Decryption((byte*)encKey.data(), encKey.BINARY_LENGTH, ciphertextIV);
|
auto decryption = CFB_Mode<AES>::Decryption((byte*)encKey.data(), encKey.BINARY_LENGTH, ciphertextIV);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <boost/concept_check.hpp>
|
#include <boost/concept_check.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <messmer/cpp-utils/data/Data.h>
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
namespace encrypted {
|
namespace encrypted {
|
||||||
@ -15,8 +16,8 @@ public:
|
|||||||
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::CreateRandom();
|
typename X::EncryptionKey key = X::EncryptionKey::CreateRandom();
|
||||||
same_type(cpputils::Data(0), X::encrypt((byte*)nullptr, UINT32_C(0), key));
|
same_type(cpputils::Data(0), X::encrypt((uint8_t*)nullptr, UINT32_C(0), key));
|
||||||
same_type(boost::optional<cpputils::Data>(cpputils::Data(0)), X::decrypt((byte*)nullptr, UINT32_C(0), key));
|
same_type(boost::optional<cpputils::Data>(cpputils::Data(0)), X::decrypt((uint8_t*)nullptr, UINT32_C(0), key));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include <google/gtest/gtest.h>
|
#include <google/gtest/gtest.h>
|
||||||
|
#include "../../../implementations/encrypted/ciphers/Cipher.h"
|
||||||
#include "../../../implementations/encrypted/ciphers/AES256_CFB.h"
|
#include "../../../implementations/encrypted/ciphers/AES256_CFB.h"
|
||||||
#include "../../../implementations/encrypted/ciphers/AES256_GCM.h"
|
#include "../../../implementations/encrypted/ciphers/AES256_GCM.h"
|
||||||
#include "../../../implementations/encrypted/ciphers/Cipher.h"
|
#include "testutils/FakeAuthenticatedCipher.h"
|
||||||
|
|
||||||
#include <messmer/cpp-utils/data/DataFixture.h>
|
#include <messmer/cpp-utils/data/DataFixture.h>
|
||||||
#include <messmer/cpp-utils/data/Data.h>
|
#include <messmer/cpp-utils/data/Data.h>
|
||||||
@ -16,9 +17,9 @@ template<class Cipher>
|
|||||||
class CipherTest: public ::testing::Test {
|
class CipherTest: public ::testing::Test {
|
||||||
public:
|
public:
|
||||||
BOOST_CONCEPT_ASSERT((CipherConcept<Cipher>));
|
BOOST_CONCEPT_ASSERT((CipherConcept<Cipher>));
|
||||||
typename Cipher::EncryptionKey encKey = createRandomKey();
|
typename Cipher::EncryptionKey encKey = createKeyFixture();
|
||||||
|
|
||||||
static typename Cipher::EncryptionKey createRandomKey(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::EncryptionKey::BINARY_LENGTH, seed);
|
||||||
return Cipher::EncryptionKey::FromBinary(data.data());
|
return Cipher::EncryptionKey::FromBinary(data.data());
|
||||||
}
|
}
|
||||||
@ -40,6 +41,11 @@ public:
|
|||||||
EXPECT_EQ(Cipher::ciphertextSize(plaintext.size()), ciphertext.size());
|
EXPECT_EQ(Cipher::ciphertextSize(plaintext.size()), ciphertext.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExpectDoesntDecrypt(const Data &ciphertext) {
|
||||||
|
auto decrypted = Cipher::decrypt((byte*)ciphertext.data(), ciphertext.size(), this->encKey);
|
||||||
|
EXPECT_FALSE(decrypted);
|
||||||
|
}
|
||||||
|
|
||||||
Data Encrypt(const Data &plaintext) {
|
Data Encrypt(const Data &plaintext) {
|
||||||
return Cipher::encrypt((byte*)plaintext.data(), plaintext.size(), this->encKey);
|
return Cipher::encrypt((byte*)plaintext.data(), plaintext.size(), this->encKey);
|
||||||
}
|
}
|
||||||
@ -103,23 +109,38 @@ TYPED_TEST_P(CipherTest, EncryptedSize) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(CipherTest, TryDecryptDataThatIsTooSmall) {
|
||||||
|
Data tooSmallCiphertext(TypeParam::ciphertextSize(0) - 1);
|
||||||
|
this->ExpectDoesntDecrypt(tooSmallCiphertext);
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(CipherTest, TryDecryptDataThatIsMuchTooSmall_0) {
|
||||||
|
static_assert(TypeParam::ciphertextSize(0) > 0, "If this fails, the test case doesn't make sense.");
|
||||||
|
Data tooSmallCiphertext(0);
|
||||||
|
this->ExpectDoesntDecrypt(tooSmallCiphertext);
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(CipherTest, TryDecryptDataThatIsMuchTooSmall_1) {
|
||||||
|
static_assert(TypeParam::ciphertextSize(0) > 1, "If this fails, the test case doesn't make sense.");
|
||||||
|
Data tooSmallCiphertext(1);
|
||||||
|
this->ExpectDoesntDecrypt(tooSmallCiphertext);
|
||||||
|
}
|
||||||
|
|
||||||
REGISTER_TYPED_TEST_CASE_P(CipherTest,
|
REGISTER_TYPED_TEST_CASE_P(CipherTest,
|
||||||
Size,
|
Size,
|
||||||
EncryptThenDecrypt_Zeroes,
|
EncryptThenDecrypt_Zeroes,
|
||||||
EncryptThenDecrypt_Data,
|
EncryptThenDecrypt_Data,
|
||||||
EncryptIsIndeterministic_Zeroes,
|
EncryptIsIndeterministic_Zeroes,
|
||||||
EncryptIsIndeterministic_Data,
|
EncryptIsIndeterministic_Data,
|
||||||
EncryptedSize
|
EncryptedSize,
|
||||||
|
TryDecryptDataThatIsTooSmall,
|
||||||
|
TryDecryptDataThatIsMuchTooSmall_0,
|
||||||
|
TryDecryptDataThatIsMuchTooSmall_1
|
||||||
);
|
);
|
||||||
|
|
||||||
template<class Cipher>
|
template<class Cipher>
|
||||||
class AuthenticatedCipherTest: public CipherTest<Cipher> {
|
class AuthenticatedCipherTest: public CipherTest<Cipher> {
|
||||||
public:
|
public:
|
||||||
void ExpectDoesntDecrypt(const Data &ciphertext) {
|
|
||||||
auto decrypted = Cipher::decrypt((byte*)ciphertext.data(), ciphertext.size(), this->encKey);
|
|
||||||
EXPECT_FALSE(decrypted);
|
|
||||||
}
|
|
||||||
|
|
||||||
Data zeroes1 = CipherTest<Cipher>::CreateZeroes(1);
|
Data zeroes1 = CipherTest<Cipher>::CreateZeroes(1);
|
||||||
Data plaintext1 = CipherTest<Cipher>::CreateData(1);
|
Data plaintext1 = CipherTest<Cipher>::CreateData(1);
|
||||||
Data zeroes2 = CipherTest<Cipher>::CreateZeroes(100 * 1024);
|
Data zeroes2 = CipherTest<Cipher>::CreateZeroes(100 * 1024);
|
||||||
@ -184,23 +205,6 @@ TYPED_TEST_P(AuthenticatedCipherTest, TryDecryptRandomData) {
|
|||||||
this->ExpectDoesntDecrypt(this->plaintext2);
|
this->ExpectDoesntDecrypt(this->plaintext2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(AuthenticatedCipherTest, TryDecryptDataThatIsTooSmall) {
|
|
||||||
Data tooSmallCiphertext(TypeParam::ciphertextSize(0) - 1);
|
|
||||||
this->ExpectDoesntDecrypt(tooSmallCiphertext);
|
|
||||||
}
|
|
||||||
|
|
||||||
TYPED_TEST_P(AuthenticatedCipherTest, TryDecryptDataThatIsMuchTooSmall_0) {
|
|
||||||
static_assert(TypeParam::ciphertextSize(0) > 0, "If this fails, the test case doesn't make sense.");
|
|
||||||
Data tooSmallCiphertext(0);
|
|
||||||
this->ExpectDoesntDecrypt(tooSmallCiphertext);
|
|
||||||
}
|
|
||||||
|
|
||||||
TYPED_TEST_P(AuthenticatedCipherTest, TryDecryptDataThatIsMuchTooSmall_1) {
|
|
||||||
static_assert(TypeParam::ciphertextSize(0) > 1, "If this fails, the test case doesn't make sense.");
|
|
||||||
Data tooSmallCiphertext(1);
|
|
||||||
this->ExpectDoesntDecrypt(tooSmallCiphertext);
|
|
||||||
}
|
|
||||||
|
|
||||||
REGISTER_TYPED_TEST_CASE_P(AuthenticatedCipherTest,
|
REGISTER_TYPED_TEST_CASE_P(AuthenticatedCipherTest,
|
||||||
ModifyFirstByte_Zeroes_Size1,
|
ModifyFirstByte_Zeroes_Size1,
|
||||||
ModifyFirstByte_Zeroes,
|
ModifyFirstByte_Zeroes,
|
||||||
@ -211,13 +215,12 @@ REGISTER_TYPED_TEST_CASE_P(AuthenticatedCipherTest,
|
|||||||
ModifyMiddleByte_Zeroes,
|
ModifyMiddleByte_Zeroes,
|
||||||
ModifyMiddleByte_Data,
|
ModifyMiddleByte_Data,
|
||||||
TryDecryptZeroesData,
|
TryDecryptZeroesData,
|
||||||
TryDecryptRandomData,
|
TryDecryptRandomData
|
||||||
TryDecryptDataThatIsTooSmall,
|
|
||||||
TryDecryptDataThatIsMuchTooSmall_0,
|
|
||||||
TryDecryptDataThatIsMuchTooSmall_1
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
INSTANTIATE_TYPED_TEST_CASE_P(AES256_CFB, CipherTest, AES256_CFB);
|
INSTANTIATE_TYPED_TEST_CASE_P(Fake, CipherTest, FakeAuthenticatedCipher);
|
||||||
|
INSTANTIATE_TYPED_TEST_CASE_P(Fake, AuthenticatedCipherTest, FakeAuthenticatedCipher);
|
||||||
|
INSTANTIATE_TYPED_TEST_CASE_P(AES256_CFB, CipherTest, AES256_CFB); //CFB mode is not authenticated
|
||||||
INSTANTIATE_TYPED_TEST_CASE_P(AES256_GCM, CipherTest, AES256_GCM);
|
INSTANTIATE_TYPED_TEST_CASE_P(AES256_GCM, CipherTest, AES256_GCM);
|
||||||
INSTANTIATE_TYPED_TEST_CASE_P(AES256_GCM, AuthenticatedCipherTest, AES256_GCM);
|
INSTANTIATE_TYPED_TEST_CASE_P(AES256_GCM, AuthenticatedCipherTest, AES256_GCM);
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
#include "../../../implementations/encrypted/ciphers/AES256_GCM.h"
|
|
||||||
#include "../../../implementations/encrypted/EncryptedBlockStore.h"
|
|
||||||
#include "../../../implementations/testfake/FakeBlockStore.h"
|
|
||||||
#include "../../testutils/BlockStoreTest.h"
|
|
||||||
#include "google/gtest/gtest.h"
|
|
||||||
|
|
||||||
|
|
||||||
using blockstore::BlockStore;
|
|
||||||
using blockstore::encrypted::EncryptedBlockStore;
|
|
||||||
using blockstore::testfake::FakeBlockStore;
|
|
||||||
using blockstore::encrypted::AES256_GCM;
|
|
||||||
|
|
||||||
using std::unique_ptr;
|
|
||||||
using std::make_unique;
|
|
||||||
|
|
||||||
class EncryptedBlockStoreTestFixture: public BlockStoreTestFixture {
|
|
||||||
public:
|
|
||||||
unique_ptr<BlockStore> createBlockStore() override {
|
|
||||||
return make_unique<EncryptedBlockStore<AES256_GCM>>(make_unique<FakeBlockStore>(), AES256_GCM::EncryptionKey::FromString("1491BB4932A389EE14BC7090A272EE5517627CFA147A971A8E6E747E0C772972"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
INSTANTIATE_TYPED_TEST_CASE_P(Encrypted, BlockStoreTest, EncryptedBlockStoreTestFixture);
|
|
||||||
|
|
||||||
//TODO Add specific tests, for example
|
|
||||||
// - loading it with a different encKey doesn't work
|
|
||||||
// - loading it with a different blockstore::Key will fail (because it stores its key in a header)
|
|
||||||
// - when using an authenticated cipher, loading a modified block will fail
|
|
@ -0,0 +1,40 @@
|
|||||||
|
#include "../../../implementations/encrypted/ciphers/AES256_GCM.h"
|
||||||
|
#include "../../../implementations/encrypted/ciphers/AES256_CFB.h"
|
||||||
|
#include "../../../implementations/encrypted/ciphers/Cipher.h"
|
||||||
|
#include "../../../implementations/encrypted/EncryptedBlockStore.h"
|
||||||
|
#include "../../../implementations/testfake/FakeBlockStore.h"
|
||||||
|
#include "../../testutils/BlockStoreTest.h"
|
||||||
|
#include "testutils/FakeAuthenticatedCipher.h"
|
||||||
|
#include "google/gtest/gtest.h"
|
||||||
|
|
||||||
|
using ::testing::Test;
|
||||||
|
|
||||||
|
using blockstore::BlockStore;
|
||||||
|
using blockstore::encrypted::EncryptedBlockStore;
|
||||||
|
using blockstore::testfake::FakeBlockStore;
|
||||||
|
using blockstore::encrypted::AES256_GCM;
|
||||||
|
using blockstore::encrypted::AES256_CFB;
|
||||||
|
|
||||||
|
using std::unique_ptr;
|
||||||
|
using std::make_unique;
|
||||||
|
|
||||||
|
using cpputils::Data;
|
||||||
|
using cpputils::DataFixture;
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
class EncryptedBlockStoreTestFixture: public BlockStoreTestFixture {
|
||||||
|
public:
|
||||||
|
unique_ptr<BlockStore> createBlockStore() override {
|
||||||
|
return make_unique<EncryptedBlockStore<Cipher>>(make_unique<FakeBlockStore>(), createKeyFixture());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static typename Cipher::EncryptionKey createKeyFixture(int seed = 0) {
|
||||||
|
Data data = DataFixture::generate(Cipher::EncryptionKey::BINARY_LENGTH, seed);
|
||||||
|
return Cipher::EncryptionKey::FromBinary(data.data());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
INSTANTIATE_TYPED_TEST_CASE_P(Encrypted_FakeCipher, BlockStoreTest, EncryptedBlockStoreTestFixture<FakeAuthenticatedCipher>);
|
||||||
|
INSTANTIATE_TYPED_TEST_CASE_P(Encrypted_AES256_GCM, BlockStoreTest, EncryptedBlockStoreTestFixture<AES256_GCM>);
|
||||||
|
INSTANTIATE_TYPED_TEST_CASE_P(Encrypted_AES256_CFB, BlockStoreTest, EncryptedBlockStoreTestFixture<AES256_CFB>);
|
@ -0,0 +1,35 @@
|
|||||||
|
#include <google/gtest/gtest.h>
|
||||||
|
#include "testutils/FakeAuthenticatedCipher.h"
|
||||||
|
#include "../../../implementations/encrypted/EncryptedBlockStore.h"
|
||||||
|
#include "../../../implementations/testfake/FakeBlockStore.h"
|
||||||
|
|
||||||
|
using ::testing::Test;
|
||||||
|
|
||||||
|
using std::unique_ptr;
|
||||||
|
using std::make_unique;
|
||||||
|
|
||||||
|
using blockstore::testfake::FakeBlockStore;
|
||||||
|
|
||||||
|
using namespace blockstore::encrypted;
|
||||||
|
|
||||||
|
class EncryptedBlockStoreTest: public Test {
|
||||||
|
public:
|
||||||
|
EncryptedBlockStoreTest(): blockStore(make_unique<EncryptedBlockStore<FakeAuthenticatedCipher>>(make_unique<FakeBlockStore>(), FakeAuthenticatedCipher::Key1())) {}
|
||||||
|
unique_ptr<EncryptedBlockStore<FakeAuthenticatedCipher>> blockStore;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(EncryptedBlockStoreTest, LoadingWithSameKeyWorks) {
|
||||||
|
//TODO implement
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(EncryptedBlockStoreTest, LoadingWithDifferentKeyDoesntWork) {
|
||||||
|
//TODO Implement
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(EncryptedBlockStoreTest, LoadingModifiedBlockFails) {
|
||||||
|
//TODO Implement
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(EncryptedBlockStoreTest, LoadingWithDifferentBlockIdFails) {
|
||||||
|
//TODO loading it with a different blockstore::Key will fail (because it stores its key in a header)
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
#include "FakeAuthenticatedCipher.h"
|
||||||
|
|
||||||
|
constexpr unsigned int FakeKey::BINARY_LENGTH;
|
@ -0,0 +1,102 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef MESSMER_BLOCKSTORE_TEST_IMPLEMENTATIONS_ENCRYPTED_TESTUTILS_FAKEAUTHENTICATEDCIPHER_H_
|
||||||
|
#define MESSMER_BLOCKSTORE_TEST_IMPLEMENTATIONS_ENCRYPTED_TESTUTILS_FAKEAUTHENTICATEDCIPHER_H_
|
||||||
|
|
||||||
|
#include "../../../../implementations/encrypted/ciphers/Cipher.h"
|
||||||
|
#include <messmer/cpp-utils/data/FixedSizeData.h>
|
||||||
|
|
||||||
|
struct FakeKey {
|
||||||
|
FakeKey(uint8_t value_):value(value_) {}
|
||||||
|
static FakeKey CreateRandom() {
|
||||||
|
return FakeKey(rand());
|
||||||
|
}
|
||||||
|
static FakeKey FromBinary(const void *data) {
|
||||||
|
return FakeKey(*(uint8_t*)data);
|
||||||
|
}
|
||||||
|
static constexpr unsigned int BINARY_LENGTH = 1;
|
||||||
|
|
||||||
|
uint8_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is a fake cipher that uses an indeterministic caesar chiffre and a 4-byte parity for a simple authentication mechanism
|
||||||
|
class FakeAuthenticatedCipher {
|
||||||
|
public:
|
||||||
|
BOOST_CONCEPT_ASSERT((blockstore::encrypted::CipherConcept<FakeAuthenticatedCipher>));
|
||||||
|
|
||||||
|
using EncryptionKey = FakeKey;
|
||||||
|
|
||||||
|
static EncryptionKey Key1() {
|
||||||
|
return FakeKey(5);
|
||||||
|
}
|
||||||
|
static EncryptionKey Key2() {
|
||||||
|
return FakeKey(63);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) {
|
||||||
|
return plaintextBlockSize + 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr unsigned int plaintextSize(unsigned int ciphertextBlockSize) {
|
||||||
|
return ciphertextBlockSize - 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cpputils::Data encrypt(const byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) {
|
||||||
|
cpputils::Data result(ciphertextSize(plaintextSize));
|
||||||
|
|
||||||
|
//Add a random IV
|
||||||
|
uint8_t iv = rand();
|
||||||
|
std::memcpy(result.data(), &iv, 1);
|
||||||
|
|
||||||
|
//Use caesar chiffre on plaintext
|
||||||
|
_caesar((byte*)result.data() + 1, plaintext, plaintextSize, encKey.value + iv);
|
||||||
|
|
||||||
|
//Add parity information
|
||||||
|
int32_t parity = _parity((byte*)result.data(), plaintextSize + 1);
|
||||||
|
std::memcpy((byte*)result.data() + plaintextSize + 1, &parity, 4);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boost::optional<cpputils::Data> decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) {
|
||||||
|
//We need at least 5 bytes (iv + parity)
|
||||||
|
if (ciphertextSize < 5) {
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check parity
|
||||||
|
int32_t expectedParity = _parity(ciphertext, plaintextSize(ciphertextSize) + 1);
|
||||||
|
int32_t actualParity = *(int32_t*)(ciphertext + plaintextSize(ciphertextSize) + 1);
|
||||||
|
if (expectedParity != actualParity) {
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Decrypt caesar chiffre from ciphertext
|
||||||
|
int32_t iv = *(int32_t*)ciphertext;
|
||||||
|
cpputils::Data result(plaintextSize(ciphertextSize));
|
||||||
|
_caesar((byte*)result.data(), ciphertext + 1, plaintextSize(ciphertextSize), -(encKey.value+iv));
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int32_t _parity(const byte *data, unsigned int size) {
|
||||||
|
int32_t parity = 34343435; // some init value
|
||||||
|
int32_t *intData = (int32_t*)data;
|
||||||
|
unsigned int intSize = size / sizeof(int32_t);
|
||||||
|
for (unsigned int i = 0; i < intSize; ++i) {
|
||||||
|
parity += intData[i];
|
||||||
|
}
|
||||||
|
unsigned int remainingBytes = size - 4 * intSize;
|
||||||
|
for (unsigned int i = 0; i < remainingBytes; ++i) {
|
||||||
|
parity += (data[4*intSize + i] << (24 - 8*i));
|
||||||
|
}
|
||||||
|
return parity;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _caesar(byte *dst, const byte *src, unsigned int size, uint8_t key) {
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
dst[i] = src[i] + key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user