From 2d3f329b6a26399583e5dd98114220eb7d077d78 Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Sat, 6 Dec 2014 11:22:34 +0100 Subject: [PATCH] Block-Keys are created randomly --- .../implementations/ondisk/CMakeLists.txt | 4 +- .../ondisk/OnDiskBlobStore.cpp | 28 +++++++++- .../implementations/ondisk/OnDiskBlobStore.h | 10 +++- .../ondisk/RandomKeyGenerator.cpp | 55 +++++++++++++++++++ .../ondisk/RandomKeyGenerator.h | 41 ++++++++++++++ src/blobstore/interface/BlobStore.h | 2 +- .../ondisk/RandomKeyGeneratorTest.cpp | 20 +++++++ 7 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 src/blobstore/implementations/ondisk/RandomKeyGenerator.cpp create mode 100644 src/blobstore/implementations/ondisk/RandomKeyGenerator.h create mode 100644 src/test/blobstore/ondisk/RandomKeyGeneratorTest.cpp diff --git a/src/blobstore/implementations/ondisk/CMakeLists.txt b/src/blobstore/implementations/ondisk/CMakeLists.txt index 53ef89f8..8923c56d 100644 --- a/src/blobstore/implementations/ondisk/CMakeLists.txt +++ b/src/blobstore/implementations/ondisk/CMakeLists.txt @@ -1,3 +1,3 @@ -add_library(blobstore_ondisk Data.cpp OnDiskBlob.cpp OnDiskBlobStore.cpp FileAlreadyExistsException.cpp FileDoesntExistException.cpp) +add_library(blobstore_ondisk Data.cpp OnDiskBlob.cpp OnDiskBlobStore.cpp RandomKeyGenerator.cpp FileAlreadyExistsException.cpp FileDoesntExistException.cpp) -target_link_libraries(blobstore_ondisk boost_filesystem boost_system) +target_link_libraries(blobstore_ondisk boost_filesystem boost_system cryptopp) diff --git a/src/blobstore/implementations/ondisk/OnDiskBlobStore.cpp b/src/blobstore/implementations/ondisk/OnDiskBlobStore.cpp index ee306cda..386f09d1 100644 --- a/src/blobstore/implementations/ondisk/OnDiskBlobStore.cpp +++ b/src/blobstore/implementations/ondisk/OnDiskBlobStore.cpp @@ -1,23 +1,45 @@ #include "OnDiskBlobStore.h" #include "OnDiskBlob.h" +#include "RandomKeyGenerator.h" using std::unique_ptr; +using std::string; +using std::mutex; +using std::lock_guard; + +namespace bf = boost::filesystem; namespace blobstore { namespace ondisk { OnDiskBlobStore::OnDiskBlobStore(const boost::filesystem::path &rootdir) - : _rootdir(rootdir) {} + : _rootdir(rootdir), _generate_key_mutex() {} -BlobStore::BlobWithKey OnDiskBlobStore::create(const std::string &key, size_t size) { +BlobStore::BlobWithKey OnDiskBlobStore::create(size_t size) { + std::string key = _generateKey(); auto file_path = _rootdir / key; auto blob = OnDiskBlob::CreateOnDisk(file_path, size); return BlobStore::BlobWithKey(key, std::move(blob)); } -unique_ptr OnDiskBlobStore::load(const std::string &key) { +string OnDiskBlobStore::_generateKey() { + lock_guard lock(_generate_key_mutex); + + string key; + do { + key = _generateRandomKey(); + } while (bf::exists(_rootdir / key)); + + return key; +} + +string OnDiskBlobStore::_generateRandomKey() { + return RandomKeyGenerator::singleton().create(); +} + +unique_ptr OnDiskBlobStore::load(const string &key) { auto file_path = _rootdir / key; return OnDiskBlob::LoadFromDisk(file_path); } diff --git a/src/blobstore/implementations/ondisk/OnDiskBlobStore.h b/src/blobstore/implementations/ondisk/OnDiskBlobStore.h index 0764bdd2..14f6cfb8 100644 --- a/src/blobstore/implementations/ondisk/OnDiskBlobStore.h +++ b/src/blobstore/implementations/ondisk/OnDiskBlobStore.h @@ -4,10 +4,12 @@ #include "blobstore/interface/BlobStore.h" -#include +#include #include "fspp/utils/macros.h" +#include + namespace blobstore { namespace ondisk { class OnDiskBlob; @@ -16,12 +18,16 @@ class OnDiskBlobStore: public BlobStore { public: OnDiskBlobStore(const boost::filesystem::path &rootdir); - BlobWithKey create(const std::string &key, size_t size) override; + BlobWithKey create(size_t size) override; std::unique_ptr load(const std::string &key) override; private: + std::string _generateKey(); + std::string _generateRandomKey(); const boost::filesystem::path _rootdir; + std::mutex _generate_key_mutex; + DISALLOW_COPY_AND_ASSIGN(OnDiskBlobStore); }; diff --git a/src/blobstore/implementations/ondisk/RandomKeyGenerator.cpp b/src/blobstore/implementations/ondisk/RandomKeyGenerator.cpp new file mode 100644 index 00000000..a3873862 --- /dev/null +++ b/src/blobstore/implementations/ondisk/RandomKeyGenerator.cpp @@ -0,0 +1,55 @@ +#include + +using std::string; + +#include +#include + +using CryptoPP::AutoSeededRandomPool; +using CryptoPP::ArraySource; +using CryptoPP::StringSink; +using CryptoPP::HexEncoder; + +using std::make_unique; + +namespace blobstore { +namespace ondisk { + +constexpr unsigned int RandomKeyGenerator::KEYLENGTH_ENTROPY; +constexpr unsigned int RandomKeyGenerator::KEYLENGTH; + +namespace { +string encodeKeyToHex(const byte *data); +} + +RandomKeyGenerator::RandomKeyGenerator() +: _randomPool(make_unique()) { +} + +RandomKeyGenerator::~RandomKeyGenerator() { +} + +RandomKeyGenerator &RandomKeyGenerator::singleton() { + static RandomKeyGenerator singleton; + return singleton; +} + +string RandomKeyGenerator::create() { + byte key[KEYLENGTH_ENTROPY]; + _randomPool->GenerateBlock(key, KEYLENGTH_ENTROPY); + return encodeKeyToHex(key); +} + +namespace { +string encodeKeyToHex(const byte *data) { + string result; + ArraySource(data, RandomKeyGenerator::KEYLENGTH_ENTROPY, true, + new HexEncoder(new StringSink(result)) + ); + assert(result.size() == RandomKeyGenerator::KEYLENGTH); + return result; +} +} + +} /* namespace ondisk */ +} /* namespace blobstore */ diff --git a/src/blobstore/implementations/ondisk/RandomKeyGenerator.h b/src/blobstore/implementations/ondisk/RandomKeyGenerator.h new file mode 100644 index 00000000..0e331d16 --- /dev/null +++ b/src/blobstore/implementations/ondisk/RandomKeyGenerator.h @@ -0,0 +1,41 @@ +#pragma once +#ifndef BLOBSTORE_IMPLEMENTATIONS_ONDISK_RANDOMKEYGENERATOR_H_ +#define BLOBSTORE_IMPLEMENTATIONS_ONDISK_RANDOMKEYGENERATOR_H_ + +#include "Data.h" + +#include "fspp/utils/macros.h" +#include + +namespace CryptoPP { +class AutoSeededRandomPool; +} + +namespace blobstore { +namespace ondisk { + +// Creates random keys for use as block access handles. +// A key here is NOT a key for encryption, but a key as used in key->value mappings ("access handle for a block"). +class RandomKeyGenerator { +public: + virtual ~RandomKeyGenerator(); + + static constexpr unsigned int KEYLENGTH_ENTROPY = 16; // random bytes in the key + static constexpr unsigned int KEYLENGTH = KEYLENGTH_ENTROPY * 2; + + static RandomKeyGenerator &singleton(); + + std::string create(); + +private: + RandomKeyGenerator(); + + std::unique_ptr _randomPool; + + DISALLOW_COPY_AND_ASSIGN(RandomKeyGenerator); +}; + +} /* namespace ondisk */ +} /* namespace blobstore */ + +#endif diff --git a/src/blobstore/interface/BlobStore.h b/src/blobstore/interface/BlobStore.h index 16d4f9dc..c5af9d61 100644 --- a/src/blobstore/interface/BlobStore.h +++ b/src/blobstore/interface/BlobStore.h @@ -22,7 +22,7 @@ public: std::unique_ptr blob; }; - virtual BlobWithKey create(const std::string &key, size_t size) = 0; + virtual BlobWithKey create(size_t size) = 0; virtual std::unique_ptr load(const std::string &key) = 0; //TODO Needed for performance? Or is deleting loaded blobs enough? //virtual void remove(const std::string &key) = 0; diff --git a/src/test/blobstore/ondisk/RandomKeyGeneratorTest.cpp b/src/test/blobstore/ondisk/RandomKeyGeneratorTest.cpp new file mode 100644 index 00000000..96d7bbc6 --- /dev/null +++ b/src/test/blobstore/ondisk/RandomKeyGeneratorTest.cpp @@ -0,0 +1,20 @@ +#include "gtest/gtest.h" + +#include "blobstore/implementations/ondisk/RandomKeyGenerator.h" + +using ::testing::Test; + +using std::string; + +using namespace blobstore::ondisk; + +class RandomKeyGeneratorTest: public Test {}; + +TEST_F(RandomKeyGeneratorTest, RunsWithoutCrashes) { + string result = RandomKeyGenerator::singleton().create(); +} + +TEST_F(RandomKeyGeneratorTest, KeySizeIsAsSpecified) { + string result = RandomKeyGenerator::singleton().create(); + EXPECT_EQ(RandomKeyGenerator::KEYLENGTH, result.size()); +}