Sophisticated and bug-fixed DataOutput/InputLayer, and added ModuleDecryption
This commit is contained in:
parent
d9fb90a01e
commit
a93b3b3fe5
@ -38,6 +38,11 @@ namespace IO {
|
|||||||
private:
|
private:
|
||||||
static std::istream* in;
|
static std::istream* in;
|
||||||
|
|
||||||
|
// Will read n bytes from the input.
|
||||||
|
// If EOF is reached, it will return a string of length <= 5
|
||||||
|
// and will set the approriate flags.
|
||||||
|
static std::string ReadBytes(const std::size_t n, std::size_t& out_bytes_read);
|
||||||
|
|
||||||
// We have to hold on to a reference to a filestream,
|
// We have to hold on to a reference to a filestream,
|
||||||
// even if we're always just reading from in.
|
// even if we're always just reading from in.
|
||||||
// We still have to CLOSE the file handle afterwards!
|
// We still have to CLOSE the file handle afterwards!
|
||||||
@ -49,6 +54,9 @@ namespace IO {
|
|||||||
// Indicates whether this class has been initialized
|
// Indicates whether this class has been initialized
|
||||||
static bool initialized;
|
static bool initialized;
|
||||||
|
|
||||||
|
// Are we reading ciphertext or regular text?
|
||||||
|
static bool isReadingCiphertext;
|
||||||
|
|
||||||
// All read blocks, that haven't been given out yet
|
// All read blocks, that haven't been given out yet
|
||||||
static std::queue<Block> blocks;
|
static std::queue<Block> blocks;
|
||||||
|
|
||||||
|
@ -32,6 +32,10 @@ namespace IO {
|
|||||||
static bool IsFinished();
|
static bool IsFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
//! If we are finished, and are outputting to stdout,
|
||||||
|
//! and the user didn't specifically opt out, print a newline
|
||||||
|
static void AddTrailingLinebreakIfRequired();
|
||||||
|
|
||||||
static std::ostream* out;
|
static std::ostream* out;
|
||||||
|
|
||||||
// We have to hold on to a reference to a filestream,
|
// We have to hold on to a reference to a filestream,
|
||||||
|
18
GCryptCLI/include/ModuleDecryption.h
Normal file
18
GCryptCLI/include/ModuleDecryption.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef GCRYPTCLI_MODULE_DECRYPTION_H
|
||||||
|
#define GCRYPTCLI_MODULE_DECRYPTION_H
|
||||||
|
|
||||||
|
namespace Module {
|
||||||
|
//! This module will decrypt supplied input
|
||||||
|
class Decryption {
|
||||||
|
public:
|
||||||
|
//! Will run the module
|
||||||
|
static void Run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// No instanciation! >:(
|
||||||
|
Decryption() {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -171,16 +171,14 @@ std::vector<Block> DataFormatter::DecodeFormatMultiblock(
|
|||||||
|
|
||||||
// A block is this many digits wide, in encoding
|
// A block is this many digits wide, in encoding
|
||||||
const std::size_t blockWidth = blockLengthByBase[base];
|
const std::size_t blockWidth = blockLengthByBase[base];
|
||||||
//std::cout << "blockWidth is: " << blockWidth << std::endl;
|
|
||||||
|
|
||||||
// How many blocks are we dealing with here?
|
// How many blocks are we dealing with here?
|
||||||
const std::size_t n_blocks = (str.length() / blockWidth) + 1;
|
const std::size_t n_blocks = (str.length() / blockWidth) + 1;
|
||||||
blocks.reserve(n_blocks);
|
blocks.reserve(n_blocks);
|
||||||
//std::cout << "n_blocks is: " << n_blocks << std::endl;
|
|
||||||
|
|
||||||
// Iterate over the string, and parse all blocks
|
// Iterate over the string, and parse all blocks
|
||||||
// We now have to differentiate between single-char digit sets (hex),
|
// We now have to differentiate between single-char digit sets (like hex),
|
||||||
// and multi-char digit sets (uwu):
|
// and multi-char digit sets (like uwu):
|
||||||
switch (base) {
|
switch (base) {
|
||||||
case Configuration::IOBASE_FORMAT::BASE_BYTES:
|
case Configuration::IOBASE_FORMAT::BASE_BYTES:
|
||||||
case Configuration::IOBASE_FORMAT::BASE_2:
|
case Configuration::IOBASE_FORMAT::BASE_2:
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "DataIngestionLayer.h"
|
#include "DataIngestionLayer.h"
|
||||||
#include "CommandlineInterface.h"
|
#include "CommandlineInterface.h"
|
||||||
|
#include "DataFormatter.h"
|
||||||
#include "Bases.h"
|
#include "Bases.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
@ -53,6 +54,16 @@ void DataIngestionLayer::Init() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Derive from our the current module if we're reading ciphertext or not
|
||||||
|
if (
|
||||||
|
(Configuration::activeModule == Configuration::MODULE::DECRYPTION)
|
||||||
|
) {
|
||||||
|
isReadingCiphertext = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
isReadingCiphertext = false;
|
||||||
|
}
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
reachedEof = false;
|
reachedEof = false;
|
||||||
|
|
||||||
@ -74,35 +85,95 @@ void DataIngestionLayer::ReadBlock() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!reachedEof) {
|
if (!reachedEof) {
|
||||||
// This should really account for iobase recoding!
|
// A block is this many digits wide, in encoding
|
||||||
|
const std::size_t blockWidth = blockLengthByBase[Configuration::formatIn];
|
||||||
|
|
||||||
// Create buffer to read into
|
// Iterate over the string, and parse all blocks
|
||||||
char buf[Block::BLOCK_SIZE];
|
// We now have to differentiate between single-char digit sets (like hex),
|
||||||
memset(buf, 0, sizeof(buf));
|
// and multi-char digit sets (like uwu):
|
||||||
|
switch (Configuration::formatIn) {
|
||||||
|
case Configuration::IOBASE_FORMAT::BASE_BYTES:
|
||||||
|
case Configuration::IOBASE_FORMAT::BASE_2:
|
||||||
|
case Configuration::IOBASE_FORMAT::BASE_8:
|
||||||
|
case Configuration::IOBASE_FORMAT::BASE_10:
|
||||||
|
case Configuration::IOBASE_FORMAT::BASE_16:
|
||||||
|
case Configuration::IOBASE_FORMAT::BASE_64:
|
||||||
|
// Easy case: Each digit is exactly one char in size.
|
||||||
|
// We can just calculate how many bytes we have to read.
|
||||||
|
|
||||||
// Read
|
// bytesRead is always of the correct length, 0-padded.
|
||||||
in->read(buf, sizeof(buf));
|
std::size_t n_bytes_read;
|
||||||
|
const std::string dataRead = ReadBytes(blockWidth, n_bytes_read);
|
||||||
|
|
||||||
// Fetch how much we've read
|
// If we've read 0 bytes, this was the last block
|
||||||
const std::size_t n_bytes_read = in->gcount();
|
// and it's completely empty. We can abort without doing anything.
|
||||||
|
// The ReadBytes function takes care of setting the reachedEof flag.
|
||||||
|
if (n_bytes_read == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Is this fewer bytes than we requested?
|
// If we are reading ciphertext
|
||||||
if (n_bytes_read < sizeof(buf)) {
|
// make sure we've read enough bytes to compose a block.
|
||||||
// Yes: EOF reached.
|
if (
|
||||||
reachedEof = true;
|
(isReadingCiphertext) &&
|
||||||
}
|
(n_bytes_read < blockWidth)
|
||||||
|
) {
|
||||||
|
throw std::runtime_error("DataIngestionLayer::ReadBlock() read an input-data fragment that is smaller than a data block should be. Is your cipher text incomplete?");
|
||||||
|
}
|
||||||
|
|
||||||
// Construct a Block from this buf
|
// This should decode to a block just like this.
|
||||||
Block block;
|
Block newBlock;
|
||||||
block.FromByteString(std::string(buf, sizeof(buf)));
|
|
||||||
|
// Special-case: We are reading cleartext (no ciphertext)
|
||||||
|
// cleartext is always base_bytes
|
||||||
|
if (!isReadingCiphertext) {
|
||||||
|
// When just reading cleartext-bytes, we also allow shorter strings
|
||||||
|
// than BLOCK_SIZE. These will just get zero-padded.
|
||||||
|
newBlock.FromTextString(dataRead);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Else: recode to a block.
|
||||||
|
newBlock = DataFormatter::DecodeFormat(
|
||||||
|
dataRead,
|
||||||
|
Configuration::formatIn
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
blocks.emplace(newBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Enqueue it
|
|
||||||
blocks.emplace(block);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DataIngestionLayer::ReadBytes(const std::size_t n, std::size_t& out_bytes_read) {
|
||||||
|
|
||||||
|
// Prepare a buffer to read to
|
||||||
|
char* buf = new char[n+1];
|
||||||
|
memset(buf, 0, (n+1) * sizeof(buf[0]));
|
||||||
|
|
||||||
|
// Read
|
||||||
|
in->read(buf, n * sizeof(buf[0]));
|
||||||
|
|
||||||
|
// Fetch how much we've read
|
||||||
|
out_bytes_read = in->gcount();
|
||||||
|
|
||||||
|
// Is this fewer bytes than got requested?
|
||||||
|
if (out_bytes_read < n) {
|
||||||
|
// Yes: EOF reached.
|
||||||
|
reachedEof = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Translate buffer to a standard string
|
||||||
|
const std::string sbuf(buf, n);
|
||||||
|
delete[] buf;
|
||||||
|
|
||||||
|
// Return our buffer
|
||||||
|
return sbuf;
|
||||||
|
}
|
||||||
|
|
||||||
bool DataIngestionLayer::ReachedEOF() {
|
bool DataIngestionLayer::ReachedEOF() {
|
||||||
return reachedEof;
|
return reachedEof;
|
||||||
}
|
}
|
||||||
@ -142,5 +213,6 @@ std::ifstream DataIngestionLayer::ifs;
|
|||||||
std::istringstream DataIngestionLayer::iss;
|
std::istringstream DataIngestionLayer::iss;
|
||||||
bool DataIngestionLayer::reachedEof = false;
|
bool DataIngestionLayer::reachedEof = false;
|
||||||
bool DataIngestionLayer::initialized = false;
|
bool DataIngestionLayer::initialized = false;
|
||||||
|
bool DataIngestionLayer::isReadingCiphertext;
|
||||||
std::queue<Block> DataIngestionLayer::blocks;
|
std::queue<Block> DataIngestionLayer::blocks;
|
||||||
|
|
||||||
|
@ -75,7 +75,6 @@ void DataOutputLayer::WriteBlock() {
|
|||||||
(reachedEof)
|
(reachedEof)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// Fetch the block to write
|
// Fetch the block to write
|
||||||
const Block block = blocks.front();
|
const Block block = blocks.front();
|
||||||
blocks.pop();
|
blocks.pop();
|
||||||
@ -88,7 +87,8 @@ void DataOutputLayer::WriteBlock() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Dump it
|
// Dump it
|
||||||
*out << formattedBlock;
|
// This way we avoid zerobytes getting trimmed off...
|
||||||
|
out->write(formattedBlock.data(), formattedBlock.length());
|
||||||
|
|
||||||
// If this is not the last block, and the used iobase set
|
// If this is not the last block, and the used iobase set
|
||||||
// requires it, append a seperator
|
// requires it, append a seperator
|
||||||
@ -102,15 +102,8 @@ void DataOutputLayer::WriteBlock() {
|
|||||||
*out << " ";
|
*out << " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are finished, and are outputting to stdout,
|
AddTrailingLinebreakIfRequired();
|
||||||
// and the user didn't specifically opt out, print a newline
|
out->flush();
|
||||||
if (
|
|
||||||
(IsFinished()) &&
|
|
||||||
(Configuration::outputTo == Configuration::OUTPUT_TO::STDOUT) &&
|
|
||||||
(!CommandlineInterface::Get().HasParam("--no-newline"))
|
|
||||||
) {
|
|
||||||
*out << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,6 +112,11 @@ void DataOutputLayer::WriteBlock() {
|
|||||||
|
|
||||||
void DataOutputLayer::ReachedEOF() {
|
void DataOutputLayer::ReachedEOF() {
|
||||||
reachedEof = true;
|
reachedEof = true;
|
||||||
|
|
||||||
|
// Add the trailing linebreak here aswell, as, if input is ciphertext,
|
||||||
|
// ReachedEOF() may only be called after all blocks are already written
|
||||||
|
AddTrailingLinebreakIfRequired();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,6 +124,23 @@ bool DataOutputLayer::IsFinished() {
|
|||||||
return (reachedEof) && (blocks.size() == 0);
|
return (reachedEof) && (blocks.size() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DataOutputLayer::AddTrailingLinebreakIfRequired() {
|
||||||
|
// If we are finished, and are outputting to stdout,
|
||||||
|
// and input format is not bytes,
|
||||||
|
// and the user didn't specifically opt out, print a newline
|
||||||
|
if (
|
||||||
|
(IsFinished()) &&
|
||||||
|
(Configuration::outputTo == Configuration::OUTPUT_TO::STDOUT) &&
|
||||||
|
(Configuration::formatIn != Configuration::IOBASE_FORMAT::BASE_BYTES) &&
|
||||||
|
(!CommandlineInterface::Get().HasParam("--no-newline"))
|
||||||
|
) {
|
||||||
|
*out << std::endl;
|
||||||
|
out->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream* DataOutputLayer::out;
|
std::ostream* DataOutputLayer::out;
|
||||||
std::ofstream DataOutputLayer::ofs;
|
std::ofstream DataOutputLayer::ofs;
|
||||||
bool DataOutputLayer::reachedEof = false;
|
bool DataOutputLayer::reachedEof = false;
|
||||||
|
56
GCryptCLI/src/ModuleDecryption.cpp
Normal file
56
GCryptCLI/src/ModuleDecryption.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include "ModuleDecryption.h"
|
||||||
|
#include "DataIngestionLayer.h"
|
||||||
|
#include "DataOutputLayer.h"
|
||||||
|
#include "KeyManager.h"
|
||||||
|
#include <GCrypt/GCipher.h>
|
||||||
|
|
||||||
|
using namespace Module;
|
||||||
|
using namespace Leonetienne::GCrypt;
|
||||||
|
|
||||||
|
void Decryption::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::DECIPHER
|
||||||
|
);
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
}
|
@ -2,7 +2,6 @@
|
|||||||
#include "DataIngestionLayer.h"
|
#include "DataIngestionLayer.h"
|
||||||
#include "DataOutputLayer.h"
|
#include "DataOutputLayer.h"
|
||||||
#include "KeyManager.h"
|
#include "KeyManager.h"
|
||||||
#include <iostream>
|
|
||||||
#include <GCrypt/GCipher.h>
|
#include <GCrypt/GCipher.h>
|
||||||
|
|
||||||
using namespace Module;
|
using namespace Module;
|
||||||
@ -35,12 +34,12 @@ void Encryption::Run() {
|
|||||||
|
|
||||||
// Enqueue the block for output
|
// Enqueue the block for output
|
||||||
IO::DataOutputLayer::Enqueue(ciphertext);
|
IO::DataOutputLayer::Enqueue(ciphertext);
|
||||||
|
}
|
||||||
|
|
||||||
// Tell the data output layer that it just received the
|
// Tell the data output layer that it just received the
|
||||||
// last block, if it did
|
// last block, if it did
|
||||||
if (IO::DataIngestionLayer::IsFinished()) {
|
if (IO::DataIngestionLayer::IsFinished()) {
|
||||||
IO::DataOutputLayer::ReachedEOF();
|
IO::DataOutputLayer::ReachedEOF();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to write a block
|
// Attempt to write a block
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "KeyManager.h"
|
#include "KeyManager.h"
|
||||||
#include "ModuleGenerateKey.h"
|
#include "ModuleGenerateKey.h"
|
||||||
#include "ModuleEncryption.h"
|
#include "ModuleEncryption.h"
|
||||||
|
#include "ModuleDecryption.h"
|
||||||
|
|
||||||
int main(int argc, char* const* argv) {
|
int main(int argc, char* const* argv) {
|
||||||
|
|
||||||
@ -24,6 +25,10 @@ int main(int argc, char* const* argv) {
|
|||||||
case Configuration::MODULE::ENCRYPTION:
|
case Configuration::MODULE::ENCRYPTION:
|
||||||
Module::Encryption::Run();
|
Module::Encryption::Run();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Configuration::MODULE::DECRYPTION:
|
||||||
|
Module::Decryption::Run();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user