Merge branch 'feature/relaunch' into master
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(gecrypt)
|
||||
project(gcrypt)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
@@ -42,3 +42,37 @@ target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${gcrypt_include}
|
||||
)
|
||||
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE
|
||||
-Werror
|
||||
-fdiagnostics-color=always
|
||||
)
|
||||
|
||||
#########
|
||||
# Tests #
|
||||
#########
|
||||
LIST(FILTER main_src EXCLUDE REGEX ".*/main.cpp")
|
||||
FILE(GLOB test_src test/*.cpp)
|
||||
|
||||
add_executable(test
|
||||
test/Catch2.h
|
||||
${test_src}
|
||||
${main_src}
|
||||
${stringtools_src}
|
||||
${generalutility_src}
|
||||
${hazelnupp_src}
|
||||
${gcrypt_src}
|
||||
)
|
||||
|
||||
target_include_directories(test PRIVATE
|
||||
include
|
||||
${stringtools_include}
|
||||
${generalutility_include}
|
||||
${hazelnupp_include}
|
||||
${gcrypt_include}
|
||||
)
|
||||
|
||||
target_compile_options(test PRIVATE
|
||||
-Werror
|
||||
-fdiagnostics-color=always
|
||||
)
|
||||
|
||||
|
@@ -1,6 +1,28 @@
|
||||
#pragma once
|
||||
#ifndef GCRYPTCLI_BASES_H
|
||||
#define GCRYPTCLI_BASES_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
// This lookup table holds how many digits a block is long
|
||||
// in any iobase.
|
||||
// This cannot be calculated on the fly, as it involves
|
||||
// arithmetic with involving REALLY big numbers (like, 2^512).
|
||||
// Here's how to calculate these numbers:
|
||||
// Print an all 1's block in this format, and check the string size.
|
||||
// That's it.
|
||||
static auto blockLengthByBase =
|
||||
std::map<Configuration::IOBASE_FORMAT, std::size_t>({
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_BYTES, 64),
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_2, 512),
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_8, 171),
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_10, 155),
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_16, 128),
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_64, 86),
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_UWU, 81),
|
||||
std::make_pair(Configuration::IOBASE_FORMAT::BASE_UGH, 126)
|
||||
});
|
||||
|
||||
// Actually useful bases
|
||||
static const std::vector<std::string> BASE_2 = { "0","1" };
|
||||
@@ -116,3 +138,6 @@ static const std::vector<std::string> BASE_UGH = {
|
||||
"Bah!",
|
||||
"Wha-?"
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,4 +1,6 @@
|
||||
#pragma once
|
||||
#ifndef GCRYPTCLI_CLIINTERFACE_H
|
||||
#define GCRYPTCLI_CLIINTERFACE_H
|
||||
|
||||
#include <Hazelnupp/CmdArgsInterface.h>
|
||||
|
||||
class CommandlineInterface
|
||||
@@ -14,8 +16,11 @@ private:
|
||||
static void CrashWithMsg(const std::string& msg);
|
||||
static void CatchVersionQueries();
|
||||
|
||||
CommandlineInterface() {};
|
||||
|
||||
static Hazelnp::CmdArgsInterface nupp;
|
||||
|
||||
// No instanciation! >:(
|
||||
CommandlineInterface() {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
61
GCryptCLI/include/Configuration.h
Normal file
61
GCryptCLI/include/Configuration.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef GCRYPTCLI_CONFIGURATION_H
|
||||
#define GCRYPTCLI_CONFIGURATION_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class Configuration {
|
||||
public:
|
||||
static enum class INPUT_FROM {
|
||||
STDIN,
|
||||
FILE,
|
||||
PARAMETER
|
||||
} inputFrom;
|
||||
|
||||
static enum class OUTPUT_TO {
|
||||
STDOUT,
|
||||
FILE
|
||||
} outputTo;
|
||||
|
||||
static enum class IOBASE_FORMAT {
|
||||
BASE_BYTES,
|
||||
BASE_2,
|
||||
BASE_8,
|
||||
BASE_10,
|
||||
BASE_16,
|
||||
BASE_64,
|
||||
BASE_UWU,
|
||||
BASE_UGH
|
||||
}
|
||||
formatIn,
|
||||
formatOut;
|
||||
|
||||
static std::string inputFilename;
|
||||
static std::string outputFilename;
|
||||
|
||||
static enum class MODULE {
|
||||
ENCRYPTION,
|
||||
DECRYPTION,
|
||||
HASH,
|
||||
GENERATE_KEY
|
||||
} activeModule;
|
||||
|
||||
//! Will analyze the supplied cli parameters,
|
||||
//! and decide what the configuration will be.
|
||||
static void Parse();
|
||||
|
||||
private:
|
||||
static void DecideInputFrom();
|
||||
static void DecideOutputTo();
|
||||
static void DecideCiphertextFormat();
|
||||
static void MapCiphertextFormatToIOBases();
|
||||
static void DecideModule();
|
||||
|
||||
// This is just an intermediary value, used between methods
|
||||
static IOBASE_FORMAT ciphertextFormat;
|
||||
|
||||
// No instanciation! >:(
|
||||
Configuration() {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
58
GCryptCLI/include/DataFormatter.h
Normal file
58
GCryptCLI/include/DataFormatter.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifndef GCRYPTCLI_DATAFORMATTER_H
|
||||
#define GCRYPTCLI_DATAFORMATTER_H
|
||||
|
||||
#include <GCrypt/Block.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Configuration.h"
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
// This class has the task to format Blocks to various formats.
|
||||
class DataFormatter {
|
||||
public:
|
||||
//! Will format a single block to a given iobase
|
||||
static std::string FormatBlock(
|
||||
const Block& block,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
);
|
||||
|
||||
//! Will parse a string of a given iobase to a block
|
||||
static Block DecodeFormat(
|
||||
const std::string& str,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
);
|
||||
|
||||
//! Will format a vector of blocks to a given iobase
|
||||
static std::string FormatBlocks(
|
||||
const std::vector<Block>& blocks,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
);
|
||||
|
||||
//! Will format a string making up multiple block in a given iobase into a vector of block
|
||||
static std::vector<Block> DecodeFormatMultiblock(
|
||||
const std::string& str,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
);
|
||||
|
||||
|
||||
private:
|
||||
static std::string Bin2CustomBase(
|
||||
const std::string& bin,
|
||||
const std::vector<std::string>& customSet,
|
||||
const std::size_t minLen,
|
||||
const std::string& seperator = ""
|
||||
);
|
||||
|
||||
static std::string CustomBase2Bin(
|
||||
const std::string& in,
|
||||
const std::vector<std::string>& customSet,
|
||||
const std::string& seperator = ""
|
||||
);
|
||||
|
||||
// No instanciation! >:(
|
||||
DataFormatter() {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
75
GCryptCLI/include/DataIngestionLayer.h
Normal file
75
GCryptCLI/include/DataIngestionLayer.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#ifndef GCRYPTCLI_DATAINGESTIONLAYER_H
|
||||
#define GCRYPTCLI_DATAINGESTIONLAYER_H
|
||||
|
||||
#include <iosfwd>
|
||||
#include <queue>
|
||||
#include <GCrypt/Block.h>
|
||||
#include "Configuration.h"
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
namespace IO {
|
||||
|
||||
// This class is used to read in data.
|
||||
class DataIngestionLayer {
|
||||
public:
|
||||
//! Will initialize the ingestion
|
||||
static void Init();
|
||||
|
||||
//! Will destruct the ingestion layer (like, closing file handles)
|
||||
static void Destruct();
|
||||
|
||||
//! Will attempt to read a data block.
|
||||
//! Requires Init() to have been called
|
||||
static void ReadBlock();
|
||||
|
||||
//! Have we read in all available blocks?
|
||||
static bool ReachedEOF();
|
||||
|
||||
//! Returns true if there are blocks to be fetched (GetNextBlock())
|
||||
static bool IsBlockReady();
|
||||
|
||||
//! Will return the next block in the queue
|
||||
static Block GetNextBlock();
|
||||
|
||||
//! Returns true, if EOF is reached, and there are no more blocks to fetch (GetNextBlock())
|
||||
static bool IsFinished();
|
||||
|
||||
//! Returns how many blocks have been read, in total
|
||||
static std::size_t NBlocksRead();
|
||||
|
||||
private:
|
||||
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,
|
||||
// even if we're always just reading from in.
|
||||
// We still have to CLOSE the file handle afterwards!
|
||||
static std::ifstream ifs;
|
||||
static std::istringstream iss;
|
||||
|
||||
// Indicates whether EOF has been reached
|
||||
static bool reachedEof;
|
||||
// Indicates whether this class has been initialized
|
||||
static bool initialized;
|
||||
|
||||
// Are we reading ciphertext or regular text?
|
||||
static bool isReadingCiphertext;
|
||||
|
||||
// How many blocks have been read in total
|
||||
static std::size_t nBlocksRead;
|
||||
|
||||
// All read blocks, that haven't been given out yet
|
||||
static std::queue<Block> blocks;
|
||||
|
||||
// No instanciation! >:(
|
||||
DataIngestionLayer();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
61
GCryptCLI/include/DataOutputLayer.h
Normal file
61
GCryptCLI/include/DataOutputLayer.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef GCRYPTCLI_DATAOUTPUTLAYER_H
|
||||
#define GCRYPTCLI_DATAOUTPUTLAYER_H
|
||||
|
||||
#include <iosfwd>
|
||||
#include <queue>
|
||||
#include <GCrypt/Block.h>
|
||||
#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:
|
||||
//! 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;
|
||||
|
||||
// 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<Block> blocks;
|
||||
|
||||
//! No instanciation >:(
|
||||
DataOutputLayer() {};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
30
GCryptCLI/include/KeyManager.h
Normal file
30
GCryptCLI/include/KeyManager.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef GCRYPTCLI_KEYMANAGER_H
|
||||
#define GCRYPTCLI_KEYMANAGER_H
|
||||
|
||||
#include <GCrypt/Key.h>
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
// This class has the task to prepare and supply the encryption key.
|
||||
class KeyManager {
|
||||
public:
|
||||
//! Will prepare the key. Be it from cli, a file, or, random, or whatever.
|
||||
static void PrepareKey();
|
||||
|
||||
//! Will return the key, if prepared.
|
||||
static const Key& GetKey();
|
||||
|
||||
private:
|
||||
//! Will ask for a password on stdin,
|
||||
//! hiding the input.
|
||||
static std::string PasswordPrompt();
|
||||
|
||||
//! The encryption key
|
||||
static Key key;
|
||||
|
||||
// No instanciation! >:(
|
||||
KeyManager() {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
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
|
||||
|
18
GCryptCLI/include/ModuleEncryption.h
Normal file
18
GCryptCLI/include/ModuleEncryption.h
Normal file
@@ -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
|
||||
|
19
GCryptCLI/include/ModuleGenerateKey.h
Normal file
19
GCryptCLI/include/ModuleGenerateKey.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef GCRYPTCLI_MODULE_GENERATEKEY_H
|
||||
#define GCRYPTCLI_MODULE_GENERATEKEY_H
|
||||
|
||||
namespace Module {
|
||||
// This module just generates a key, and outputs it.
|
||||
// Can be used to create a keyfiles.
|
||||
class GenerateKey {
|
||||
public:
|
||||
//! Will write the key to a file
|
||||
static void Run();
|
||||
|
||||
private:
|
||||
// No instanciation! >:(
|
||||
GenerateKey() {};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
18
GCryptCLI/include/ModuleHashing.h
Normal file
18
GCryptCLI/include/ModuleHashing.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef GCRYPTCLI_MODULE_HASHING_H
|
||||
#define GCRYPTCLI_MODULE_HASHING_H
|
||||
|
||||
namespace Module {
|
||||
//! This module will hash supplied input
|
||||
class Hashing {
|
||||
public:
|
||||
//! Will run the module
|
||||
static void Run();
|
||||
|
||||
private:
|
||||
// No instanciation! >:(
|
||||
Hashing() {};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
23
GCryptCLI/include/ProgressPrinter.h
Normal file
23
GCryptCLI/include/ProgressPrinter.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef GCRYPTCLI_PROGRESSPRINTER_H
|
||||
#define GCRYPTCLI_PROGRESSPRINTER_H
|
||||
|
||||
#include <iostream>
|
||||
#include "CommandlineInterface.h"
|
||||
|
||||
// This class has the task to output progress to stderr, if requested
|
||||
class ProgressPrinter {
|
||||
public:
|
||||
//! Will print progress to stderr, if requested, and the interval matches
|
||||
static void PrintIfAppropriate(
|
||||
const std::string& message,
|
||||
const std::size_t current,
|
||||
const std::size_t target
|
||||
);
|
||||
|
||||
private:
|
||||
// No instanciation! >:(
|
||||
ProgressPrinter() {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -1,3 +1,7 @@
|
||||
#pragma once
|
||||
#define GHETTOCRYPTCLI_VERSION 0.1241
|
||||
#ifndef GCRYPTCLI_VERSION_H
|
||||
#define GCRYPTCLI_VERSION_H
|
||||
|
||||
#define GCRYPTCLI_VERSION 0.1251
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,62 +1,88 @@
|
||||
# GCrypt CLI
|
||||
Easy text and file encryption via the command line using Ghetto Crypt. Now supporting [*esoteric data formats*](#esoteric-data-formats)... :)
|
||||
Easy text and file encryption via the command line using GCrypt. Now supporting [*esoteric data formats*](#esoteric-data-formats)... :)
|
||||
Again, please only use this as an obfuscator or if the only other option would be no encryption at all.
|
||||
Do you want to quickly and securely encrypt stuff via the command line? Use openssl-cli with the aes cipher. It's a bit more wordy but much faster and more secure.
|
||||
|
||||
Still want to use Ghetto Crypt cli? Here ya go!
|
||||
Just clone this repository, navigate into this directory and run `cmake . && make`. It shouuuld *\*crosses fingers\** just build.
|
||||
Still want to use GCrypt cli? Here ya go!
|
||||
Just clone this repository, navigate into this directory and compile it:
|
||||
|
||||
## How do i use this?
|
||||
### Prerequsities:
|
||||
Have these depencies installed:
|
||||
* git
|
||||
* make
|
||||
* cmake
|
||||
* build-essentials (c++ >= 17) (might work with 11, if you're lucky)
|
||||
|
||||
### How2compile
|
||||
1) Clone this repository.
|
||||
2) Download all submodules: `git submodule update --init --recursive`.
|
||||
3) Cd into /GCryptCLI: `cd GCryptCLI`.
|
||||
4) Create a build directory: `cmake -B build`.
|
||||
5) Cd into the build directory: `cd build`.
|
||||
6) Compile: `make`.
|
||||
The executable `gcrypt` should now lie in `build/`.
|
||||
|
||||
If you want to use this globally, you could move it to `/usr/bin/`, or some other location in your $PATH.
|
||||
|
||||
## How do i use this?
|
||||
### Options and flags
|
||||
All arguments and flags:
|
||||
```
|
||||
$ gecrypt --help
|
||||
CLI for the ghettocrypt cipher/obfuscator
|
||||
CLI for the GCrypt cipher/obfuscator
|
||||
Copyright (c) 2022 Leon Etienne
|
||||
Ghettocrypt v0.21
|
||||
Ghettocrypt CLI v0.124
|
||||
THIS IS EXPERIMENTAL SOFTWARE AND MUST BE CONSIDERED INSECURE. DO NOT USE THIS TO ENCRYPT SENSITIVE DATA! READ THE README FILES ACCESSIBLE AT "https://github.com/Leonetienne/GhettoCrypt/blob/master/readme.md" AND "https://github.com/Leonetienne/GhettoCrypt/blob/master/GhettoCryptCLI/readme.md"
|
||||
GCrypt v0.236
|
||||
GCrypt CLI v0.1241
|
||||
THIS IS EXPERIMENTAL SOFTWARE AND MUST BE CONSIDERED INSECURE. DO NOT USE THIS TO ENCRYPT SENSITIVE DATA! READ THE README FILES ACCESSIBLE AT "https://gitea.leonetienne.de/leonetienne/GCrypt"
|
||||
|
||||
==== AVAILABLE PARAMETERS ====
|
||||
|
||||
--iobase-8 VOID incompatibilities=[--iobase-2, --iobase-10, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base8
|
||||
--iobase-bytes VOID incompatibilities=[--iobase-2, --iobase-8, --iobase-10, --iobase-16, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and output ciphertexts as raw bytes.
|
||||
|
||||
--iobase-16 VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-8, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base16 (hex)
|
||||
|
||||
--progress -p VOID Print digestion progress to stdout. May be advisable for large files, as the cipher is rather slow.
|
||||
|
||||
--cli-version VOID Will supply the version of ghettocrypt-cli used.
|
||||
--cli-version -v VOID Will supply the version of GCryptCLI used.
|
||||
|
||||
--keyfile -kf STRING incompatibilities=[--key, --keyask, --hash] Read in the first {KEYSIZE}(=512) bits of this file and use that as an encryption key. WARNING: Arguments may be logged by the system!
|
||||
|
||||
--iobase-2 VOID incompatibilities=[--iobase-8, --iobase-10, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base2
|
||||
--iobase-2 VOID incompatibilities=[--iobase-bytes, --iobase-8, --iobase-10, --iobase-16, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base2
|
||||
|
||||
--iobase-10 VOID incompatibilities=[--iobase-2, --iobase-8, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base10
|
||||
--iobase-10 VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-8, --iobase-16, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base10
|
||||
|
||||
--iobase-ugh VOID incompatibilities=[--iobase-2, --iobase-8, --iobase-10, --iobase-64, --iobase-uwu] Interpret and format ciphertexts in base ugh
|
||||
--ofile -o STRING incompatibilities=[--ostdout, --hash] Write output in this file.
|
||||
|
||||
--iobase-uwu VOID incompatibilities=[--iobase-2, --iobase-8, --iobase-10, --iobase-64, --iobase-ugh] Interpret and format ciphertexts in base uwu
|
||||
|
||||
--iobase-64 VOID incompatibilities=[--iobase-2, --iobase-8, --iobase-10, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base64
|
||||
|
||||
--ostdout VOID incompatibilities=[--ofile, --hash] Output of digested files will be dumped to stdout instead of a file.
|
||||
|
||||
--encrypt -e VOID incompatibilities=[--decrypt, --hash] Use the encryption routine.
|
||||
|
||||
--infile -if STRING incompatibilities=[--intext] Encrypt this file. Saves as {filename}.crypt, if not specified otherwise.
|
||||
|
||||
--version -v VOID Will supply the version of ghettocrypt used.
|
||||
|
||||
--decrypt -d VOID incompatibilities=[--encrypt, --hash] Use decryption routine.
|
||||
|
||||
--hash -h VOID incompatibilities=[--encrypt, --decrypt] Use the ghetto cipher as a hash digest.
|
||||
|
||||
--intext -it STRING incompatibilities=[--infile] Encrypt this string. Dumps to stdout.
|
||||
|
||||
--ofile -o STRING incompatibilities=[--ostdout, --hash] Use this filename for output if --infile is specified. Gets ignored otherwise.
|
||||
--key -k STRING incompatibilities=[--keyfile, --keyask, --hash] Use this value as a password to extrapolate the encryption key. WARNING: Arguments may be logged by the system!
|
||||
|
||||
--keyask -ka VOID incompatibilities=[--key, --keyfile, --hash] Read the encryption key from stdin.
|
||||
|
||||
--key -k STRING incompatibilities=[--keyfile, --keyask, --hash] Use this value as a password to extrapolate the encryption key. WARNING: Arguments may be logged by the system!
|
||||
--no-newline VOID Don't postfix stdout output with a newline
|
||||
|
||||
--puffer-output VOID Will digest the entire data before initiating any output.
|
||||
|
||||
--puffer-input VOID Will read the entire input before beginning any digestion.
|
||||
|
||||
--decrypt -d VOID incompatibilities=[--encrypt, --hash, --generate-key] Use decryption module.
|
||||
|
||||
--lib-version VOID Will supply the version of GCryptLib used.
|
||||
|
||||
--iobase-ugh VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-8, --iobase-10, --iobase-16, --iobase-64, --iobase-uwu] Interpret and format ciphertexts in base ugh
|
||||
|
||||
--infile -if STRING incompatibilities=[--intext] Encrypt this file.
|
||||
|
||||
--iobase-uwu VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-8, --iobase-10, --iobase-16, --iobase-64, --iobase-ugh] Interpret and format ciphertexts in base uwu
|
||||
|
||||
--iobase-64 VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-8, --iobase-10, --iobase-16, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base64
|
||||
|
||||
--iobase-8 VOID incompatibilities=[--iobase-bytes, --iobase-2, --iobase-10, --iobase-16, --iobase-64, --iobase-uwu, --iobase-ugh] Interpret and format ciphertexts in base8
|
||||
|
||||
--encrypt -e VOID incompatibilities=[--decrypt, --hash] Use the encryption module.
|
||||
|
||||
--generate-key VOID incompatibilities=[--encrypt, --decrypt, --hash] Use the key generation module. Will generate a random key based on hardware events, output it, and exit.
|
||||
|
||||
--hash -h VOID incompatibilities=[--encrypt, --decrypt, --generate-key] Use the GHash hash module to calculate a hashsum.
|
||||
|
||||
--intext -it STRING incompatibilities=[--infile] Encrypt this string.
|
||||
```
|
||||
|
||||
### Examples
|
||||
@@ -64,13 +90,13 @@ Please note that commonly used arguments are supplied in their short form (`-e`
|
||||
|
||||
#### I want to encrypt text!
|
||||
```sh
|
||||
$ gecrypt -e --keyask --intext "hello, world!"
|
||||
$ gcrypt -e --keyask --intext "hello, world!"
|
||||
efbebc429c8370bf84f00b0d8ccbaf7858b3b87d71ff58cb1cfefa8fb0c68094c0865565873aa8a5254ede59be46e81a4d4917e679b18cb290dbd6669cb6207a
|
||||
```
|
||||
|
||||
#### Now decrypt it
|
||||
```sh
|
||||
$ gecrypt -d --keyask --intext "efbebc429c8370bf84f00b0d8ccbaf7858b3b87d71ff58cb1cfefa8fb0c68094c0865565873aa8a5254ede59be46e81a4d4917e679b18cb290dbd6669cb6207a"
|
||||
$ gcrypt -d --keyask --intext "efbebc429c8370bf84f00b0d8ccbaf7858b3b87d71ff58cb1cfefa8fb0c68094c0865565873aa8a5254ede59be46e81a4d4917e679b18cb290dbd6669cb6207a"
|
||||
hello, world!
|
||||
```
|
||||
|
||||
@@ -80,95 +106,109 @@ hello, world!
|
||||
> Outputting it in base-64 took just over ONE MINUTE. In base-2 over SEVEN MINUTES. The general trend seems to be, the larger the base, the better it performs.
|
||||
|
||||
```sh
|
||||
$ gecrypt -e --keyask --intext "hello, world!" --iobase-2
|
||||
$ gcrypt -e --keyask --intext "hello, world!" --iobase-2
|
||||
111001001011100000011111000100010100110011100110000100100101001001110001001000101011110000000011011100001010111010001000110111110110011011100000001100110001001000100111011000101010010001011011111011001000011111100100101001011110011101110001010011000101011001111010000001001100101110000101101101101001110100100001101010111101010000100111101110000110011101100101101011000011101001000011010010011001111010001001101000101001100101010000100010111101101100010000000001001110010001001011001001011011010111001101000100
|
||||
|
||||
$ gecrypt -e --keyask --intext "hello, world!" --iobase-8
|
||||
$ gcrypt -e --keyask --intext "hello, world!" --iobase-8
|
||||
71134037042463460445116110536003341272106766334014611047305221337310374451363561230531720114560555516441527520475606354553035103223172115051452042755420011621131133271504
|
||||
|
||||
$ gecrypt -e --keyask --intext "hello, world!" --iobase-10
|
||||
$ gcrypt -e --keyask --intext "hello, world!" --iobase-10
|
||||
2994749439449970047518881970731547473115480925772565399786126223459744370490386223437520234266936877059618216185983047971748564015130703048737306773910340
|
||||
|
||||
$ gecrypt -e --keyask --intext "hello, world!" --iobase-64
|
||||
$ gcrypt -e --keyask --intext "hello, world!" --iobase-64
|
||||
Co/WjpV5nPrCaz0QMdrXAXzzOH5HODRsBNL22KZowmGMcTLwfmsQpzt7Ik+ViR5vOhUXowFQeR5x2vbcj1X5ae
|
||||
```
|
||||
I won't be pasting in stdout for every example. It would become too cluttered.
|
||||
|
||||
#### Passing the key as an argument
|
||||
```sh
|
||||
$ gecrypt -e --key "secretpassword" --intext "hello, world!"
|
||||
$ gcrypt -e --key "secretpassword" --intext "hello, world!"
|
||||
```
|
||||
> :warning: Some operating systems will log cli arguments! THIS WOULD BE THE ENTIRE KEY!
|
||||
|
||||
#### Using keyfiles
|
||||
```sh
|
||||
$ gecrypt -e --keyfile "dog.jpg" --intext "hello, world!"
|
||||
$ gcrypt -e --keyfile "dog.jpg" --intext "hello, world!"
|
||||
```
|
||||
|
||||
#### Creating keyfiles
|
||||
```sh
|
||||
$ gcrypt --generate-key --ofile "my-keyfile.bin"
|
||||
```
|
||||
This will generate a random 512-bit keyfile from hardware events
|
||||
> :warning: Some operating systems will log cli arguments! One might find your keyfile!
|
||||
|
||||
#### Encrypting files
|
||||
```sh
|
||||
$ gecrypt -e --keyask --infile "cat.jpg"
|
||||
$ gcrypt -e --keyask --infile "cat.jpg"
|
||||
```
|
||||
File `cat.jpg.crypt` will be created.
|
||||
|
||||
#### Encrypting files to a target file name
|
||||
```sh
|
||||
$ gecrypt -e --keyask --infile "cat.jpg" -o "encrypted_cat.jpg"
|
||||
$ gcrypt -e --keyask --infile "cat.jpg" -o "encrypted_cat.jpg"
|
||||
```
|
||||
File `encrypted_cat.jpg` will be created.
|
||||
|
||||
#### Decrypting files
|
||||
```sh
|
||||
$ gecrypt -d --keyask --infile "cat.jpg.crypt"
|
||||
$ gcrypt -d --keyask --infile "cat.jpg.crypt"
|
||||
```
|
||||
File `cat.jpg.crypt.plain` will be created. Its contents match `cat.jpg`
|
||||
> :warning: Since this is a block cipher, decrypted files may be tailpadded with a few nullbytes.
|
||||
|
||||
#### Decrypting files to a target file name
|
||||
```sh
|
||||
$ gecrypt -d --keyask --infile "cat.jpg.crypt" -o "decrypted_cat.jpg"
|
||||
$ gcrypt -d --keyask --infile "cat.jpg.crypt" -o "decrypted_cat.jpg"
|
||||
```
|
||||
File `decrypted_cat.jpg` will be created. You can now open it again.
|
||||
|
||||
#### Encrypting large files takes time. How's the progress?
|
||||
```sh
|
||||
$ gecrypt -e --keyask --infile "cat.jpg" --progress
|
||||
$ gcrypt -e --keyask --infile "cat.jpg" --progress
|
||||
```
|
||||
Something along the lines of `Encrypting... (Block 200 / 1148 - 17.4216%)` will be regularly, but not too often, printed to stdout.
|
||||
|
||||
#### Any cipher can also compute hashsums
|
||||
```sh
|
||||
$ gecrypt -h --intext "hello, world!"
|
||||
$ gcrypt -h --intext "hello, world!"
|
||||
a96f42c9d97e46b9e1ed7de5182770170d4ef9b7b8264f3fbd89b38dc60c1fe06232653f5856013307fc020fb1d35f2bea26bc0f373c5ac35a722c6b03d8254d
|
||||
|
||||
$ gecrypt -h --infile "cat.jpg"
|
||||
$ gcrypt -h --infile "cat.jpg"
|
||||
fe6bdfb6ec39771c4fdcdc40e52397bcd67fbfef0ad5a15ebbd8b9e4c2a815848b3984eda5ef6f727e9e420c23500c90c42ab80ac5659048be8969357741e3e5
|
||||
|
||||
```
|
||||
The hashsum will always be of size BLOCK_SIZE. That is 512 bits by default.
|
||||
> :warning: Calculating a hashsum takes about twice as long as regular encryption.
|
||||
The hashsum will always be of size BLOCK_SIZE. That is 512.
|
||||
|
||||
#### What version am i running?
|
||||
Depending on wether you want to know the GhettoCrypt version or the CLI's version, use either `--version` or `--cli-version`. It will print out a floating point number.
|
||||
Depending on wether you want to know the GCrypt version or the CLI's version,
|
||||
use either `--cli-version` or `--lib-version`.
|
||||
It will print out a floating point number.
|
||||
|
||||
#### I want to stream the output of file en/decryption.
|
||||
You can dump the binary result to stdout. In this example, we'll stream it into a jpg file,
|
||||
but you could stream it to whatever you'd like.
|
||||
// Easily! If you do not supply any output or input, stdout and stdin will be used instead!
|
||||
```sh
|
||||
$ gecrypt -d --keyask --infile "cat.jpg.crypt" --ostdout > "decrypted_cat.jpg"
|
||||
# mpv is a media player, as an example
|
||||
$ gcrypt -d --key "123" --infile "music.mp3.crypt" | mpv -
|
||||
```
|
||||
|
||||
#### Don't want to stream input and output?
|
||||
By default, gcrypt will read a block, digest it, and output the result immediately.
|
||||
Sometimes you don't want that. Use these flags, respectively:
|
||||
```
|
||||
--puffer-input # Reads all input to memory before beginning to digest it
|
||||
--puffer-output # Digests all input before beginning to write any
|
||||
```
|
||||
|
||||
## Esoteric data formats
|
||||
#### Base *UwU*
|
||||
```sh
|
||||
$ gecrypt -e --keyask --intext "hello, world!" --iobase-uwu
|
||||
$ gcrypt -e --keyask --intext "hello, world!" --iobase-uwu
|
||||
:) sewnpaiii tastieee uhh?! nappies cutewr twe best cutieee :O tastieee senpaiiiw favowite toesy-woesies ^.^ :3 best chomp whiffle uwu Awww sewnpaiii comfy-womfy :p keewl Awww youuu nyeko :O tasties hiiiii heeeey (*^_^*) youuu toot uhh..? smush (*^_^*) *bites-lip* whiffle haaaay nyah! comfy-womfy :) cutsie Owww haaaay snaffle haaaai haaaai nyeko *sweats* :) uhh..? boop toot *bites-lip* <3 whiiiich whiffskaws ^.^ twe whiffskaws hiiiii *sweats* Owww dewicious i tasties :P awe hewwo boop rawr uwu dewicious eughh twe cutsie xD
|
||||
```
|
||||
|
||||
#### Base **UGH!**
|
||||
```sh
|
||||
$ gecrypt -e --keyask --intext "hello, world!" --iobase-ugh
|
||||
$ gcrypt -e --keyask --intext "hello, world!" --iobase-ugh
|
||||
Grr... Wha-? Aah! Aah! Uh-huh... Aah! Grr... Aah! Aah! Uh-huh... Ah... Ugh Grr... Ugh Pft! Nu-uh... Gah! Bah! Huh...? Ah... Uh-huh... Wha-? Pft! Nu-uh... Ugh Wha-? Psh! Agh! Ah... Aah! Nu-uh... Psh! Pft! Nu-uh... Psh! Shh! Gah! Ah... Pft! Gah! Shh! Bah! Gah! Uh-huh... Gah! Duh! Aah! Uh-huh... Er- Nu-uh... Gah! Wha-? Pft! Er- Shh! Ah... Huh...? Er- Wha-? Uh-huh... Ah... Shh! Ugh Bah! Wha-? Uaah! Ah... Nu-uh... Uh-huh... Ugh Pft! Pft! Gah! Shh! Shh! Wha-? Bah! Ugh Grr... Aah! Pft! Nu-uh... Ah... Aah! Agh! Er- Psh! Uaah! Nu-uh... Ugh Wha-? Uh-huh... Shh! Pft! Aah! Agh! Grr... Agh! Agh! Grr... Pft! Wha-? Wha-? Uh-huh... Aah! Ugh Aah! Pft! Gah! Bah! Huh...? Ugh Bah! Uaah! Gah! Bah! Duh! Duh! Uh-huh... Grr... Ah... Grr... Ugh Ah... Pft!
|
||||
```
|
||||
|
||||
|
@@ -2,20 +2,19 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <GCrypt/Version.h>
|
||||
#include <GCrypt/Config.h>
|
||||
#include <GCrypt/Block.h>
|
||||
#include "Version.h"
|
||||
|
||||
using namespace Hazelnp;
|
||||
using namespace Leonetienne;
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
void CommandlineInterface::Init(int argc, const char* const* argv)
|
||||
{
|
||||
void CommandlineInterface::Init(int argc, const char* const* argv) {
|
||||
/* General information */
|
||||
std::stringstream ss;
|
||||
ss << "CLI for the gcrypt cipher/obfuscator" << std::endl
|
||||
ss << "CLI for the GCrypt cipher/obfuscator" << std::endl
|
||||
<< "Copyright (c) 2022 Leon Etienne" << std::endl
|
||||
<< "GCrypt v" << GHETTOCRYPT_VERSION << std::endl
|
||||
<< "GCrypt CLI v" << GHETTOCRYPTCLI_VERSION << std::endl
|
||||
<< "GCrypt v" << GCRYPT_VERSION << std::endl
|
||||
<< "GCrypt CLI v" << GCRYPTCLI_VERSION << std::endl
|
||||
<< "THIS IS EXPERIMENTAL SOFTWARE AND MUST BE CONSIDERED INSECURE. DO NOT USE THIS TO ENCRYPT SENSITIVE DATA! READ THE README FILES ACCESSIBLE AT \"https://gitea.leonetienne.de/leonetienne/GCrypt\"";
|
||||
nupp.SetBriefDescription(ss.str());
|
||||
ss.str("");
|
||||
@@ -23,39 +22,39 @@ void CommandlineInterface::Init(int argc, const char* const* argv)
|
||||
nupp.SetCrashOnFail("true");
|
||||
|
||||
/* Builtin documentation */
|
||||
nupp.RegisterDescription("--encrypt", "Use the encryption routine.");
|
||||
nupp.RegisterDescription("--encrypt", "Use the encryption module.");
|
||||
nupp.RegisterConstraint("--encrypt", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {"--decrypt", "--hash" }));
|
||||
nupp.RegisterAbbreviation("-e", "--encrypt");
|
||||
|
||||
nupp.RegisterDescription("--decrypt", "Use decryption routine.");
|
||||
nupp.RegisterConstraint("--decrypt", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--encrypt", "--hash" }));
|
||||
nupp.RegisterDescription("--decrypt", "Use decryption module.");
|
||||
nupp.RegisterConstraint("--decrypt", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--encrypt", "--hash", "--generate-key" }));
|
||||
nupp.RegisterAbbreviation("-d", "--decrypt");
|
||||
|
||||
nupp.RegisterDescription("--hash", "Use the ghetto cipher as a hash digest.");
|
||||
nupp.RegisterConstraint("--hash", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--encrypt", "--decrypt" }));
|
||||
nupp.RegisterDescription("--hash", "Use the GHash hash module to calculate a hashsum.");
|
||||
nupp.RegisterConstraint("--hash", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--encrypt", "--decrypt", "--generate-key" }));
|
||||
nupp.RegisterAbbreviation("-h", "--hash");
|
||||
|
||||
nupp.RegisterDescription("--intext", "Encrypt this string. Dumps to stdout.");
|
||||
nupp.RegisterDescription("--generate-key", "Use the key generation module. Will generate a random key based on hardware events, output it, and exit.");
|
||||
nupp.RegisterConstraint("--generate-key", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--encrypt", "--decrypt", "--hash" }));
|
||||
|
||||
nupp.RegisterDescription("--intext", "Encrypt this string.");
|
||||
nupp.RegisterConstraint("--intext", ParamConstraint(true, DATA_TYPE::STRING, {}, false, { "--infile" }));
|
||||
nupp.RegisterAbbreviation("-it", "--intext");
|
||||
|
||||
nupp.RegisterDescription("--infile", "Encrypt this file. Saves as {filename}.crypt, if not specified otherwise.");
|
||||
nupp.RegisterDescription("--infile", "Encrypt this file.");
|
||||
nupp.RegisterConstraint("--infile", ParamConstraint(true, DATA_TYPE::STRING, {}, false, { "--intext" }));
|
||||
nupp.RegisterAbbreviation("-if", "--infile");
|
||||
|
||||
nupp.RegisterDescription("--ofile", "Use this filename for output if --infile is specified. Gets ignored otherwise.");
|
||||
nupp.RegisterDescription("--ofile", "Write output in this file.");
|
||||
nupp.RegisterConstraint("--ofile", ParamConstraint(true, DATA_TYPE::STRING, {}, false, { "--ostdout", "--hash" }));
|
||||
nupp.RegisterAbbreviation("-of", "--ofile");
|
||||
nupp.RegisterAbbreviation("-o", "--ofile");
|
||||
|
||||
nupp.RegisterDescription("--ostdout", "Output of digested files will be dumped to stdout instead of a file.");
|
||||
nupp.RegisterConstraint("--ostdout", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--ofile", "--hash" }));
|
||||
|
||||
nupp.RegisterDescription("--key", "Use this value as a password to extrapolate the encryption key. WARNING: Arguments may be logged by the system!");
|
||||
nupp.RegisterConstraint("--key", ParamConstraint(true, DATA_TYPE::STRING, {}, false, { "--keyfile", "--keyask", "--hash" }));
|
||||
nupp.RegisterAbbreviation("-k", "--key");
|
||||
|
||||
ss << "Read in the first {KEYSIZE}(=" << GCrypt::BLOCK_SIZE << ") bits of this file and use that as an encryption key. WARNING: Arguments may be logged by the system!";
|
||||
ss << "Read in the first {KEYSIZE}(=" << Block::BLOCK_SIZE_BITS << ") bits of this file and use that as an encryption key. WARNING: Arguments may be logged by the system!";
|
||||
nupp.RegisterDescription("--keyfile", ss.str());
|
||||
ss.str("");
|
||||
nupp.RegisterConstraint("--keyfile", ParamConstraint(true, DATA_TYPE::STRING, {}, false, { "--key", "--keyask", "--hash" }));
|
||||
@@ -65,34 +64,52 @@ void CommandlineInterface::Init(int argc, const char* const* argv)
|
||||
nupp.RegisterConstraint("--keyask", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--key", "--keyfile", "--hash" }));
|
||||
nupp.RegisterAbbreviation("-ka", "--keyask");
|
||||
|
||||
nupp.RegisterDescription("--progress", "Print digestion progress to stdout. May be advisable for large files, as the cipher is rather slow.");
|
||||
nupp.RegisterDescription("--progress", "Print digestion progress to stderr. May be advisable for large files, as the cipher is rather slow.");
|
||||
nupp.RegisterConstraint("--progress", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
|
||||
nupp.RegisterAbbreviation("-p", "--progress");
|
||||
|
||||
nupp.RegisterDescription("--progress-interval", "Print digestion progress reports every these many data blocks.");
|
||||
nupp.RegisterConstraint("--progress-interval", ParamConstraint(true, DATA_TYPE::INT, { "1000" }, true, {}));
|
||||
|
||||
nupp.RegisterDescription("--iobase-bytes", "Interpret and output ciphertexts as raw bytes.");
|
||||
nupp.RegisterConstraint("--iobase-bytes", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-2", "--iobase-8", "--iobase-10", "--iobase-16", "--iobase-64", "--iobase-uwu", "--iobase-ugh" }));
|
||||
|
||||
nupp.RegisterDescription("--iobase-2", "Interpret and format ciphertexts in base2");
|
||||
nupp.RegisterConstraint("--iobase-2", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-8", "--iobase-10", "--iobase-64", "--iobase-uwu", "--iobase-ugh" }));
|
||||
nupp.RegisterConstraint("--iobase-2", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-bytes", "--iobase-8", "--iobase-10", "--iobase-16", "--iobase-64", "--iobase-uwu", "--iobase-ugh" }));
|
||||
|
||||
nupp.RegisterDescription("--iobase-8", "Interpret and format ciphertexts in base8");
|
||||
nupp.RegisterConstraint("--iobase-8", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-2", "--iobase-10", "--iobase-64", "--iobase-uwu", "--iobase-ugh" }));
|
||||
nupp.RegisterConstraint("--iobase-8", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-bytes", "--iobase-2", "--iobase-10", "--iobase-16", "--iobase-64", "--iobase-uwu", "--iobase-ugh" }));
|
||||
|
||||
nupp.RegisterDescription("--iobase-10", "Interpret and format ciphertexts in base10");
|
||||
nupp.RegisterConstraint("--iobase-10", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-2", "--iobase-8", "--iobase-64", "--iobase-uwu", "--iobase-ugh" }));
|
||||
nupp.RegisterConstraint("--iobase-10", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-bytes", "--iobase-2", "--iobase-8", "--iobase-16", "--iobase-64", "--iobase-uwu", "--iobase-ugh" }));
|
||||
|
||||
nupp.RegisterDescription("--iobase-16", "Interpret and format ciphertexts in base16 (hex)");
|
||||
nupp.RegisterConstraint("--iobase-16", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-bytes", "--iobase-2", "--iobase-8", "--iobase-64", "--iobase-uwu", "--iobase-ugh" }));
|
||||
|
||||
nupp.RegisterDescription("--iobase-64", "Interpret and format ciphertexts in base64");
|
||||
nupp.RegisterConstraint("--iobase-64", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-2", "--iobase-8", "--iobase-10", "--iobase-uwu", "--iobase-ugh" }));
|
||||
nupp.RegisterConstraint("--iobase-64", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-bytes", "--iobase-2", "--iobase-8", "--iobase-10", "--iobase-16", "--iobase-uwu", "--iobase-ugh" }));
|
||||
|
||||
nupp.RegisterDescription("--iobase-uwu", "Interpret and format ciphertexts in base uwu");
|
||||
nupp.RegisterConstraint("--iobase-uwu", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-2", "--iobase-8", "--iobase-10", "--iobase-64", "--iobase-ugh" }));
|
||||
nupp.RegisterConstraint("--iobase-uwu", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-bytes", "--iobase-2", "--iobase-8", "--iobase-10", "--iobase-16", "--iobase-64", "--iobase-ugh" }));
|
||||
|
||||
nupp.RegisterDescription("--iobase-ugh", "Interpret and format ciphertexts in base ugh");
|
||||
nupp.RegisterConstraint("--iobase-ugh", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-2", "--iobase-8", "--iobase-10", "--iobase-64", "--iobase-uwu" }));
|
||||
nupp.RegisterConstraint("--iobase-ugh", ParamConstraint(true, DATA_TYPE::VOID, {}, false, { "--iobase-bytes", "--iobase-2", "--iobase-8", "--iobase-10", "--iobase-16", "--iobase-64", "--iobase-uwu" }));
|
||||
|
||||
nupp.RegisterDescription("--version", "Will supply the version of ghettocrypt used.");
|
||||
nupp.RegisterConstraint("--version", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
|
||||
nupp.RegisterAbbreviation("-v", "--version");
|
||||
nupp.RegisterDescription("--lib-version", "Will supply the version of GCryptLib used.");
|
||||
nupp.RegisterConstraint("--lib-version", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
|
||||
|
||||
nupp.RegisterDescription("--cli-version", "Will supply the version of ghettocrypt-cli used.");
|
||||
nupp.RegisterDescription("--cli-version", "Will supply the version of GCryptCLI used.");
|
||||
nupp.RegisterConstraint("--cli-version", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
|
||||
nupp.RegisterAbbreviation("-v", "--cli-version");
|
||||
|
||||
nupp.RegisterDescription("--puffer-input", "Will read the entire input before beginning any digestion.");
|
||||
nupp.RegisterConstraint("--puffer-input", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
|
||||
|
||||
nupp.RegisterDescription("--puffer-output", "Will digest the entire data before initiating any output.");
|
||||
nupp.RegisterConstraint("--puffer-output", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
|
||||
|
||||
nupp.RegisterDescription("--no-newline", "Don't postfix stdout output with a newline");
|
||||
nupp.RegisterConstraint("--no-newline", ParamConstraint(true, DATA_TYPE::VOID, {}, false, {}));
|
||||
|
||||
/* Now parse */
|
||||
nupp.Parse(argc, argv);
|
||||
@@ -103,45 +120,69 @@ void CommandlineInterface::Init(int argc, const char* const* argv)
|
||||
return;
|
||||
}
|
||||
|
||||
Hazelnp::CmdArgsInterface& CommandlineInterface::Get()
|
||||
{
|
||||
Hazelnp::CmdArgsInterface& CommandlineInterface::Get() {
|
||||
return nupp;
|
||||
}
|
||||
|
||||
void CommandlineInterface::SpecialCompatibilityChecking()
|
||||
{
|
||||
// Encryption key
|
||||
// Do we have EITHER --hash (no key required), --key, --keyask or --keyfile given?
|
||||
if (
|
||||
(!nupp.HasParam("--hash")) &&
|
||||
(!nupp.HasParam("--key")) &&
|
||||
(!nupp.HasParam("--keyfile")) &&
|
||||
(!nupp.HasParam("--keyask"))
|
||||
)
|
||||
CrashWithMsg("No encryption key supplied! Please supply either --key, --keyfile, or --keyask!");
|
||||
void CommandlineInterface::SpecialCompatibilityChecking() {
|
||||
|
||||
// Encryption input
|
||||
// Do we have EITHER --intext or --infile?
|
||||
if (
|
||||
(!nupp.HasParam("--intext")) &&
|
||||
(!nupp.HasParam("--infile"))
|
||||
)
|
||||
CrashWithMsg("No encryption input supplied! Please supply either --intext or --infile!");
|
||||
|
||||
// Encryption mode
|
||||
// Active module
|
||||
// Do we have EITHER --encrypt or --decrypt or --hash?
|
||||
if (
|
||||
(!nupp.HasParam("--generate-key")) &&
|
||||
(!nupp.HasParam("--hash")) &&
|
||||
(!nupp.HasParam("--encrypt")) &&
|
||||
(!nupp.HasParam("--decrypt"))
|
||||
)
|
||||
CrashWithMsg("No encryption mode supplied! Please supply either --encrypt, --decrypt, or --hash!");
|
||||
) {
|
||||
CrashWithMsg("No module supplied! Please supply either --encrypt, --decrypt, --hash, or --generate-key!");
|
||||
}
|
||||
|
||||
// Encryption key
|
||||
// Do we have EITHER --hash (no key required), --generate-key (no key required), --key, --keyask or --keyfile given?
|
||||
if (
|
||||
(!nupp.HasParam("--hash")) &&
|
||||
(!nupp.HasParam("--generate-key")) &&
|
||||
(!nupp.HasParam("--key")) &&
|
||||
(!nupp.HasParam("--keyfile")) &&
|
||||
(!nupp.HasParam("--keyask"))
|
||||
) {
|
||||
CrashWithMsg("No encryption key supplied! Please supply either --key, --keyfile, or --keyask!");
|
||||
}
|
||||
|
||||
// Check that, if supplied, filename strings are not empty.
|
||||
if (
|
||||
(nupp.HasParam("--ofile")) &&
|
||||
(nupp["--ofile"].GetString().length() == 0)
|
||||
) {
|
||||
CrashWithMsg("Length of --ofile is zero! That can't be a valid path!");
|
||||
}
|
||||
|
||||
if (
|
||||
(nupp.HasParam("--ifile")) &&
|
||||
(nupp["--ifile"].GetString().length() == 0)
|
||||
) {
|
||||
CrashWithMsg("Length of --ifile is zero! That can't be a valid path!");
|
||||
}
|
||||
|
||||
if (
|
||||
(nupp.HasParam("--keyfile")) &&
|
||||
(nupp["--keyfile"].GetString().length() == 0)
|
||||
) {
|
||||
CrashWithMsg("Length of --keyfile is zero! That can't be a valid path!");
|
||||
}
|
||||
|
||||
if (
|
||||
(nupp.HasParam("--progress")) &&
|
||||
(!nupp.HasParam("--puffer-input"))
|
||||
|
||||
) {
|
||||
CrashWithMsg("--progress requires --puffer-input to work!");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void CommandlineInterface::CrashWithMsg(const std::string& msg)
|
||||
{
|
||||
void CommandlineInterface::CrashWithMsg(const std::string& msg) {
|
||||
std::cerr
|
||||
<< nupp.GetBriefDescription()
|
||||
<< std::endl
|
||||
@@ -151,16 +192,17 @@ void CommandlineInterface::CrashWithMsg(const std::string& msg)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void CommandlineInterface::CatchVersionQueries()
|
||||
{
|
||||
if (nupp.HasParam("--version"))
|
||||
{
|
||||
std::cout << GHETTOCRYPT_VERSION << std::endl;
|
||||
void CommandlineInterface::CatchVersionQueries() {
|
||||
if (
|
||||
(nupp.HasParam("--version")) ||
|
||||
(nupp.HasParam("--cli-version"))
|
||||
) {
|
||||
std::cout << GCRYPTCLI_VERSION << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
else if (nupp.HasParam("--cli-version"))
|
||||
else if (nupp.HasParam("--lib-version"))
|
||||
{
|
||||
std::cout << GHETTOCRYPTCLI_VERSION << std::endl;
|
||||
std::cout << GCRYPT_VERSION << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
186
GCryptCLI/src/Configuration.cpp
Normal file
186
GCryptCLI/src/Configuration.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
#include "Configuration.h"
|
||||
#include "CommandlineInterface.h"
|
||||
|
||||
void Configuration::Parse() {
|
||||
DecideModule();
|
||||
DecideInputFrom();
|
||||
DecideOutputTo();
|
||||
DecideCiphertextFormat();
|
||||
MapCiphertextFormatToIOBases();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Configuration::DecideModule() {
|
||||
if (CommandlineInterface::Get().HasParam("--encrypt")) {
|
||||
activeModule = MODULE::ENCRYPTION;
|
||||
return;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--decrypt")) {
|
||||
activeModule = MODULE::DECRYPTION;
|
||||
return;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--hash")) {
|
||||
activeModule = MODULE::HASH;
|
||||
return;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--generate-key")) {
|
||||
activeModule = MODULE::GENERATE_KEY;
|
||||
return;
|
||||
}
|
||||
|
||||
throw std::runtime_error("No module option found. Is the CLI parser configuration correct?.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Configuration::DecideInputFrom() {
|
||||
|
||||
if (CommandlineInterface::Get().HasParam("--intext")) {
|
||||
inputFrom = INPUT_FROM::PARAMETER;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--infile")) {
|
||||
inputFrom = INPUT_FROM::FILE;
|
||||
inputFilename = CommandlineInterface::Get()["--infile"].GetString();
|
||||
}
|
||||
else {
|
||||
inputFrom = INPUT_FROM::STDIN;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Configuration::DecideOutputTo() {
|
||||
|
||||
if (CommandlineInterface::Get().HasParam("--ofile")) {
|
||||
outputTo = OUTPUT_TO::FILE;
|
||||
outputFilename = CommandlineInterface::Get()["--ofile"].GetString();
|
||||
}
|
||||
else {
|
||||
outputTo = OUTPUT_TO::STDOUT;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Configuration::DecideCiphertextFormat() {
|
||||
|
||||
// Do we have any iobase explicitly specified?
|
||||
if (CommandlineInterface::Get().HasParam("--iobase-bytes")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_BYTES;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-2")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_2;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-8")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_8;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-10")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_10;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-16")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_16;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-64")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_64;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-uwu")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_UWU;
|
||||
}
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-ugh")) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_UGH;
|
||||
}
|
||||
|
||||
// So we have no iobase explicitly specified.. Let's default..
|
||||
|
||||
// If we are encrypting,
|
||||
else if (activeModule == MODULE::ENCRYPTION) {
|
||||
// and input comes from a parameter,
|
||||
// and output goes to stdout,
|
||||
// let's assume base-16.
|
||||
if (
|
||||
(inputFrom == INPUT_FROM::PARAMETER) &&
|
||||
(outputTo == OUTPUT_TO::STDOUT)
|
||||
) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_16;
|
||||
}
|
||||
|
||||
// Any other case whilst encrypting, we'll assume base-bytes.
|
||||
else {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_BYTES;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Else, if we are hashing,
|
||||
else if (activeModule == MODULE::HASH) {
|
||||
// output is always defaults to base 16
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_16;
|
||||
}
|
||||
|
||||
// Else, if we are decrypting,
|
||||
else if (activeModule == MODULE::DECRYPTION) {
|
||||
// and input comes from a parameter, we'll assume base-16.
|
||||
if (inputFrom == INPUT_FROM::PARAMETER) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_16;
|
||||
}
|
||||
// Any other case whilst decrypting, we'll assume base-bytes.
|
||||
else {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_BYTES;
|
||||
}
|
||||
}
|
||||
|
||||
// Else, if we are generating a key,
|
||||
else if (activeModule == MODULE::GENERATE_KEY) {
|
||||
// and we're outputting to stdout, we'll use base-16.
|
||||
if (outputTo == OUTPUT_TO::STDOUT) {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_16;
|
||||
}
|
||||
// else, we're outputting to a file, use base-bytes.
|
||||
else {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_BYTES;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: Bytes
|
||||
else {
|
||||
ciphertextFormat = IOBASE_FORMAT::BASE_BYTES;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Configuration::MapCiphertextFormatToIOBases() {
|
||||
|
||||
// Now, map the ciphertextFormat to either formatIn or formatOut.
|
||||
switch (activeModule) {
|
||||
// For encryption, keygen, and hashing:
|
||||
// input is bytes and output is ciphertext
|
||||
case MODULE::ENCRYPTION:
|
||||
case MODULE::HASH:
|
||||
case MODULE::GENERATE_KEY:
|
||||
formatIn = IOBASE_FORMAT::BASE_BYTES;
|
||||
formatOut = ciphertextFormat;
|
||||
break;
|
||||
|
||||
// For decryption:
|
||||
// input is ciphertext and output is bytes
|
||||
case MODULE::DECRYPTION:
|
||||
formatIn = ciphertextFormat;
|
||||
formatOut = IOBASE_FORMAT::BASE_BYTES;
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string Configuration::inputFilename;
|
||||
std::string Configuration::outputFilename;
|
||||
Configuration::MODULE Configuration::activeModule;
|
||||
Configuration::IOBASE_FORMAT Configuration::formatIn;
|
||||
Configuration::IOBASE_FORMAT Configuration::formatOut;
|
||||
Configuration::IOBASE_FORMAT Configuration::ciphertextFormat;
|
||||
Configuration::INPUT_FROM Configuration::inputFrom;
|
||||
Configuration::OUTPUT_TO Configuration::outputTo;
|
||||
|
299
GCryptCLI/src/DataFormatter.cpp
Normal file
299
GCryptCLI/src/DataFormatter.cpp
Normal file
@@ -0,0 +1,299 @@
|
||||
#include "DataFormatter.h"
|
||||
#include "Bases.h"
|
||||
#include <GeneralUtility/BaseConversion.h>
|
||||
#include <StringTools/StringTools.h>
|
||||
#include <GCrypt/Util.h>
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
using namespace Leonetienne::StringTools;
|
||||
using namespace Leonetienne::GeneralUtility;
|
||||
|
||||
std::string DataFormatter::FormatBlock(
|
||||
const Block& block,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
) {
|
||||
switch (base) {
|
||||
case Configuration::IOBASE_FORMAT::BASE_BYTES:
|
||||
return block.ToByteString();
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_2:
|
||||
return block.ToBinaryString();
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_8:
|
||||
return Bin2CustomBase(
|
||||
block.ToBinaryString(),
|
||||
BASE_8,
|
||||
blockLengthByBase[base]
|
||||
);
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_10:
|
||||
return Bin2CustomBase(
|
||||
block.ToBinaryString(),
|
||||
BASE_10,
|
||||
blockLengthByBase[base]
|
||||
);
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_16:
|
||||
return block.ToHexString();
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_64:
|
||||
return Bin2CustomBase(
|
||||
block.ToBinaryString(),
|
||||
BASE_64,
|
||||
blockLengthByBase[base]
|
||||
);
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_UWU:
|
||||
return Bin2CustomBase(
|
||||
block.ToBinaryString(),
|
||||
BASE_UWU,
|
||||
blockLengthByBase[base],
|
||||
" "
|
||||
);
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_UGH:
|
||||
return Bin2CustomBase(
|
||||
block.ToBinaryString(),
|
||||
BASE_UGH,
|
||||
blockLengthByBase[base],
|
||||
" "
|
||||
);
|
||||
|
||||
default:
|
||||
throw std::invalid_argument("FormatBlock(): Iobase not found! Oh no. Anyway.");
|
||||
}
|
||||
}
|
||||
|
||||
std::string DataFormatter::FormatBlocks(
|
||||
const std::vector<Block>& blocks,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
) {
|
||||
std::stringstream ss;
|
||||
|
||||
std::size_t i = 0;
|
||||
for (const Block& block : blocks) {
|
||||
ss << FormatBlock(block, base);
|
||||
|
||||
// If we are dealing with a multichar base, we must append a
|
||||
// seperator (space), but only if its not the last block.
|
||||
if (
|
||||
(base == Configuration::IOBASE_FORMAT::BASE_UWU) ||
|
||||
(base == Configuration::IOBASE_FORMAT::BASE_UGH)
|
||||
) {
|
||||
if (i++ != blocks.size()) {
|
||||
ss << " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
Block DataFormatter::DecodeFormat(
|
||||
const std::string& str,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
) {
|
||||
|
||||
Block b;
|
||||
|
||||
switch (base) {
|
||||
case Configuration::IOBASE_FORMAT::BASE_BYTES:
|
||||
b.FromByteString(str);
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_2:
|
||||
b.FromBinaryString(str);
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_8:
|
||||
b.FromBinaryString(
|
||||
CustomBase2Bin(
|
||||
str,
|
||||
BASE_8
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_10:
|
||||
b.FromBinaryString(
|
||||
CustomBase2Bin(
|
||||
str,
|
||||
BASE_10
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_16:
|
||||
b.FromHexString(str);
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_64:
|
||||
b.FromBinaryString(
|
||||
CustomBase2Bin(
|
||||
str,
|
||||
BASE_64
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_UWU:
|
||||
b.FromBinaryString(
|
||||
CustomBase2Bin(
|
||||
str,
|
||||
BASE_UWU,
|
||||
" "
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_UGH:
|
||||
b.FromBinaryString(
|
||||
CustomBase2Bin(
|
||||
str,
|
||||
BASE_UGH,
|
||||
" "
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::invalid_argument("StringToBlock(): Iobase now found! Oh no. Anyway.");
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
std::vector<Block> DataFormatter::DecodeFormatMultiblock(
|
||||
const std::string& str,
|
||||
const Configuration::IOBASE_FORMAT base
|
||||
) {
|
||||
std::vector<Block> blocks;
|
||||
|
||||
// A block is this many digits wide, in encoding
|
||||
const std::size_t blockWidth = blockLengthByBase[base];
|
||||
|
||||
// How many blocks are we dealing with here?
|
||||
const std::size_t n_blocks = (str.length() / blockWidth) + 1;
|
||||
blocks.reserve(n_blocks);
|
||||
|
||||
// Iterate over the string, and parse all blocks
|
||||
// We now have to differentiate between single-char digit sets (like hex),
|
||||
// and multi-char digit sets (like uwu):
|
||||
switch (base) {
|
||||
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 should read.
|
||||
for (std::size_t i = 0; i < str.length(); i += blockWidth) {
|
||||
|
||||
const std::string subs = str.substr(i, blockWidth);
|
||||
|
||||
Block newBlock = DecodeFormat(
|
||||
subs,
|
||||
base
|
||||
);
|
||||
|
||||
blocks.emplace_back(newBlock);
|
||||
}
|
||||
break;
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_UWU:
|
||||
case Configuration::IOBASE_FORMAT::BASE_UGH: {
|
||||
// Hard case: Each digit is n digits long. Digits may vary in length.
|
||||
// They are seperated by spaces.
|
||||
// We have to parse them...
|
||||
std::size_t digitsPassed = 0;
|
||||
std::size_t blockStart = 0;
|
||||
for (std::size_t i = 0; i < str.length(); i++) {
|
||||
|
||||
if (str[i] == ' ') {
|
||||
digitsPassed++;
|
||||
|
||||
if (digitsPassed == blockWidth) {
|
||||
const std::string subs = str.substr(
|
||||
blockStart,
|
||||
i - blockStart
|
||||
);
|
||||
|
||||
Block newBlock = DecodeFormat(
|
||||
subs,
|
||||
base
|
||||
);
|
||||
|
||||
blocks.emplace_back(newBlock);
|
||||
|
||||
digitsPassed = 0;
|
||||
blockStart = i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Here should never be any digits left. A formatted block should ALWAYS be full length.
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw std::invalid_argument("DataFormatter::StringToBlocks() has been passed an unknown base! No switch-case matched!");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return blocks;
|
||||
}
|
||||
|
||||
std::string DataFormatter::Bin2CustomBase(
|
||||
const std::string& bin,
|
||||
const std::vector<std::string>& customSet,
|
||||
const std::size_t minLen,
|
||||
const std::string& seperator
|
||||
) {
|
||||
std::stringstream ss;
|
||||
|
||||
// Translate to custom set
|
||||
const std::vector<std::string> vec_base_custom =
|
||||
Leonetienne::GeneralUtility::BaseConversion::BaseX_2_Y<std::string, std::vector<std::string>>(
|
||||
bin,
|
||||
"01",
|
||||
customSet,
|
||||
minLen
|
||||
);
|
||||
|
||||
// Convert to string
|
||||
for (std::size_t i = 0; i < vec_base_custom.size(); i++) {
|
||||
ss << vec_base_custom[i];
|
||||
|
||||
if (i != vec_base_custom.size() - 1) {
|
||||
ss << seperator;
|
||||
}
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string DataFormatter::CustomBase2Bin(
|
||||
const std::string& in,
|
||||
const std::vector<std::string>& customSet,
|
||||
const std::string& seperator
|
||||
) {
|
||||
// Split input into symbols
|
||||
const std::vector<std::string> in_symbols = StringTools::Split(in, seperator);
|
||||
|
||||
// Translate to binary
|
||||
std::string binary =
|
||||
Leonetienne::GeneralUtility::BaseConversion::BaseX_2_Y<std::vector<std::string>, std::string>(
|
||||
in_symbols,
|
||||
customSet,
|
||||
std::string("01"),
|
||||
Block::BLOCK_SIZE_BITS
|
||||
);
|
||||
|
||||
if (binary.length() != Block::BLOCK_SIZE_BITS) {
|
||||
throw std::invalid_argument("DataFormatter::CustomBase2Bin() received input that doesn't translate to a bitstring of length 512!");
|
||||
}
|
||||
|
||||
return binary;
|
||||
}
|
||||
|
369
GCryptCLI/src/DataIngestionLayer.cpp
Normal file
369
GCryptCLI/src/DataIngestionLayer.cpp
Normal file
@@ -0,0 +1,369 @@
|
||||
#include "DataIngestionLayer.h"
|
||||
#include "CommandlineInterface.h"
|
||||
#include "DataFormatter.h"
|
||||
#include "Bases.h"
|
||||
#include <StringTools/StringTools.h>
|
||||
#include <iostream>
|
||||
#include <istream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
|
||||
using namespace IO;
|
||||
using namespace Leonetienne::StringTools;
|
||||
|
||||
void DataIngestionLayer::Init() {
|
||||
|
||||
// Set our istream
|
||||
switch (Configuration::inputFrom) {
|
||||
|
||||
// Are we reading from stdin?
|
||||
case Configuration::INPUT_FROM::STDIN:
|
||||
|
||||
// Redirect our istream to stdin
|
||||
in = &std::cin;
|
||||
break;
|
||||
|
||||
// Are we reading from a file?
|
||||
case Configuration::INPUT_FROM::FILE:
|
||||
|
||||
// Open the file
|
||||
ifs.open(
|
||||
Configuration::inputFilename,
|
||||
std::ios::in | std::ios::binary
|
||||
);
|
||||
|
||||
// A little bit of error handling
|
||||
if (!ifs.good()) {
|
||||
throw std::runtime_error("Unable to open infilestream!");
|
||||
}
|
||||
|
||||
// Redirect our istream to this infilestream
|
||||
in = &ifs;
|
||||
break;
|
||||
|
||||
// Are we reading from a parameter?
|
||||
case Configuration::INPUT_FROM::PARAMETER:
|
||||
|
||||
// Create an instringstream with our parameter
|
||||
iss = std::istringstream(
|
||||
CommandlineInterface::Get()["--intext"].GetString()
|
||||
);
|
||||
|
||||
// Redirect our istream to this instringstream
|
||||
in = &iss;
|
||||
|
||||
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;
|
||||
reachedEof = false;
|
||||
nBlocksRead = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DataIngestionLayer::Destruct() {
|
||||
|
||||
if (Configuration::inputFrom == Configuration::INPUT_FROM::FILE) {
|
||||
ifs.close();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DataIngestionLayer::ReadBlock() {
|
||||
if (!initialized) {
|
||||
throw std::runtime_error("Attempted to read on uninitialized DataIngestionLayer!");
|
||||
}
|
||||
|
||||
if (!reachedEof) {
|
||||
// A block is this many digits wide, in encoding
|
||||
const std::size_t blockWidth = blockLengthByBase[Configuration::formatIn];
|
||||
|
||||
// Iterate over the string, and parse all blocks
|
||||
// We now have to differentiate between single-char digit sets (like hex),
|
||||
// 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.
|
||||
|
||||
// bytesRead is always of the correct length, 0-padded.
|
||||
std::size_t n_bytes_read;
|
||||
const std::string dataRead = ReadBytes(blockWidth, n_bytes_read);
|
||||
|
||||
// If we've read 0 bytes, this was the last block
|
||||
// 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;
|
||||
}
|
||||
|
||||
// If we are reading ciphertext
|
||||
// make sure we've read enough bytes to compose a block.
|
||||
if (
|
||||
(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?");
|
||||
}
|
||||
|
||||
// This should decode to a block just like this.
|
||||
Block newBlock;
|
||||
|
||||
// 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);
|
||||
nBlocksRead++;
|
||||
break;
|
||||
}
|
||||
|
||||
case Configuration::IOBASE_FORMAT::BASE_UWU:
|
||||
case Configuration::IOBASE_FORMAT::BASE_UGH: {
|
||||
// The whole of Italy doesn't have as much spaghetti as this is...
|
||||
|
||||
// Hard case: Each digit is n digits long. Digits may vary in length.
|
||||
// They are seperated by spaces.
|
||||
// We have to parse them...
|
||||
std::string overshoot = ""; // this is how much we've read too much in the last iteration
|
||||
|
||||
|
||||
// Gets terminated by a break statement
|
||||
while (1) {
|
||||
// We'll read chunks of 64 bytes... This should be a good
|
||||
// median, to also support small multi-byte-digit sets
|
||||
std::size_t n_bytes_read = 0;
|
||||
int lastDigitPos = -1; // Should point the the space BEFORE it. Relative to chunk.
|
||||
std::size_t digitsCollected = 0;
|
||||
std::stringstream digits;
|
||||
bool foundBlock = false;
|
||||
|
||||
// Remember to prepend our overshoot from the previous iteration this chunk
|
||||
std::string chunk = overshoot + ReadBytes(64, n_bytes_read);
|
||||
|
||||
// We should also strip all linebreaks from the chunk, that may be a result of manual stdin input.
|
||||
chunk = StringTools::Replace(chunk, '\n', "");
|
||||
|
||||
// We can't just check for completeness by n_bytes_read...
|
||||
// It can be any number of bytes, since any digit is n bytes long...
|
||||
|
||||
// Parse the 64-byte chunk string we've just fetched:
|
||||
for (std::size_t i = 0; i < chunk.size(); i++) {
|
||||
|
||||
// If we are near the end, and have still not found a complete block, let's load an additional chunk
|
||||
if (i == chunk.size() - 2) {
|
||||
const std::string nextChunk = ReadBytes(64, n_bytes_read);
|
||||
if (n_bytes_read != 0) {
|
||||
chunk += StringTools::Replace(nextChunk, '\n', "");
|
||||
}
|
||||
}
|
||||
|
||||
// If i is on a space, or at the end of the chunk,
|
||||
// and, at least one of i, or lastDigitPos is on a space,
|
||||
if (
|
||||
(
|
||||
(chunk[i] == ' ') ||
|
||||
(i == chunk.size() - 1)
|
||||
) &&
|
||||
(
|
||||
(chunk[i] == ' ') ||
|
||||
lastDigitPos >= 0 // This basically does the same as discribed, but safer, as its default value is -1.
|
||||
)
|
||||
){
|
||||
digitsCollected++;
|
||||
|
||||
// We have found a digit. Let's store it away...
|
||||
// We're putting them in a stringstream, to fit the format required by the data formatter...
|
||||
|
||||
// We have a slight edgecase if we're currently on the last char. Then we do NOT want to read one short.
|
||||
// This is because we ususally stand on a seperator char (' '), which we do not want to extract. But in that case,
|
||||
// in which we're standing on the last char, it could be not a seperator char.
|
||||
// note: chunk[i] != ' ' can only be true if we're on the last char.
|
||||
if (chunk[i] == ' ') {
|
||||
digits <<
|
||||
chunk.substr(
|
||||
lastDigitPos + 1,
|
||||
(int)i - lastDigitPos - 1
|
||||
)
|
||||
;
|
||||
} else {
|
||||
digits <<
|
||||
chunk.substr(
|
||||
lastDigitPos + 1,
|
||||
(int)i - lastDigitPos
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
// Add a seperator, if its not the last
|
||||
if (digitsCollected != blockWidth) {
|
||||
digits << ' ';
|
||||
}
|
||||
|
||||
lastDigitPos = i;
|
||||
|
||||
// Do we have enough digits to form a block?
|
||||
if (digitsCollected == blockWidth) {
|
||||
// We've found a complete block!
|
||||
|
||||
// Trim excess nullbytes off out digit string
|
||||
const std::string digitString = std::string(
|
||||
digits.str().data(),
|
||||
strlen(digits.str().data())
|
||||
);
|
||||
|
||||
// Decode it to a block object
|
||||
const Block newBlock = DataFormatter::DecodeFormat(
|
||||
digitString,
|
||||
Configuration::formatIn
|
||||
);
|
||||
|
||||
// Enqueue it to be processed by some module
|
||||
blocks.emplace(newBlock);
|
||||
nBlocksRead++;
|
||||
foundBlock = true;
|
||||
|
||||
// Now we have to calculate how many bytes we've read TOO MANY.
|
||||
// We have to trim this current chunk to be our new overshoot.
|
||||
|
||||
// If we still have more than a byte left, leave out the current seperator char
|
||||
if (i < chunk.size() - 1) {
|
||||
overshoot = chunk.substr(i+1); // Take all bytes from the next iterator, to the end
|
||||
}
|
||||
// Else: we are on the last char: there is no overshoot
|
||||
else {
|
||||
overshoot = "";
|
||||
}
|
||||
|
||||
// Stop the for loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Exit-condition:
|
||||
// We have not found any block, not even any digit.
|
||||
if ((!foundBlock) && (digitsCollected == 0)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Hard-abort: We have not finished reading a block
|
||||
if (!foundBlock) {
|
||||
throw std::runtime_error("DataIngestionLayer reached EOF whilst parsing multi-byte-digit block...");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw std::invalid_argument("DataFormatter::StringToBlocks() has been passed an unknown base! No switch-case matched!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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() {
|
||||
return reachedEof;
|
||||
}
|
||||
|
||||
bool DataIngestionLayer::IsBlockReady() {
|
||||
// We're not ready, if we haven't reached EOF, if we should puffer
|
||||
// the input.
|
||||
if (
|
||||
(CommandlineInterface::Get().HasParam("--puffer-input")) &&
|
||||
(!reachedEof)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we're not puffering, just return whether or not
|
||||
// we have any blocks...
|
||||
return blocks.size() > 0;
|
||||
}
|
||||
|
||||
bool DataIngestionLayer::IsFinished() {
|
||||
return (reachedEof) && (blocks.size() == 0);
|
||||
}
|
||||
|
||||
Block DataIngestionLayer::GetNextBlock() {
|
||||
if (!IsBlockReady()) {
|
||||
throw std::runtime_error("Attempted to get the next block, but there are none left!");
|
||||
}
|
||||
|
||||
// Why... why not just return a T in pop()???
|
||||
const Block popped = blocks.front();
|
||||
blocks.pop();
|
||||
return popped;
|
||||
}
|
||||
|
||||
std::size_t DataIngestionLayer::NBlocksRead() {
|
||||
return nBlocksRead;
|
||||
}
|
||||
|
||||
std::istream* DataIngestionLayer::in;
|
||||
std::ifstream DataIngestionLayer::ifs;
|
||||
std::istringstream DataIngestionLayer::iss;
|
||||
bool DataIngestionLayer::reachedEof = false;
|
||||
bool DataIngestionLayer::initialized = false;
|
||||
bool DataIngestionLayer::isReadingCiphertext;
|
||||
std::size_t DataIngestionLayer::nBlocksRead = 0;
|
||||
std::queue<Block> DataIngestionLayer::blocks;
|
||||
|
149
GCryptCLI/src/DataOutputLayer.cpp
Normal file
149
GCryptCLI/src/DataOutputLayer.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
#include "DataOutputLayer.h"
|
||||
#include "DataFormatter.h"
|
||||
#include "CommandlineInterface.h"
|
||||
#include <ostream>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
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::outputFilename,
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
Configuration::formatOut
|
||||
);
|
||||
|
||||
// Dump it
|
||||
// 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
|
||||
// requires it, append a seperator
|
||||
if (
|
||||
(!IsFinished()) &&
|
||||
(
|
||||
(Configuration::formatOut == Configuration::IOBASE_FORMAT::BASE_UWU) ||
|
||||
(Configuration::formatOut == Configuration::IOBASE_FORMAT::BASE_UGH)
|
||||
)
|
||||
) {
|
||||
*out << " ";
|
||||
}
|
||||
|
||||
AddTrailingLinebreakIfRequired();
|
||||
out->flush();
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DataOutputLayer::ReachedEOF() {
|
||||
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;
|
||||
}
|
||||
|
||||
bool DataOutputLayer::IsFinished() {
|
||||
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::formatOut != Configuration::IOBASE_FORMAT::BASE_BYTES) &&
|
||||
(!CommandlineInterface::Get().HasParam("--no-newline"))
|
||||
) {
|
||||
*out << std::endl;
|
||||
out->flush();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::ostream* DataOutputLayer::out;
|
||||
std::ofstream DataOutputLayer::ofs;
|
||||
bool DataOutputLayer::reachedEof = false;
|
||||
bool DataOutputLayer::initialized = false;
|
||||
std::queue<Block> DataOutputLayer::blocks;
|
||||
|
107
GCryptCLI/src/KeyManager.cpp
Normal file
107
GCryptCLI/src/KeyManager.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "KeyManager.h"
|
||||
#include "CommandlineInterface.h"
|
||||
#include "Configuration.h"
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
// Required for hidden password input
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
#include <Windows.h>
|
||||
#elif defined __GNUG__
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
void KeyManager::PrepareKey() {
|
||||
|
||||
// Special-case: We are hashing:
|
||||
// no key needed.
|
||||
if (Configuration::activeModule == Configuration::MODULE::HASH) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Special-case: We are generating a keyfile:
|
||||
// generate a random key from hardware events.
|
||||
else if (Configuration::activeModule == Configuration::MODULE::GENERATE_KEY) {
|
||||
key = Key::Random();
|
||||
return;
|
||||
}
|
||||
|
||||
// Else:
|
||||
// Is a password passed on the command line?
|
||||
else if (CommandlineInterface::Get().HasParam("--key")) {
|
||||
// Fetch it, and hash it to a key
|
||||
std::string password = CommandlineInterface::Get()["--key"].GetString();
|
||||
|
||||
key = Key::FromPassword(password);
|
||||
|
||||
// Don't forget to zero string memory.
|
||||
memset(password.data(), 0, password.size());
|
||||
return;
|
||||
}
|
||||
|
||||
// Should we prompt for a password on stdin?
|
||||
else if (CommandlineInterface::Get().HasParam("--keyask")) {
|
||||
// Create a password prompt
|
||||
std::string password = PasswordPrompt();
|
||||
|
||||
key = Key::FromPassword(password);
|
||||
|
||||
// Don't forget to zero string memory.
|
||||
memset(password.data(), 0, password.size());
|
||||
return;
|
||||
}
|
||||
|
||||
// Else:
|
||||
// Should we read from a keyfile?
|
||||
else if (CommandlineInterface::Get().HasParam("--keyfile")) {
|
||||
// Fetch the filename, and read it
|
||||
const std::string filepath = CommandlineInterface::Get()["--keyfile"].GetString();
|
||||
key = Key::LoadFromFile(filepath);
|
||||
return;
|
||||
}
|
||||
|
||||
throw std::runtime_error("No key option found. Is the CLI parser configuration correct?.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const Key& KeyManager::GetKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
std::string KeyManager::PasswordPrompt() {
|
||||
// Disable stdin-echo
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
DWORD mode = 0;
|
||||
GetConsoleMode(hStdin, &mode);
|
||||
SetConsoleMode(hStdin, mode & (~ENABLE_ECHO_INPUT));
|
||||
|
||||
#elif defined __GNUG__
|
||||
termios oldt;
|
||||
tcgetattr(STDIN_FILENO, &oldt);
|
||||
termios newt = oldt;
|
||||
newt.c_lflag &= ~ECHO;
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
||||
|
||||
#endif
|
||||
|
||||
// Prompt stdin
|
||||
std::string password;
|
||||
std::cin >> password;
|
||||
|
||||
// Restore previous config
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
SetConsoleMode(hStdin, mode);
|
||||
|
||||
#elif defined __GNUG__
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||
#endif
|
||||
|
||||
return password;
|
||||
}
|
||||
|
||||
Key KeyManager::key;
|
||||
|
67
GCryptCLI/src/ModuleDecryption.cpp
Normal file
67
GCryptCLI/src/ModuleDecryption.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "ModuleDecryption.h"
|
||||
#include "DataIngestionLayer.h"
|
||||
#include "DataOutputLayer.h"
|
||||
#include "ProgressPrinter.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
|
||||
);
|
||||
|
||||
std::size_t nBlocksDigested = 0;
|
||||
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()) {
|
||||
|
||||
// Print progress, if appropriate
|
||||
ProgressPrinter::PrintIfAppropriate(
|
||||
"Decrypting",
|
||||
nBlocksDigested,
|
||||
IO::DataIngestionLayer::NBlocksRead()
|
||||
);
|
||||
|
||||
const Block cleartext = IO::DataIngestionLayer::GetNextBlock();
|
||||
const Block ciphertext = cipher.Digest(cleartext);
|
||||
nBlocksDigested++;
|
||||
|
||||
// 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;
|
||||
}
|
68
GCryptCLI/src/ModuleEncryption.cpp
Normal file
68
GCryptCLI/src/ModuleEncryption.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "ModuleEncryption.h"
|
||||
#include "DataIngestionLayer.h"
|
||||
#include "DataOutputLayer.h"
|
||||
#include "KeyManager.h"
|
||||
#include "ProgressPrinter.h"
|
||||
#include <GCrypt/GCipher.h>
|
||||
#include <iostream>
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
std::size_t nBlocksDigested = 0;
|
||||
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()) {
|
||||
|
||||
// Print progress, if appropriate
|
||||
ProgressPrinter::PrintIfAppropriate(
|
||||
"Encrypting",
|
||||
nBlocksDigested,
|
||||
IO::DataIngestionLayer::NBlocksRead()
|
||||
);
|
||||
|
||||
const Block cleartext = IO::DataIngestionLayer::GetNextBlock();
|
||||
const Block ciphertext = cipher.Digest(cleartext);
|
||||
nBlocksDigested++;
|
||||
|
||||
// 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;
|
||||
}
|
32
GCryptCLI/src/ModuleGenerateKey.cpp
Normal file
32
GCryptCLI/src/ModuleGenerateKey.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "ModuleGenerateKey.h"
|
||||
#include "DataOutputLayer.h"
|
||||
#include "KeyManager.h"
|
||||
#include "CommandlineInterface.h"
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
using namespace Module;
|
||||
|
||||
void GenerateKey::Run() {
|
||||
|
||||
// Initialize the data output layer
|
||||
IO::DataOutputLayer::Init();
|
||||
|
||||
// Enqueue our single block of data
|
||||
IO::DataOutputLayer::Enqueue(KeyManager::GetKey());
|
||||
|
||||
// Tell the data output layer, that is has received all blocks
|
||||
IO::DataOutputLayer::ReachedEOF();
|
||||
|
||||
// Tell it to write all blocks
|
||||
// (a single call should suffice, but a while-loop is the proper
|
||||
// way to do it)
|
||||
while (!IO::DataOutputLayer::IsFinished()) {
|
||||
IO::DataOutputLayer::WriteBlock();
|
||||
}
|
||||
|
||||
// Destruct the data output layer
|
||||
IO::DataOutputLayer::Destruct();
|
||||
|
||||
return;
|
||||
}
|
||||
|
64
GCryptCLI/src/ModuleHashing.cpp
Normal file
64
GCryptCLI/src/ModuleHashing.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include "ModuleHashing.h"
|
||||
#include "DataIngestionLayer.h"
|
||||
#include "DataOutputLayer.h"
|
||||
#include "ProgressPrinter.h"
|
||||
#include "KeyManager.h"
|
||||
#include <GCrypt/GHash.h>
|
||||
|
||||
using namespace Module;
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
void Hashing::Run() {
|
||||
|
||||
// Initialize the data ingestion layer
|
||||
IO::DataIngestionLayer::Init();
|
||||
|
||||
// Initialize the data output layer
|
||||
IO::DataOutputLayer::Init();
|
||||
|
||||
// Initialize a ghasher
|
||||
GHash hasher;
|
||||
|
||||
// Read in new blocks, if not reached eof
|
||||
std::size_t nBlocksDigested = 0;
|
||||
while (!IO::DataIngestionLayer::IsFinished()) {
|
||||
if (!IO::DataIngestionLayer::ReachedEOF()) {
|
||||
IO::DataIngestionLayer::ReadBlock();
|
||||
}
|
||||
|
||||
// Process a block, if one is ready
|
||||
if (IO::DataIngestionLayer::IsBlockReady()) {
|
||||
|
||||
// Print progress, if appropriate
|
||||
ProgressPrinter::PrintIfAppropriate(
|
||||
"Hashing",
|
||||
nBlocksDigested,
|
||||
IO::DataIngestionLayer::NBlocksRead()
|
||||
);
|
||||
|
||||
const Block cleartext = IO::DataIngestionLayer::GetNextBlock();
|
||||
hasher.Digest(cleartext);
|
||||
nBlocksDigested++;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait until we've finished digesting all blocks
|
||||
// Enqueue that single block (the hash result) to the output layer
|
||||
IO::DataOutputLayer::Enqueue(hasher.GetHashsum());
|
||||
|
||||
// Tell the data output layer that that was the last block
|
||||
IO::DataOutputLayer::ReachedEOF();
|
||||
|
||||
// Dump it
|
||||
while (!IO::DataOutputLayer::IsFinished()) {
|
||||
IO::DataOutputLayer::WriteBlock();
|
||||
}
|
||||
|
||||
// Destruct the data ingestion layer
|
||||
IO::DataIngestionLayer::Destruct();
|
||||
|
||||
// Destruct the data output layer
|
||||
IO::DataOutputLayer::Destruct();
|
||||
|
||||
return;
|
||||
}
|
28
GCryptCLI/src/ProgressPrinter.cpp
Normal file
28
GCryptCLI/src/ProgressPrinter.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "ProgressPrinter.h"
|
||||
#include "CommandlineInterface.h"
|
||||
#include <iostream>
|
||||
|
||||
void ProgressPrinter::PrintIfAppropriate(
|
||||
const std::string& message,
|
||||
const std::size_t current,
|
||||
const std::size_t target
|
||||
) {
|
||||
if (
|
||||
(CommandlineInterface::Get().HasParam("--progress")) &&
|
||||
(current % CommandlineInterface::Get()["--progress-interval"].GetInt32() == 0)
|
||||
) {
|
||||
std::cerr
|
||||
<< message
|
||||
<< "... (Block "
|
||||
<< current + 1
|
||||
<< " / "
|
||||
<< target
|
||||
<< " - " << ((float)(current+1)*100 / target)
|
||||
<< "%)"
|
||||
<< std::endl
|
||||
;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@@ -1,420 +1,41 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <GCrypt/Util.h>
|
||||
#include <GCrypt/Config.h>
|
||||
#include <GCrypt/Cipher.h>
|
||||
#include <GCrypt/Flexblock.h>
|
||||
#include <GCrypt/Block.h>
|
||||
#include "CommandlineInterface.h"
|
||||
|
||||
#include "Bases.h"
|
||||
#include <GeneralUtility/BaseConversion.h>
|
||||
#include <StringTools/StringTools.h>
|
||||
|
||||
// Required for hidden password input
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
#include <Windows.h>
|
||||
#elif defined __GNUG__
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
using namespace ::Leonetienne::GCrypt;
|
||||
using namespace ::Leonetienne::StringTools;
|
||||
using namespace ::Leonetienne::GeneralUtility;
|
||||
|
||||
enum class OPERATION_MODE {
|
||||
ENCRYPT,
|
||||
DECRYPT,
|
||||
HASH
|
||||
};
|
||||
|
||||
namespace {
|
||||
inline std::string Bin2CustomBase(const std::string& bin, const std::vector<std::string>& customSet, const std::string& seperator = "")
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
// Translate to custom set
|
||||
const std::vector<std::string> vec_base_custom =
|
||||
Leonetienne::GeneralUtility::BaseConversion::BaseX_2_Y<std::string, std::vector<std::string>>(bin, "01", customSet);
|
||||
|
||||
// Convert to string
|
||||
for (std::size_t i = 0; i < vec_base_custom.size(); i++)
|
||||
{
|
||||
ss << vec_base_custom[i];
|
||||
|
||||
if (i != vec_base_custom.size() - 1)
|
||||
ss << seperator;
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
inline std::string CustomBase2Bin(const std::string& in, const std::vector<std::string>& customSet, const std::string& seperator = "")
|
||||
{
|
||||
// Split input into symbols
|
||||
const std::vector<std::string> in_symbols = StringTools::Split(in, seperator);
|
||||
|
||||
// Translate to binary
|
||||
std::string binary =
|
||||
Leonetienne::GeneralUtility::BaseConversion::BaseX_2_Y<std::vector<std::string>, std::string>(in_symbols, customSet, std::string("01"));
|
||||
|
||||
// Apply padding to be a multiple of BLOCK_SIZE
|
||||
// Count how many bits we need
|
||||
std::size_t required_size = 0;
|
||||
while (required_size < binary.length())
|
||||
required_size += BLOCK_SIZE;
|
||||
|
||||
// Create a string of that many zeroes
|
||||
std::string padding = "";
|
||||
for (std::size_t i = binary.length(); i < required_size; i++)
|
||||
padding += "0";
|
||||
|
||||
// Prepend it to our bitstring
|
||||
binary = padding + binary;
|
||||
|
||||
return binary;
|
||||
}
|
||||
}
|
||||
|
||||
//! Will prompt a user password from stdin, hiding the input
|
||||
std::string PasswordPrompt()
|
||||
{
|
||||
// Disable stdin-echo
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
DWORD mode = 0;
|
||||
GetConsoleMode(hStdin, &mode);
|
||||
SetConsoleMode(hStdin, mode & (~ENABLE_ECHO_INPUT));
|
||||
|
||||
#elif defined __GNUG__
|
||||
termios oldt;
|
||||
tcgetattr(STDIN_FILENO, &oldt);
|
||||
termios newt = oldt;
|
||||
newt.c_lflag &= ~ECHO;
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
||||
|
||||
#endif
|
||||
|
||||
// Prompt stdin
|
||||
std::string key;
|
||||
std::cin >> key;
|
||||
|
||||
// Restore previous config
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
SetConsoleMode(hStdin, mode);
|
||||
|
||||
#elif defined __GNUG__
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||
|
||||
#endif
|
||||
|
||||
// Return input
|
||||
return key;
|
||||
}
|
||||
|
||||
Block GetEncryptionKey()
|
||||
{
|
||||
// Easy-case: key supplied as param
|
||||
if (CommandlineInterface::Get().HasParam("--key"))
|
||||
return PasswordToKey(CommandlineInterface::Get()["--key"].GetString());
|
||||
|
||||
// Case: Ask for key
|
||||
else if (CommandlineInterface::Get().HasParam("--keyask"))
|
||||
return PasswordToKey(PasswordPrompt());
|
||||
|
||||
// Case: Read key from file
|
||||
else if (CommandlineInterface::Get().HasParam("--keyfile"))
|
||||
{
|
||||
const std::string keyfilepath = CommandlineInterface::Get()["--keyfile"].GetString();
|
||||
|
||||
// Read this many chars
|
||||
const std::size_t maxChars = BLOCK_SIZE / 8;
|
||||
|
||||
// Open ifilestream for keyfile
|
||||
std::ifstream ifs(keyfilepath, std::ios::in | std::ios::binary);
|
||||
|
||||
// Is the file open now? Or were there any issues...
|
||||
if (!ifs.good())
|
||||
{
|
||||
std::cerr << "Unable to open ifilestream for keyfile \"" << keyfilepath << "\"! Aborting..." << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Read these chars to buffer
|
||||
char* ckeyfileContent = new char[maxChars];
|
||||
memset(ckeyfileContent, 0, maxChars * sizeof(char));
|
||||
ifs.read(ckeyfileContent, maxChars);
|
||||
ifs.close();
|
||||
|
||||
// Convert the buffer to a bit block of key size
|
||||
std::stringstream ss;
|
||||
for (std::size_t i = 0; i < maxChars; i++)
|
||||
ss << std::bitset<8>(ckeyfileContent[i]);
|
||||
|
||||
Block key(ss.str());
|
||||
|
||||
// And delete the buffer
|
||||
delete[] ckeyfileContent;
|
||||
ckeyfileContent = nullptr;
|
||||
|
||||
// Return it
|
||||
return key;
|
||||
}
|
||||
|
||||
// Unreachable
|
||||
throw std::runtime_error("This code should not have been reached. Most likely, the cli argument parser failed making sure at least one key method was supplied.");
|
||||
}
|
||||
|
||||
const Flexblock GetInputText(const OPERATION_MODE operationMode)
|
||||
{
|
||||
// Easy-case: input text supplied as param
|
||||
if (CommandlineInterface::Get().HasParam("--intext")) {
|
||||
switch (operationMode) {
|
||||
// Encryption, or hashing mode: We want to return the text as-is, as bits
|
||||
case OPERATION_MODE::ENCRYPT:
|
||||
case OPERATION_MODE::HASH:
|
||||
return StringToBits(CommandlineInterface::Get()["--intext"].GetString());
|
||||
|
||||
// Decryption mode: We need to first convert our input to a bitstring
|
||||
case OPERATION_MODE::DECRYPT:
|
||||
const std::string userInput = CommandlineInterface::Get()["--intext"].GetString();
|
||||
|
||||
// Are we using iobase 2?
|
||||
if (CommandlineInterface::Get().HasParam("--iobase-2"))
|
||||
// Yes: convert to binary from base 2
|
||||
return CustomBase2Bin(userInput, BASE_2);
|
||||
|
||||
// Are we using iobase 8?
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-8"))
|
||||
// Yes: convert to binary from base 8
|
||||
return CustomBase2Bin(userInput, BASE_8);
|
||||
|
||||
// Are we using iobase 10?
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-10"))
|
||||
// Yes: convert to binary from base 10
|
||||
return CustomBase2Bin(userInput, BASE_10);
|
||||
|
||||
// Are we using iobase 64?
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-64"))
|
||||
// Yes: convert to binary from base 64
|
||||
return CustomBase2Bin(userInput, BASE_64);
|
||||
|
||||
// Are we using iobase uwu?
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-uwu"))
|
||||
// Yes: convert to binary from base uwu
|
||||
return CustomBase2Bin(userInput, BASE_UWU, " ");
|
||||
|
||||
// Are we using iobase emoji?
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-ugh"))
|
||||
// Yes: convert to binary from base ugh
|
||||
return CustomBase2Bin(userInput, BASE_UGH, " ");
|
||||
|
||||
// Else, no special output format specified, use hex
|
||||
else
|
||||
return HexstringToBits(userInput);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Case: Read from file
|
||||
else if (CommandlineInterface::Get().HasParam("--infile"))
|
||||
return ReadFileToBits(CommandlineInterface::Get()["--infile"].GetString());
|
||||
|
||||
// Unreachable
|
||||
throw std::runtime_error("This code should not have been reached. Most likely, the cli argument parser failed making sure at least one input method was supplied.");
|
||||
}
|
||||
|
||||
const std::string GetOutfileName(const OPERATION_MODE operationMode)
|
||||
{
|
||||
// Do we have an output file name specified?
|
||||
// Use it.
|
||||
if (CommandlineInterface::Get().HasParam("--ofile"))
|
||||
return CommandlineInterface::Get()["--ofile"].GetString();
|
||||
|
||||
// Else: append a custom postfix to the inputs filename
|
||||
else
|
||||
return CommandlineInterface::Get()["--infile"].GetString() +
|
||||
(operationMode == OPERATION_MODE::ENCRYPT ? ".crypt" : ".plain");
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Init cmdargs
|
||||
CommandlineInterface::Init(argc, argv);
|
||||
|
||||
// Get operation modes
|
||||
OPERATION_MODE opMode;
|
||||
if (CommandlineInterface::Get().HasParam("--encrypt"))
|
||||
opMode = OPERATION_MODE::ENCRYPT;
|
||||
else if (CommandlineInterface::Get().HasParam("--hash"))
|
||||
opMode = OPERATION_MODE::HASH;
|
||||
else if (CommandlineInterface::Get().HasParam("--decrypt"))
|
||||
opMode = OPERATION_MODE::DECRYPT;
|
||||
else
|
||||
// Unreachable
|
||||
throw std::runtime_error("This code should not have been reached. Most likely, the cli argument parser failed making sure at least one mode of operation (-e, -d, -h) was supplied.");
|
||||
|
||||
const bool isFileMode = CommandlineInterface::Get().HasParam("--infile");
|
||||
const bool printDigestionProgress = CommandlineInterface::Get().HasParam("--progress");
|
||||
|
||||
|
||||
// Digest
|
||||
Flexblock output;
|
||||
|
||||
switch (opMode) {
|
||||
case OPERATION_MODE::ENCRYPT: {
|
||||
// Gather input and key
|
||||
const Block encryptionKey = GetEncryptionKey();
|
||||
const Flexblock input = GetInputText(opMode);
|
||||
|
||||
// Create cipher
|
||||
Cipher cipher(encryptionKey);
|
||||
|
||||
// Run it
|
||||
output = cipher.Encipher(input, printDigestionProgress);
|
||||
break;
|
||||
}
|
||||
|
||||
case OPERATION_MODE::DECRYPT: {
|
||||
// Gather input and key
|
||||
const Block encryptionKey = GetEncryptionKey();
|
||||
const Flexblock input = GetInputText(opMode);
|
||||
|
||||
// Create cipher
|
||||
Cipher cipher(encryptionKey);
|
||||
|
||||
// Run it
|
||||
output = cipher.Decipher(input, printDigestionProgress);
|
||||
break;
|
||||
}
|
||||
|
||||
case OPERATION_MODE::HASH: {
|
||||
// Gather input
|
||||
Flexblock input = GetInputText(opMode);
|
||||
|
||||
// Also add an extra left-padded block with the length of the input,
|
||||
// to make sure, H(n) != H(n + 0x0)
|
||||
input += PadStringToLength(Block(input.size()).to_string(), BLOCK_SIZE, '0');
|
||||
|
||||
// Derive an encryption key
|
||||
// This is quiet sensitive, because it absolutely MUST be impossible
|
||||
// to acquire K without already knowing M.
|
||||
// This alone is making this cipher a one-way function.
|
||||
// Just reducing the output is not a solution, because: If len(input) <= BLOCK_SIZE: H(m) = E(m)_k ^ k, with k being 0 <= k <= BLOCK_SIZE. That's not good.
|
||||
//
|
||||
// So here's what we're doing:
|
||||
// - We're going to take the first BLOCK_SIZE bits of the input (it's length is at least that because of the size embedding)
|
||||
// - We're creating a sudo-random initialization vector, seeded with this block.
|
||||
// - That's our encryption key.
|
||||
// This way, the encryption key can only be obtained by already knowing the first BLOCK_SIZE bits of the cleartext.
|
||||
// By not taking in ALL the bits for deriving a key, we're saving a LOT on performance, as otherwise we would basically be encrypting the input THREE times.
|
||||
// Why create an initialization vector at all? To make sure, even an input of only zeroes would provide a strong key
|
||||
const Block encryptionKey = InitializationVector(
|
||||
Block(input.substr(0, BLOCK_SIZE))
|
||||
);
|
||||
|
||||
// Create cipher
|
||||
Cipher cipher(encryptionKey);
|
||||
|
||||
// Run it
|
||||
output = cipher.Encipher(input, printDigestionProgress);
|
||||
|
||||
if (printDigestionProgress) {
|
||||
std::cout << "Done encrypting... Applying reduction function on ciphertext..." << std::endl;
|
||||
std::cout << "This will take about just as long..." << std::endl;
|
||||
}
|
||||
|
||||
// Reduce output to a single block
|
||||
output = ReductionFunction_Flexblock2Block(output).to_string();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Now output the darn thing.
|
||||
// Outputting to a file (only if not hashing)
|
||||
if ((isFileMode) && (opMode != OPERATION_MODE::HASH))
|
||||
{
|
||||
// File mode is a bit different.
|
||||
|
||||
// Dump to stdout?
|
||||
if (CommandlineInterface::Get().HasParam("--ostdout"))
|
||||
{
|
||||
const std::string outstr = BitsToBytes(output);
|
||||
|
||||
// We have to print char-by-char to prevent a nullbyte terminating output.
|
||||
for (std::size_t i = 0; i < outstr.size(); i++)
|
||||
std::cout << outstr[i];
|
||||
}
|
||||
// Else: Dump to file
|
||||
else
|
||||
{
|
||||
const std::string outfileName = GetOutfileName(opMode);
|
||||
WriteBitsToFile(outfileName, output);
|
||||
}
|
||||
}
|
||||
// Else: we are just dealing with a string, or want to print a hashsum
|
||||
else
|
||||
{
|
||||
switch (opMode) {
|
||||
case OPERATION_MODE::ENCRYPT:
|
||||
case OPERATION_MODE::HASH: {
|
||||
|
||||
// We are encrypting or hashing:
|
||||
// Output to stdout as a formatted bytestring
|
||||
std::string formattedCiphertext;
|
||||
|
||||
// Are we using iobase 2?
|
||||
if (CommandlineInterface::Get().HasParam("--iobase-2"))
|
||||
// Yes: convert hex to base 2
|
||||
formattedCiphertext = Bin2CustomBase(output, BASE_2);
|
||||
|
||||
// Are we using iobase 8?
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-8"))
|
||||
// Yes: convert binary to base 8
|
||||
formattedCiphertext = Bin2CustomBase(output, BASE_8);
|
||||
|
||||
// Are we using iobase 10?
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-10"))
|
||||
// Yes: convert binary to base 10
|
||||
formattedCiphertext = Bin2CustomBase(output, BASE_10);
|
||||
|
||||
// Are we using iobase 64?
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-64"))
|
||||
// Yes: convert binary to base 64
|
||||
formattedCiphertext = Bin2CustomBase(output, BASE_64);
|
||||
|
||||
// Are we using iobase uwu?
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-uwu"))
|
||||
// Yes: convert binary to base 64
|
||||
formattedCiphertext = Bin2CustomBase(output, BASE_UWU, " ");
|
||||
|
||||
// Are we using iobase ugh?
|
||||
else if (CommandlineInterface::Get().HasParam("--iobase-ugh"))
|
||||
// Yes: convert binary to base 64
|
||||
formattedCiphertext = Bin2CustomBase(output, BASE_UGH, " ");
|
||||
|
||||
// Else, no special output format specified, use hex
|
||||
else
|
||||
formattedCiphertext = BitsToHexstring(output);
|
||||
|
||||
std::cout << formattedCiphertext << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
case OPERATION_MODE::DECRYPT:
|
||||
// We are just decrypting:
|
||||
// Just print it string-formatted
|
||||
std::cout << BitsToString(output) << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "CommandlineInterface.h"
|
||||
#include "Configuration.h"
|
||||
#include "KeyManager.h"
|
||||
#include "ModuleGenerateKey.h"
|
||||
#include "ModuleEncryption.h"
|
||||
#include "ModuleDecryption.h"
|
||||
#include "ModuleHashing.h"
|
||||
|
||||
int main(int argc, char* const* argv) {
|
||||
|
||||
// Init cli args
|
||||
CommandlineInterface::Init(argc, argv);
|
||||
|
||||
// Parse configuration
|
||||
Configuration::Parse();
|
||||
|
||||
// Prepare the key
|
||||
KeyManager::PrepareKey();
|
||||
|
||||
// Launch our module
|
||||
switch (Configuration::activeModule) {
|
||||
case Configuration::MODULE::ENCRYPTION:
|
||||
Module::Encryption::Run();
|
||||
break;
|
||||
|
||||
case Configuration::MODULE::DECRYPTION:
|
||||
Module::Decryption::Run();
|
||||
break;
|
||||
|
||||
case Configuration::MODULE::GENERATE_KEY:
|
||||
Module::GenerateKey::Run();
|
||||
break;
|
||||
|
||||
case Configuration::MODULE::HASH:
|
||||
Module::Hashing::Run();
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
17965
GCryptCLI/test/Catch2.h
Normal file
17965
GCryptCLI/test/Catch2.h
Normal file
File diff suppressed because it is too large
Load Diff
90
GCryptCLI/test/DataFormatter.cpp
Normal file
90
GCryptCLI/test/DataFormatter.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#include <DataFormatter.h>
|
||||
#include <GCrypt/Key.h>
|
||||
#include <GCrypt/GPrng.h>
|
||||
#include "Catch2.h"
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
// Tests that recoding iobase formats works for individual blocks, with random data
|
||||
TEMPLATE_TEST_CASE_SIG(
|
||||
__FILE__"Data formats can be converted, without changing in value, with indivudual blocks, with random data",
|
||||
"[DataFormatter]",
|
||||
((Configuration::IOBASE_FORMAT formatUnderTest), formatUnderTest),
|
||||
Configuration::IOBASE_FORMAT::BASE_BYTES,
|
||||
Configuration::IOBASE_FORMAT::BASE_2,
|
||||
Configuration::IOBASE_FORMAT::BASE_8,
|
||||
Configuration::IOBASE_FORMAT::BASE_10,
|
||||
Configuration::IOBASE_FORMAT::BASE_16,
|
||||
Configuration::IOBASE_FORMAT::BASE_64,
|
||||
Configuration::IOBASE_FORMAT::BASE_UWU,
|
||||
Configuration::IOBASE_FORMAT::BASE_UGH
|
||||
) {
|
||||
|
||||
// Let's use a GPrng instead of Key::Random,
|
||||
// because Key::Random is rather slow (because it's using hardware events).
|
||||
// We just want randomized data for tests...
|
||||
|
||||
GPrng prng(Key::Random());
|
||||
|
||||
// Let's try 10 different random blocks per test
|
||||
for (std::size_t i = 0; i < 10; i++) {
|
||||
|
||||
// Setup
|
||||
const Block b_initial = prng.GetBlock();
|
||||
|
||||
// Exercise
|
||||
// Convert to a custom base
|
||||
const std::string b_format = DataFormatter::FormatBlock(
|
||||
b_initial,
|
||||
formatUnderTest
|
||||
);
|
||||
|
||||
// Convert back to a block
|
||||
const Block b_retrieved = DataFormatter::DecodeFormat(
|
||||
b_format,
|
||||
formatUnderTest
|
||||
);
|
||||
|
||||
// Verify
|
||||
// Do b_initial and b_retrieved match?
|
||||
REQUIRE(b_initial == b_retrieved);
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that recoding iobase format works
|
||||
TEMPLATE_TEST_CASE_SIG(
|
||||
__FILE__"Data formats can be converted, without changing in value, with indivudual blocks, with very little data (lots of nullbytes)",
|
||||
"[DataFormatter]",
|
||||
((Configuration::IOBASE_FORMAT formatUnderTest), formatUnderTest),
|
||||
Configuration::IOBASE_FORMAT::BASE_BYTES,
|
||||
Configuration::IOBASE_FORMAT::BASE_2,
|
||||
Configuration::IOBASE_FORMAT::BASE_8,
|
||||
Configuration::IOBASE_FORMAT::BASE_10,
|
||||
Configuration::IOBASE_FORMAT::BASE_16,
|
||||
Configuration::IOBASE_FORMAT::BASE_64,
|
||||
Configuration::IOBASE_FORMAT::BASE_UWU,
|
||||
Configuration::IOBASE_FORMAT::BASE_UGH
|
||||
) {
|
||||
|
||||
// Setup
|
||||
Block b_initial;
|
||||
b_initial.FromTextString("Heyu");
|
||||
|
||||
// Exercise
|
||||
// Convert to a custom base
|
||||
const std::string b_format = DataFormatter::FormatBlock(
|
||||
b_initial,
|
||||
formatUnderTest
|
||||
);
|
||||
|
||||
// Convert back to a block
|
||||
const Block b_retrieved = DataFormatter::DecodeFormat(
|
||||
b_format,
|
||||
formatUnderTest
|
||||
);
|
||||
|
||||
// Verify
|
||||
// Do b_initial and b_retrieved match?
|
||||
REQUIRE(b_initial == b_retrieved);
|
||||
}
|
||||
|
2
GCryptCLI/test/main.cpp
Normal file
2
GCryptCLI/test/main.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "Catch2.h"
|
Reference in New Issue
Block a user