diff --git a/GCryptCLI/include/DataIngestionLayer.h b/GCryptCLI/include/DataIngestionLayer.h index 53338b7..9b77032 100644 --- a/GCryptCLI/include/DataIngestionLayer.h +++ b/GCryptCLI/include/DataIngestionLayer.h @@ -49,7 +49,7 @@ namespace IO { // Indicates whether EOF has been reached static bool reachedEof; - // Indicates whether this class is initialized + // Indicates whether this class has been initialized static bool initialized; // All read blocks, that haven't been given out yet diff --git a/GCryptCLI/include/DataOutputLayer.h b/GCryptCLI/include/DataOutputLayer.h new file mode 100644 index 0000000..42fbd5a --- /dev/null +++ b/GCryptCLI/include/DataOutputLayer.h @@ -0,0 +1,60 @@ +#ifndef GCRYPTCLI_DATAOUTPUTLAYER_H +#define GCRYPTCLI_DATAOUTPUTLAYER_H + +#include +#include +#include +#include "Configuration.h" + +using namespace Leonetienne::GCrypt; + +namespace IO { + + // This class is used to read in data. + class DataOutputLayer { + public: + //! Will initialize the output + static void Init(); + + //! Will destruct the output layer (like, closing file handles) + static void Destruct(); + + //! Will queue a block for writing + static void Enqueue(const Block& block); + + //! Will attempt to write the next block + static void WriteBlock(); + + //! Indicates that no more blocks will be enqueued + static void ReachedEOF(); + + //! Returns true, if all blocks have been written, and an EOF signal as been received + static bool IsFinished(); + + private: + static std::ostream* out; + + // The format to write data in + static Configuration::IOBASE_FORMAT outFormat; + + // We have to hold on to a reference to a filestream, + // even if we're always just reading from in. + // We still have to CLOSE the file handle afterwards! + static std::ofstream ofs; + + // Indicates whether EOF has been reached + static bool reachedEof; + + // Indicates whether this class has been initialized + static bool initialized; + + // All blocks, that haven't been written yet + static std::queue blocks; + + //! No instanciation >:( + DataOutputLayer() {}; + }; +} + +#endif + diff --git a/GCryptCLI/include/ModuleEncryption.h b/GCryptCLI/include/ModuleEncryption.h new file mode 100644 index 0000000..069a65a --- /dev/null +++ b/GCryptCLI/include/ModuleEncryption.h @@ -0,0 +1,18 @@ +#ifndef GCRYPTCLI_MODULE_ENCRYPTION_H +#define GCRYPTCLI_MODULE_ENCRYPTION_H + +namespace Module { + //! This module will encrypt supplied input + class Encryption { + public: + //! Will run the module + static void Run(); + + private: + // No instanciation! >:( + Encryption() {}; + }; +} + +#endif + diff --git a/GCryptCLI/src/DataOutputLayer.cpp b/GCryptCLI/src/DataOutputLayer.cpp new file mode 100644 index 0000000..e3e40b4 --- /dev/null +++ b/GCryptCLI/src/DataOutputLayer.cpp @@ -0,0 +1,135 @@ +#include "DataOutputLayer.h" +#include "DataFormatter.h" +#include "CommandlineInterface.h" +#include +#include +#include + +using namespace IO; + +void DataOutputLayer::Init() { + + // Set our ostream + switch (Configuration::outputTo) { + + // Are we writing to stdout? + case Configuration::OUTPUT_TO::STDOUT: + + // Redirect our ostream to stdout + out = &std::cout; + break; + + // Are we writing to a file? + case Configuration::OUTPUT_TO::FILE: + + // Open the file + ofs.open( + Configuration::inputFilename, + std::ios::out | std::ios::binary + ); + + // A little bit of error handling + if (!ofs.good()) { + throw std::runtime_error("Unable to open outfilestream!"); + } + + // Redirect our ostream to this outfilestream + out = &ofs; + break; + } + + // Determine which iobase format to write in + // If we are decrypting, input is not formatted + if (Configuration::activeModule == Configuration::MODULE::DECRYPTION) { + outFormat = Configuration::IOBASE_FORMAT::BASE_BYTES; + } + // If we are doing anything else, output is the requested format + else { + outFormat = Configuration::iobaseFormat; + } + + initialized = true; + reachedEof = false; + + return; + +} + +void DataOutputLayer::Destruct() { + if (Configuration::outputTo == Configuration::OUTPUT_TO::FILE) { + ofs.close(); + } + + return; +} + +void DataOutputLayer::Enqueue(const Block& block) { + blocks.emplace(block); + return; +} + +void DataOutputLayer::WriteBlock() { + // Some error checking + if (!initialized) { + throw std::runtime_error("Attempted to write on uninitialized DataOutputLayer!"); + } + + // Check if we have any block to write + // and if we should (output-puffering) + // Basically: only output if we have anything to output, and + // if --puffer-output is given, only output once we have reachedEof. + if ( + (blocks.size() > 0) && + ( + (!CommandlineInterface::Get().HasParam("--puffer-output")) || + (reachedEof) + ) + ) { + + // Fetch the block to write + const Block block = blocks.front(); + blocks.pop(); + + // Recode it to our output format + const std::string formattedBlock = + DataFormatter::FormatBlock( + block, + outFormat + ); + + // Dump it + *out << formattedBlock; + + // If this is not the last block, and the used iobase set + // requires it, append a seperator + if ( + (!IsFinished()) && + ( + (outFormat == Configuration::IOBASE_FORMAT::BASE_UWU) || + (outFormat == Configuration::IOBASE_FORMAT::BASE_UGH) + ) + ) { + *out << " "; + } + + } + + return; +} + +void DataOutputLayer::ReachedEOF() { + reachedEof = true; + return; +} + +bool DataOutputLayer::IsFinished() { + return (reachedEof) && (blocks.size() == 0); +} + +std::ostream* DataOutputLayer::out; +std::ofstream DataOutputLayer::ofs; +bool DataOutputLayer::reachedEof = false; +bool DataOutputLayer::initialized = false; +Configuration::IOBASE_FORMAT DataOutputLayer::outFormat; +std::queue DataOutputLayer::blocks; + diff --git a/GCryptCLI/src/ModuleEncryption.cpp b/GCryptCLI/src/ModuleEncryption.cpp new file mode 100644 index 0000000..9cec537 --- /dev/null +++ b/GCryptCLI/src/ModuleEncryption.cpp @@ -0,0 +1,57 @@ +#include "ModuleEncryption.h" +#include "DataIngestionLayer.h" +#include "DataOutputLayer.h" +#include "KeyManager.h" +#include +#include + +using namespace Module; +using namespace Leonetienne::GCrypt; + +void Encryption::Run() { + + // Initialize the data ingestion layer + IO::DataIngestionLayer::Init(); + + // Initialize the data output layer + IO::DataOutputLayer::Init(); + + // Initialize a cipher + GCipher cipher( + KeyManager::GetKey(), + GCipher::DIRECTION::ENCIPHER + ); + + while (!IO::DataOutputLayer::IsFinished()) { + // Read in new blocks, if not reached eof + if (!IO::DataIngestionLayer::ReachedEOF()) { + IO::DataIngestionLayer::ReadBlock(); + } + + // Process a block, if one is ready + if (IO::DataIngestionLayer::IsBlockReady()) { + const Block cleartext = IO::DataIngestionLayer::GetNextBlock(); + const Block ciphertext = cipher.Digest(cleartext); + + // Enqueue the block for output + IO::DataOutputLayer::Enqueue(ciphertext); + + // Tell the data output layer that it just received the + // last block, if it did + if (IO::DataIngestionLayer::IsFinished()) { + IO::DataOutputLayer::ReachedEOF(); + } + } + + // Attempt to write a block + IO::DataOutputLayer::WriteBlock(); + } + + // Destruct the data ingestion layer + IO::DataIngestionLayer::Destruct(); + + // Destruct the data output layer + IO::DataOutputLayer::Destruct(); + + return; +} diff --git a/GCryptCLI/src/main.cpp b/GCryptCLI/src/main.cpp index 672566c..79748b5 100644 --- a/GCryptCLI/src/main.cpp +++ b/GCryptCLI/src/main.cpp @@ -2,8 +2,7 @@ #include "Configuration.h" #include "KeyManager.h" #include "ModuleGenerateKey.h" - -#include "DataIngestionLayer.h" +#include "ModuleEncryption.h" int main(int argc, char* const* argv) { @@ -16,12 +15,12 @@ int main(int argc, char* const* argv) { // Prepare the key KeyManager::PrepareKey(); - IO::DataIngestionLayer::Init(); - // Launch our module switch (Configuration::activeModule) { case Configuration::MODULE::GENERATE_KEY: Module::GenerateKey::Run(); + case Configuration::MODULE::ENCRYPTION: + Module::Encryption::Run(); } return 0;