Factor out encryption algorithm from EncryptedBlockStore
This commit is contained in:
parent
03597b9474
commit
6e50c9d8a5
2
implementations/encrypted/Cipher.cpp
Normal file
2
implementations/encrypted/Cipher.cpp
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#include "Cipher.h"
|
||||||
|
|
26
implementations/encrypted/Cipher.h
Normal file
26
implementations/encrypted/Cipher.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHER_H_
|
||||||
|
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHER_H_
|
||||||
|
|
||||||
|
#include <cryptopp/cryptopp/modes.h>
|
||||||
|
|
||||||
|
namespace blockstore {
|
||||||
|
namespace encrypted {
|
||||||
|
|
||||||
|
class Cipher {
|
||||||
|
public:
|
||||||
|
virtual ~Cipher() {}
|
||||||
|
|
||||||
|
virtual unsigned int ciphertextBlockSize(unsigned int ciphertextBlockSize) const = 0;
|
||||||
|
virtual unsigned int plaintextBlockSize(unsigned int plaintextBlockSize) const = 0;
|
||||||
|
|
||||||
|
virtual void encrypt(const byte *plaintext, unsigned int plaintextSize, byte *ciphertext) const = 0;
|
||||||
|
virtual void decrypt(const byte *ciphertext, byte *plaintext, unsigned int plaintextSize) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -1,91 +1 @@
|
|||||||
#include "EncryptedBlock.h"
|
#include "EncryptedBlock.h"
|
||||||
#include <cryptopp/cryptopp/modes.h>
|
|
||||||
|
|
||||||
#include "../../utils/BlockStoreUtils.h"
|
|
||||||
|
|
||||||
using CryptoPP::CFB_Mode;
|
|
||||||
using CryptoPP::AES;
|
|
||||||
|
|
||||||
using std::make_unique;
|
|
||||||
|
|
||||||
//TODO not only encryption, but also hmac
|
|
||||||
|
|
||||||
namespace blockstore {
|
|
||||||
namespace encrypted {
|
|
||||||
|
|
||||||
constexpr unsigned int EncryptedBlock::IV_SIZE;
|
|
||||||
|
|
||||||
std::unique_ptr<EncryptedBlock> EncryptedBlock::TryCreateNew(BlockStore *baseBlockStore, const Key &key, Data data, const EncryptionKey &encKey) {
|
|
||||||
Data encrypted = _encrypt(data, encKey);
|
|
||||||
auto baseBlock = baseBlockStore->tryCreate(key, std::move(encrypted));
|
|
||||||
if (baseBlock.get() == nullptr) {
|
|
||||||
//TODO Test this code branch
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return make_unique<EncryptedBlock>(std::move(baseBlock), encKey, std::move(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
EncryptedBlock::EncryptedBlock(std::unique_ptr<Block> baseBlock, const EncryptionKey &encKey)
|
|
||||||
:EncryptedBlock(std::move(baseBlock), encKey, Data(USEABLE_BLOCK_SIZE(baseBlock->size()))) {
|
|
||||||
_decryptFromBaseBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
EncryptedBlock::EncryptedBlock(std::unique_ptr<Block> baseBlock, const EncryptionKey &encKey, Data plaintextData)
|
|
||||||
:Block(baseBlock->key()),
|
|
||||||
_baseBlock(std::move(baseBlock)),
|
|
||||||
_plaintextData(std::move(plaintextData)),
|
|
||||||
_encKey(encKey),
|
|
||||||
_dataChanged(false) {
|
|
||||||
}
|
|
||||||
|
|
||||||
EncryptedBlock::~EncryptedBlock() {
|
|
||||||
_encryptToBaseBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
const void *EncryptedBlock::data() const {
|
|
||||||
return _plaintextData.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EncryptedBlock::write(const void *source, uint64_t offset, uint64_t size) {
|
|
||||||
assert(offset <= _plaintextData.size() && offset + size <= _plaintextData.size()); //Also check offset < _data->size() because of possible overflow in the addition
|
|
||||||
std::memcpy((uint8_t*)_plaintextData.data()+offset, source, size);
|
|
||||||
_dataChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EncryptedBlock::flush() {
|
|
||||||
_encryptToBaseBlock();
|
|
||||||
return _baseBlock->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t EncryptedBlock::size() const {
|
|
||||||
return _plaintextData.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EncryptedBlock::_decryptFromBaseBlock() {
|
|
||||||
const byte *iv = (byte*)_baseBlock->data();
|
|
||||||
const byte *data = (byte*)_baseBlock->data() + IV_SIZE;
|
|
||||||
auto decryption = CFB_Mode<AES>::Decryption((byte*)_encKey.data(), EncryptionKey::BINARY_LENGTH, iv);
|
|
||||||
decryption.ProcessData((byte*)_plaintextData.data(), data, _plaintextData.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EncryptedBlock::_encryptToBaseBlock() {
|
|
||||||
if (_dataChanged) {
|
|
||||||
Data encrypted = _encrypt(_plaintextData, _encKey);
|
|
||||||
_baseBlock->write(encrypted.data(), 0, encrypted.size());
|
|
||||||
_dataChanged = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Data EncryptedBlock::_encrypt(const Data &plaintext, const EncryptionKey &encKey) {
|
|
||||||
FixedSizeData<IV_SIZE> iv = FixedSizeData<IV_SIZE>::CreateRandom();
|
|
||||||
auto encryption = CFB_Mode<AES>::Encryption(encKey.data(), EncryptionKey::BINARY_LENGTH, iv.data());
|
|
||||||
//TODO More performance when not using "Data encrypted" object, but encrypting directly to a target that was specified via a parameter using a specialized CryptoPP sink
|
|
||||||
Data encrypted(IV_SIZE + plaintext.size());
|
|
||||||
std::memcpy(encrypted.data(), iv.data(), IV_SIZE);
|
|
||||||
encryption.ProcessData((byte*)encrypted.data() + IV_SIZE, (byte*)plaintext.data(), plaintext.size());
|
|
||||||
return encrypted;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#define BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_ENCRYPTEDBLOCK_H_
|
#define BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_ENCRYPTEDBLOCK_H_
|
||||||
|
|
||||||
#include "../../interface/Block.h"
|
#include "../../interface/Block.h"
|
||||||
#include "EncryptionKey.h"
|
#include "Cipher.h"
|
||||||
#include "../../utils/Data.h"
|
#include "../../utils/Data.h"
|
||||||
#include "../../interface/BlockStore.h"
|
#include "../../interface/BlockStore.h"
|
||||||
|
|
||||||
@ -12,16 +12,19 @@
|
|||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
namespace encrypted {
|
namespace encrypted {
|
||||||
class EncryptedBlockStore;
|
template<class Cipher> class EncryptedBlockStore;
|
||||||
|
|
||||||
|
//TODO not only encryption, but also hmac
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
class EncryptedBlock: public Block {
|
class EncryptedBlock: public Block {
|
||||||
public:
|
public:
|
||||||
//TODO Storing key twice (in parent class and in object pointed to). Once would be enough.
|
static std::unique_ptr<EncryptedBlock> TryCreateNew(BlockStore *baseBlockStore, const Key &key, Data data, const typename Cipher::EncryptionKey &encKey);
|
||||||
EncryptedBlock(std::unique_ptr<Block> baseBlock, const EncryptionKey &encKey);
|
|
||||||
EncryptedBlock(std::unique_ptr<Block> baseBlock, const EncryptionKey &encKey, Data plaintextData);
|
|
||||||
virtual ~EncryptedBlock();
|
|
||||||
|
|
||||||
static std::unique_ptr<EncryptedBlock> TryCreateNew(BlockStore *baseBlockStore, const Key &key, Data data, const EncryptionKey &encKey);
|
//TODO Storing key twice (in parent class and in object pointed to). Once would be enough.
|
||||||
|
EncryptedBlock(std::unique_ptr<Block> baseBlock, const typename Cipher::EncryptionKey &key);
|
||||||
|
EncryptedBlock(std::unique_ptr<Block> baseBlock, const typename Cipher::EncryptionKey &key, Data plaintextData);
|
||||||
|
virtual ~EncryptedBlock();
|
||||||
|
|
||||||
const void *data() const override;
|
const void *data() const override;
|
||||||
void write(const void *source, uint64_t offset, uint64_t size) override;
|
void write(const void *source, uint64_t offset, uint64_t size) override;
|
||||||
@ -29,33 +32,99 @@ public:
|
|||||||
|
|
||||||
size_t size() const override;
|
size_t size() const override;
|
||||||
|
|
||||||
static constexpr unsigned int BASE_BLOCK_SIZE(unsigned int useableBlockSize) {
|
std::unique_ptr<Block> releaseBlock();
|
||||||
return useableBlockSize + IV_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr unsigned int USEABLE_BLOCK_SIZE(unsigned int baseBlockSize) {
|
|
||||||
return baseBlockSize - IV_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Block> _baseBlock;
|
std::unique_ptr<Block> _baseBlock;
|
||||||
Data _plaintextData;
|
Data _plaintextData;
|
||||||
EncryptionKey _encKey;
|
typename Cipher::EncryptionKey _encKey;
|
||||||
bool _dataChanged;
|
bool _dataChanged;
|
||||||
|
|
||||||
static constexpr unsigned int IV_SIZE = CryptoPP::AES::BLOCKSIZE;
|
|
||||||
|
|
||||||
byte *baseBlockIV();
|
|
||||||
byte *baseBlockData();
|
|
||||||
|
|
||||||
void _encryptToBaseBlock();
|
void _encryptToBaseBlock();
|
||||||
void _decryptFromBaseBlock();
|
void _decryptFromBaseBlock();
|
||||||
|
|
||||||
static Data _encrypt(const Data &plaintext, const EncryptionKey &encKey);
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(EncryptedBlock);
|
DISALLOW_COPY_AND_ASSIGN(EncryptedBlock);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
std::unique_ptr<EncryptedBlock<Cipher>> EncryptedBlock<Cipher>::TryCreateNew(BlockStore *baseBlockStore, const Key &key, Data data, const typename Cipher::EncryptionKey &encKey) {
|
||||||
|
Data encrypted(Cipher::ciphertextSize(data.size()));
|
||||||
|
Cipher::encrypt((byte*)data.data(), data.size(), (byte*)encrypted.data(), encKey);
|
||||||
|
auto baseBlock = baseBlockStore->tryCreate(key, std::move(encrypted));
|
||||||
|
if (baseBlock.get() == nullptr) {
|
||||||
|
//TODO Test this code branch
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_unique<EncryptedBlock>(std::move(baseBlock), encKey, std::move(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
EncryptedBlock<Cipher>::EncryptedBlock(std::unique_ptr<Block> baseBlock, const typename Cipher::EncryptionKey &encKey)
|
||||||
|
:EncryptedBlock(std::move(baseBlock), encKey, Data(Cipher::plaintextSize(baseBlock->size()))) {
|
||||||
|
_decryptFromBaseBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
EncryptedBlock<Cipher>::EncryptedBlock(std::unique_ptr<Block> baseBlock, const typename Cipher::EncryptionKey &encKey, Data plaintextData)
|
||||||
|
:Block(baseBlock->key()),
|
||||||
|
_baseBlock(std::move(baseBlock)),
|
||||||
|
_plaintextData(std::move(plaintextData)),
|
||||||
|
_encKey(encKey),
|
||||||
|
_dataChanged(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
EncryptedBlock<Cipher>::~EncryptedBlock() {
|
||||||
|
_encryptToBaseBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
const void *EncryptedBlock<Cipher>::data() const {
|
||||||
|
return _plaintextData.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
void EncryptedBlock<Cipher>::write(const void *source, uint64_t offset, uint64_t size) {
|
||||||
|
assert(offset <= _plaintextData.size() && offset + size <= _plaintextData.size()); //Also check offset < _data->size() because of possible overflow in the addition
|
||||||
|
std::memcpy((uint8_t*)_plaintextData.data()+offset, source, size);
|
||||||
|
_dataChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
void EncryptedBlock<Cipher>::flush() {
|
||||||
|
_encryptToBaseBlock();
|
||||||
|
return _baseBlock->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
size_t EncryptedBlock<Cipher>::size() const {
|
||||||
|
return _plaintextData.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
void EncryptedBlock<Cipher>::_decryptFromBaseBlock() {
|
||||||
|
//TODO Change BlockStore so we can read their "class Data" objects instead of "void *data()", and then we can change the Cipher interface to take Data objects instead of "byte *" + size
|
||||||
|
Cipher::decrypt((byte*)_baseBlock->data(), (byte*)_plaintextData.data(), _plaintextData.size(), _encKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
void EncryptedBlock<Cipher>::_encryptToBaseBlock() {
|
||||||
|
if (_dataChanged) {
|
||||||
|
Data encrypted(Cipher::ciphertextSize(_plaintextData.size()));
|
||||||
|
Cipher::encrypt((byte*)_plaintextData.data(), _plaintextData.size(), (byte*)encrypted.data(), _encKey);
|
||||||
|
_baseBlock->write(encrypted.data(), 0, encrypted.size());
|
||||||
|
_dataChanged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
std::unique_ptr<Block> EncryptedBlock<Cipher>::releaseBlock() {
|
||||||
|
return std::move(_baseBlock);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,42 +1 @@
|
|||||||
#include "EncryptedBlockStore.h"
|
#include "EncryptedBlockStore.h"
|
||||||
#include "EncryptedBlock.h"
|
|
||||||
#include <messmer/cpp-utils/pointer.h>
|
|
||||||
#include "../../utils/BlockStoreUtils.h"
|
|
||||||
|
|
||||||
using std::unique_ptr;
|
|
||||||
using std::make_unique;
|
|
||||||
|
|
||||||
namespace blockstore {
|
|
||||||
namespace encrypted {
|
|
||||||
|
|
||||||
EncryptedBlockStore::EncryptedBlockStore(unique_ptr<BlockStore> baseBlockStore, const EncryptionKey &encKey)
|
|
||||||
: _baseBlockStore(std::move(baseBlockStore)), _encKey(encKey) {
|
|
||||||
}
|
|
||||||
|
|
||||||
Key EncryptedBlockStore::createKey() {
|
|
||||||
return _baseBlockStore->createKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
unique_ptr<Block> EncryptedBlockStore::tryCreate(const Key &key, Data data) {
|
|
||||||
return EncryptedBlock::TryCreateNew(_baseBlockStore.get(), key, std::move(data), _encKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
unique_ptr<Block> EncryptedBlockStore::load(const Key &key) {
|
|
||||||
auto block = _baseBlockStore->load(key);
|
|
||||||
if (block.get() == nullptr) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return make_unique<EncryptedBlock>(std::move(block), _encKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EncryptedBlockStore::remove(unique_ptr<Block> block) {
|
|
||||||
return _baseBlockStore->remove(std::move(block));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t EncryptedBlockStore::numBlocks() const {
|
|
||||||
return _baseBlockStore->numBlocks();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -4,14 +4,17 @@
|
|||||||
|
|
||||||
#include "../../interface/BlockStore.h"
|
#include "../../interface/BlockStore.h"
|
||||||
#include <messmer/cpp-utils/macros.h>
|
#include <messmer/cpp-utils/macros.h>
|
||||||
#include "EncryptionKey.h"
|
#include <messmer/cpp-utils/pointer.h>
|
||||||
|
#include "Cipher.h"
|
||||||
|
#include "EncryptedBlock.h"
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
namespace encrypted {
|
namespace encrypted {
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
class EncryptedBlockStore: public BlockStore {
|
class EncryptedBlockStore: public BlockStore {
|
||||||
public:
|
public:
|
||||||
EncryptedBlockStore(std::unique_ptr<BlockStore> baseBlockStore, const EncryptionKey &encKey);
|
EncryptedBlockStore(std::unique_ptr<BlockStore> baseBlockStore, const typename Cipher::EncryptionKey &encKey);
|
||||||
|
|
||||||
Key createKey() override;
|
Key createKey() override;
|
||||||
std::unique_ptr<Block> tryCreate(const Key &key, Data data) override;
|
std::unique_ptr<Block> tryCreate(const Key &key, Data data) override;
|
||||||
@ -21,11 +24,48 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<BlockStore> _baseBlockStore;
|
std::unique_ptr<BlockStore> _baseBlockStore;
|
||||||
EncryptionKey _encKey;
|
typename Cipher::EncryptionKey _encKey;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(EncryptedBlockStore);
|
DISALLOW_COPY_AND_ASSIGN(EncryptedBlockStore);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
EncryptedBlockStore<Cipher>::EncryptedBlockStore(std::unique_ptr<BlockStore> baseBlockStore, const typename Cipher::EncryptionKey &encKey)
|
||||||
|
: _baseBlockStore(std::move(baseBlockStore)), _encKey(encKey) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
Key EncryptedBlockStore<Cipher>::createKey() {
|
||||||
|
return _baseBlockStore->createKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
std::unique_ptr<Block> EncryptedBlockStore<Cipher>::tryCreate(const Key &key, Data data) {
|
||||||
|
return EncryptedBlock<Cipher>::TryCreateNew(_baseBlockStore.get(), key, std::move(data), _encKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
std::unique_ptr<Block> EncryptedBlockStore<Cipher>::load(const Key &key) {
|
||||||
|
auto block = _baseBlockStore->load(key);
|
||||||
|
if (block.get() == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return std::make_unique<EncryptedBlock<Cipher>>(std::move(block), _encKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
void EncryptedBlockStore<Cipher>::remove(std::unique_ptr<Block> block) {
|
||||||
|
auto baseBlock = cpputils::dynamic_pointer_move<EncryptedBlock<Cipher>>(block)->releaseBlock();
|
||||||
|
return _baseBlockStore->remove(std::move(baseBlock));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Cipher>
|
||||||
|
uint64_t EncryptedBlockStore<Cipher>::numBlocks() const {
|
||||||
|
return _baseBlockStore->numBlocks();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
#include "EncryptionKey.h"
|
|
@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_ENCRYPTIONKEY_H_
|
|
||||||
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_ENCRYPTIONKEY_H_
|
|
||||||
|
|
||||||
#include "../../utils/FixedSizeData.h"
|
|
||||||
|
|
||||||
namespace blockstore {
|
|
||||||
namespace encrypted {
|
|
||||||
|
|
||||||
using EncryptionKey = FixedSizeData<CryptoPP::AES::MAX_KEYLENGTH>;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
27
implementations/encrypted/ciphers/AES256_CFB.cpp
Normal file
27
implementations/encrypted/ciphers/AES256_CFB.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include <cryptopp/cryptopp/modes.h>
|
||||||
|
#include "AES256_CFB.h"
|
||||||
|
|
||||||
|
using CryptoPP::CFB_Mode;
|
||||||
|
using CryptoPP::AES;
|
||||||
|
|
||||||
|
namespace blockstore {
|
||||||
|
namespace encrypted {
|
||||||
|
|
||||||
|
constexpr unsigned int AES256_CFB::IV_SIZE;
|
||||||
|
|
||||||
|
void AES256_CFB::encrypt(const byte *plaintext, unsigned int plaintextSize, byte *ciphertext, const EncryptionKey &encKey) {
|
||||||
|
FixedSizeData<IV_SIZE> iv = FixedSizeData<IV_SIZE>::CreateRandom();
|
||||||
|
auto encryption = CFB_Mode<AES>::Encryption(encKey.data(), encKey.BINARY_LENGTH, iv.data());
|
||||||
|
std::memcpy(ciphertext, iv.data(), IV_SIZE);
|
||||||
|
encryption.ProcessData(ciphertext + IV_SIZE, plaintext, plaintextSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AES256_CFB::decrypt(const byte *ciphertext, byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) {
|
||||||
|
const byte *iv = ciphertext;
|
||||||
|
const byte *data = ciphertext + IV_SIZE;
|
||||||
|
auto decryption = CFB_Mode<AES>::Decryption((byte*)encKey.data(), encKey.BINARY_LENGTH, iv);
|
||||||
|
decryption.ProcessData(plaintext, data, plaintextSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
36
implementations/encrypted/ciphers/AES256_CFB.h
Normal file
36
implementations/encrypted/ciphers/AES256_CFB.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_AES256_CFB_H_
|
||||||
|
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_AES256_CFB_H_
|
||||||
|
|
||||||
|
#include "../../../utils/FixedSizeData.h"
|
||||||
|
#include <cryptopp/cryptopp/aes.h>
|
||||||
|
|
||||||
|
namespace blockstore {
|
||||||
|
namespace encrypted {
|
||||||
|
|
||||||
|
class AES256_CFB {
|
||||||
|
public:
|
||||||
|
using EncryptionKey = FixedSizeData<32>;
|
||||||
|
static_assert(32 == CryptoPP::AES::MAX_KEYLENGTH, "If AES offered larger keys, we should offer a variant with it");
|
||||||
|
|
||||||
|
AES256_CFB(const EncryptionKey &key);
|
||||||
|
|
||||||
|
static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) {
|
||||||
|
return plaintextBlockSize + IV_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr unsigned int plaintextSize(unsigned int ciphertextBlockSize) {
|
||||||
|
return ciphertextBlockSize - IV_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void encrypt(const byte *plaintext, unsigned int plaintextSize, byte *ciphertext, const EncryptionKey &key);
|
||||||
|
static void decrypt(const byte *ciphertext, byte *plaintext, unsigned int plaintextSize, const EncryptionKey &key);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr unsigned int IV_SIZE = CryptoPP::AES::BLOCKSIZE;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "../../../implementations/encrypted/ciphers/AES256_CFB.h"
|
||||||
#include "../../../implementations/encrypted/EncryptedBlockStore.h"
|
#include "../../../implementations/encrypted/EncryptedBlockStore.h"
|
||||||
#include "../../../implementations/testfake/FakeBlockStore.h"
|
#include "../../../implementations/testfake/FakeBlockStore.h"
|
||||||
#include "../../testutils/BlockStoreTest.h"
|
#include "../../testutils/BlockStoreTest.h"
|
||||||
@ -6,8 +7,8 @@
|
|||||||
|
|
||||||
using blockstore::BlockStore;
|
using blockstore::BlockStore;
|
||||||
using blockstore::encrypted::EncryptedBlockStore;
|
using blockstore::encrypted::EncryptedBlockStore;
|
||||||
using blockstore::encrypted::EncryptionKey;
|
|
||||||
using blockstore::testfake::FakeBlockStore;
|
using blockstore::testfake::FakeBlockStore;
|
||||||
|
using blockstore::encrypted::AES256_CFB;
|
||||||
|
|
||||||
using std::unique_ptr;
|
using std::unique_ptr;
|
||||||
using std::make_unique;
|
using std::make_unique;
|
||||||
@ -15,7 +16,7 @@ using std::make_unique;
|
|||||||
class EncryptedBlockStoreTestFixture: public BlockStoreTestFixture {
|
class EncryptedBlockStoreTestFixture: public BlockStoreTestFixture {
|
||||||
public:
|
public:
|
||||||
unique_ptr<BlockStore> createBlockStore() override {
|
unique_ptr<BlockStore> createBlockStore() override {
|
||||||
return make_unique<EncryptedBlockStore>(make_unique<FakeBlockStore>(), EncryptionKey::FromString("1491BB4932A389EE14BC7090A272EE5517627CFA147A971A8E6E747E0C772972"));
|
return make_unique<EncryptedBlockStore<AES256_CFB>>(make_unique<FakeBlockStore>(), AES256_CFB::EncryptionKey::FromString("1491BB4932A389EE14BC7090A272EE5517627CFA147A971A8E6E747E0C772972"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
|
|
||||||
template<int SIZE>
|
template<unsigned int SIZE>
|
||||||
class FixedSizeData {
|
class FixedSizeData {
|
||||||
public:
|
public:
|
||||||
//Non-virtual destructor because we want objects to be small
|
//Non-virtual destructor because we want objects to be small
|
||||||
@ -35,28 +35,28 @@ private:
|
|||||||
unsigned char _data[BINARY_LENGTH];
|
unsigned char _data[BINARY_LENGTH];
|
||||||
};
|
};
|
||||||
|
|
||||||
template<int SIZE> bool operator==(const FixedSizeData<SIZE> &lhs, const FixedSizeData<SIZE> &rhs);
|
template<unsigned int SIZE> bool operator==(const FixedSizeData<SIZE> &lhs, const FixedSizeData<SIZE> &rhs);
|
||||||
template<int SIZE> bool operator!=(const FixedSizeData<SIZE> &lhs, const FixedSizeData<SIZE> &rhs);
|
template<unsigned int SIZE> bool operator!=(const FixedSizeData<SIZE> &lhs, const FixedSizeData<SIZE> &rhs);
|
||||||
|
|
||||||
// ----- Implementation -----
|
// ----- Implementation -----
|
||||||
|
|
||||||
template<int SIZE> constexpr unsigned int FixedSizeData<SIZE>::BINARY_LENGTH;
|
template<unsigned int SIZE> constexpr unsigned int FixedSizeData<SIZE>::BINARY_LENGTH;
|
||||||
template<int SIZE> constexpr unsigned int FixedSizeData<SIZE>::STRING_LENGTH;
|
template<unsigned int SIZE> constexpr unsigned int FixedSizeData<SIZE>::STRING_LENGTH;
|
||||||
|
|
||||||
template<int SIZE>
|
template<unsigned int SIZE>
|
||||||
CryptoPP::AutoSeededRandomPool &FixedSizeData<SIZE>::RandomPool() {
|
CryptoPP::AutoSeededRandomPool &FixedSizeData<SIZE>::RandomPool() {
|
||||||
static CryptoPP::AutoSeededRandomPool singleton;
|
static CryptoPP::AutoSeededRandomPool singleton;
|
||||||
return singleton;
|
return singleton;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int SIZE>
|
template<unsigned int SIZE>
|
||||||
FixedSizeData<SIZE> FixedSizeData<SIZE>::CreateRandom() {
|
FixedSizeData<SIZE> FixedSizeData<SIZE>::CreateRandom() {
|
||||||
FixedSizeData<SIZE> result;
|
FixedSizeData<SIZE> result;
|
||||||
RandomPool().GenerateBlock(result._data, BINARY_LENGTH);
|
RandomPool().GenerateBlock(result._data, BINARY_LENGTH);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int SIZE>
|
template<unsigned int SIZE>
|
||||||
FixedSizeData<SIZE> FixedSizeData<SIZE>::FromString(const std::string &data) {
|
FixedSizeData<SIZE> FixedSizeData<SIZE>::FromString(const std::string &data) {
|
||||||
assert(data.size() == STRING_LENGTH);
|
assert(data.size() == STRING_LENGTH);
|
||||||
FixedSizeData<SIZE> result;
|
FixedSizeData<SIZE> result;
|
||||||
@ -68,7 +68,7 @@ FixedSizeData<SIZE> FixedSizeData<SIZE>::FromString(const std::string &data) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int SIZE>
|
template<unsigned int SIZE>
|
||||||
std::string FixedSizeData<SIZE>::ToString() const {
|
std::string FixedSizeData<SIZE>::ToString() const {
|
||||||
std::string result;
|
std::string result;
|
||||||
CryptoPP::ArraySource(_data, BINARY_LENGTH, true,
|
CryptoPP::ArraySource(_data, BINARY_LENGTH, true,
|
||||||
@ -80,29 +80,29 @@ std::string FixedSizeData<SIZE>::ToString() const {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int SIZE>
|
template<unsigned int SIZE>
|
||||||
const unsigned char *FixedSizeData<SIZE>::data() const {
|
const unsigned char *FixedSizeData<SIZE>::data() const {
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int SIZE>
|
template<unsigned int SIZE>
|
||||||
void FixedSizeData<SIZE>::ToBinary(void *target) const {
|
void FixedSizeData<SIZE>::ToBinary(void *target) const {
|
||||||
std::memcpy(target, _data, BINARY_LENGTH);
|
std::memcpy(target, _data, BINARY_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int SIZE>
|
template<unsigned int SIZE>
|
||||||
FixedSizeData<SIZE> FixedSizeData<SIZE>::FromBinary(const void *source) {
|
FixedSizeData<SIZE> FixedSizeData<SIZE>::FromBinary(const void *source) {
|
||||||
FixedSizeData<SIZE> result;
|
FixedSizeData<SIZE> result;
|
||||||
std::memcpy(result._data, source, BINARY_LENGTH);
|
std::memcpy(result._data, source, BINARY_LENGTH);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int SIZE>
|
template<unsigned int SIZE>
|
||||||
bool operator==(const FixedSizeData<SIZE> &lhs, const FixedSizeData<SIZE> &rhs) {
|
bool operator==(const FixedSizeData<SIZE> &lhs, const FixedSizeData<SIZE> &rhs) {
|
||||||
return 0 == std::memcmp(lhs.data(), rhs.data(), FixedSizeData<SIZE>::BINARY_LENGTH);
|
return 0 == std::memcmp(lhs.data(), rhs.data(), FixedSizeData<SIZE>::BINARY_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int SIZE>
|
template<unsigned int SIZE>
|
||||||
bool operator!=(const FixedSizeData<SIZE> &lhs, const FixedSizeData<SIZE> &rhs) {
|
bool operator!=(const FixedSizeData<SIZE> &lhs, const FixedSizeData<SIZE> &rhs) {
|
||||||
return !operator==(lhs, rhs);
|
return !operator==(lhs, rhs);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user