Renamed class Cipher to GCipher

This commit is contained in:
Leonetienne 2022-05-22 12:51:58 +02:00
parent 1cc01a840d
commit 4e2f99c28e
No known key found for this signature in database
GPG Key ID: C33879CD92E9708C
9 changed files with 119 additions and 191 deletions

View File

@ -5,32 +5,32 @@
namespace Leonetienne::GCrypt { namespace Leonetienne::GCrypt {
/** Class to apply a block/-stream cipher to messages of arbitrary length in a distributed manner /** Class to apply a block/-stream cipher to messages of arbitrary length in a distributed manner
*/ */
class Cipher { class GCipher {
public: public:
//! Describes the direction the cipher runs in //! Describes the direction the cipher runs in
enum class CIPHER_DIRECTION { enum class DIRECTION {
ENCIPHER, ENCIPHER,
DECIPHER DECIPHER
}; };
//! Will initialize this cipher with a key //! Will initialize this cipher with a key
explicit Cipher(const Block& key, const CIPHER_DIRECTION direction); explicit GCipher(const Block& key, const DIRECTION direction);
//! Will initialize this cipher with a key //! Will initialize this cipher with a key
explicit Cipher(const std::string& password, const CIPHER_DIRECTION direction); explicit GCipher(const std::string& password, const DIRECTION direction);
// Disable copying // Disable copying
Cipher(const Cipher& other) = delete; GCipher(const GCipher& other) = delete;
Cipher(Cipher&& other) noexcept = delete; GCipher(GCipher&& other) noexcept = delete;
~Cipher(); ~GCipher();
//! Will digest a data block, and return it //! Will digest a data block, and return it
Block Digest(const Block& input); Block Digest(const Block& input);
private: private:
Block key; Block key;
const CIPHER_DIRECTION direction; const DIRECTION direction;
//! The feistel instance to be used //! The feistel instance to be used
Feistel feistel; Feistel feistel;

View File

@ -2,7 +2,7 @@
#include <string> #include <string>
#include "GCrypt/Flexblock.h" #include "GCrypt/Flexblock.h"
#include "GCrypt/Block.h" #include "GCrypt/Block.h"
#include "GCrypt/Cipher.h" #include "GCrypt/GCipher.h"
namespace Leonetienne::GCrypt { namespace Leonetienne::GCrypt {
/** This class is a wrapper to make working with the GhettoCipher /** This class is a wrapper to make working with the GhettoCipher
@ -31,7 +31,7 @@ namespace Leonetienne::GCrypt {
private: private:
//! Will digest a flexblock with a key //! Will digest a flexblock with a key
static Flexblock DigestFlexblock(const Flexblock& data, const Block& key, const Cipher::CIPHER_DIRECTION direction); static Flexblock DigestFlexblock(const Flexblock& data, const Block& key, const GCipher::DIRECTION direction);
// No instanciation! >:( // No instanciation! >:(
GCryptWrapper(); GCryptWrapper();

View File

@ -3,7 +3,7 @@
#include "GCrypt/Flexblock.h" #include "GCrypt/Flexblock.h"
#include "GCrypt/Block.h" #include "GCrypt/Block.h"
#include "GCrypt/Cipher.h" #include "GCrypt/GCipher.h"
namespace Leonetienne::GCrypt { namespace Leonetienne::GCrypt {
/** This class implements a hash function, based on the GCrypt cipher /** This class implements a hash function, based on the GCrypt cipher
@ -12,8 +12,11 @@ namespace Leonetienne::GCrypt {
public: public:
Hasher(); Hasher();
//! Will add the hash value of `data` to the hashsum //! Will add the hash value of the block `data` to the hashsum.
void Digest(const Block& data); //! WARNING: If you compute hashes using this digestive method,
//! you REALLY REALLY should add a trailing block just containing the cleartext size!
//! You MOST LIKELY just want to use the wrapper function GHash::CalculateHashsum(Flexblock const&) instead!
void DigestBlock(const Block& data);
//! Will return the current hashsum //! Will return the current hashsum
const Block& GetHashsum() const; const Block& GetHashsum() const;
@ -23,7 +26,7 @@ namespace Leonetienne::GCrypt {
private: private:
//! The cipher to use //! The cipher to use
Cipher cipher; GCipher cipher;
//! The current state of the hashsum //! The current state of the hashsum
Block block; Block block;

View File

@ -9,7 +9,7 @@
#include "GCrypt/Block.h" #include "GCrypt/Block.h"
#include "GCrypt/Flexblock.h" #include "GCrypt/Flexblock.h"
#include "GCrypt/Config.h" #include "GCrypt/Config.h"
#include "GCrypt/Cipher.h" #include "GCrypt/GCipher.h"
#include "GCrypt/InitializationVector.h" #include "GCrypt/InitializationVector.h"
namespace Leonetienne::GCrypt { namespace Leonetienne::GCrypt {

View File

@ -1,163 +0,0 @@
#include <iostream>
#include <vector>
#include <stdexcept>
#include "GCrypt/Cipher.h"
#include "GCrypt/Util.h"
#include "GCrypt/InitializationVector.h"
namespace Leonetienne::GCrypt {
Cipher::Cipher(const Block& key, const CIPHER_DIRECTION direction)
:
key { key },
direction { direction },
lastBlock(InitializationVector(key)), // Initialize our lastBlock with some deterministic initial value, based on the key
feistel(key) {
return;
}
Cipher::Cipher(const std::string& password, const CIPHER_DIRECTION direction)
:
key { PasswordToKey(password) },
direction { direction },
lastBlock(InitializationVector(key)), // Initialize our lastBlock with some deterministic initial value, based on the key feistel(key) {
feistel(key) {
return;
}
Cipher::~Cipher() {
// Clear key memory
ZeroKeyMemory();
return;
}
Block Cipher::Digest(const Block& input) {
switch (direction) {
case CIPHER_DIRECTION::ENCIPHER: {
// Rename our input to cleartext
const Block& cleartext = input;
// First, xor our cleartext with the last block, and then encipher it
Block ciphertext = feistel.Encipher(cleartext ^ lastBlock);
// Now set our lastBlock to the ciphertext of this block
lastBlock = ciphertext;
// Now return the ciphertext
return ciphertext;
}
case CIPHER_DIRECTION::DECIPHER: {
// Rename our input into ciphertext
const Block& ciphertext = input;
// First, decipher our ciphertext, and then xor it with our last block
Block cleartext = feistel.Decipher(ciphertext) ^ lastBlock;
// Now set our lastBLock to the ciphertext of this block
lastBlock = ciphertext;
// Now return the cleartext
return cleartext;
}
}
throw std::runtime_error("Unreachable branch reached.");
}
/*
Flexblock Cipher::Encipher(const Flexblock& data, bool printProgress) const {
// Split cleartext into blocks
std::vector<Block> blocks;
for (std::size_t i = 0; i < data.size(); i += BLOCK_SIZE) {
blocks.push_back(Block(
PadStringToLength(data.substr(i, BLOCK_SIZE), BLOCK_SIZE, '0', false))
);
}
// Encrypt individual blocks using cipher block chaining
Feistel feistel(key);
for (std::size_t i = 0; i < blocks.size(); i++) {
// Print reports if desired. If we have > 1000 blocks, print one report every 100 blocks. Otherwise for every 10th block.
if ((i % ((blocks.size() > 1000)? 100 : 10) == 0) && (printProgress)) {
std::cout << "Encrypting... (Block " << i << " / " << blocks.size() << " - " << ((float)i*100 / blocks.size()) << "%)" << std::endl;
}
const Block& lastBlock = (i>0) ? blocks[i-1] : initializationVector;
blocks[i] = feistel.Encipher(blocks[i] ^ lastBlock); // Xor last cipher block with new clear text block before E()
}
// Concatenate ciphertext blocks back into a flexblock
std::stringstream ss;
for (Block& b : blocks) {
ss << b;
}
// Return it
return ss.str();
}
Flexblock Cipher::Decipher(const Flexblock& data, bool printProgress) const {
// Split ciphertext into blocks
std::vector<Block> blocks;
for (std::size_t i = 0; i < data.size(); i += BLOCK_SIZE) {
blocks.push_back(Block(
PadStringToLength(data.substr(i, BLOCK_SIZE), BLOCK_SIZE, '0', false))
);
}
// Decrypt individual blocks
Feistel feistel(key);
// We can't do this in-loop for decryption, because we are decrypting the blocks in-place.
Block lastBlock = initializationVector;
for (std::size_t i = 0; i < blocks.size(); i++) {
// Print reports if desired. If we have > 1000 blocks, print one report every 100 blocks. Otherwise for every 10th block.
if ((i % ((blocks.size() > 1000) ? 100 : 10) == 0) && (printProgress)) {
std::cout << "Decrypting... (Block " << i << " / " << blocks.size() << " - " << ((float)i*100/ blocks.size()) << "%)" << std::endl;
}
Block tmpCopy = blocks[i];
blocks[i] = feistel.Decipher(blocks[i]) ^ lastBlock; // Decipher cipher block [i] and then xor it with the last cipher block [i-1] we've had
lastBlock = std::move(tmpCopy);
}
// Concatenate ciphertext blocks back into a flexblock
std::stringstream ss;
for (Block& b : blocks) {
ss << b;
}
// Return it
return ss.str();
}
*/
// These pragmas only work for MSVC and g++, as far as i know. Beware!!!
#if defined _WIN32 || defined _WIN64
#pragma optimize("", off )
#elif defined __GNUG__
#pragma GCC push_options
#pragma GCC optimize ("O0")
#endif
void Cipher::ZeroKeyMemory() {
key.reset();
return;
}
#if defined _WIN32 || defined _WIN64
#pragma optimize("", on )
#elif defined __GNUG__
#pragma GCC pop_options
#endif
}

89
GCryptLib/src/GCipher.cpp Normal file
View File

@ -0,0 +1,89 @@
#include <iostream>
#include <vector>
#include <stdexcept>
#include "GCrypt/GCipher.h"
#include "GCrypt/Util.h"
#include "GCrypt/InitializationVector.h"
namespace Leonetienne::GCrypt {
GCipher::GCipher(const Block& key, const DIRECTION direction)
:
key { key },
direction { direction },
lastBlock(InitializationVector(key)), // Initialize our lastBlock with some deterministic initial value, based on the key
feistel(key) {
return;
}
GCipher::GCipher(const std::string& password, const DIRECTION direction)
:
key { PasswordToKey(password) },
direction { direction },
lastBlock(InitializationVector(key)), // Initialize our lastBlock with some deterministic initial value, based on the key feistel(key) {
feistel(key) {
return;
}
GCipher::~GCipher() {
// Clear key memory
ZeroKeyMemory();
return;
}
Block GCipher::Digest(const Block& input) {
switch (direction) {
case DIRECTION::ENCIPHER: {
// Rename our input to cleartext
const Block& cleartext = input;
// First, xor our cleartext with the last block, and then encipher it
Block ciphertext = feistel.Encipher(cleartext ^ lastBlock);
// Now set our lastBlock to the ciphertext of this block
lastBlock = ciphertext;
// Now return the ciphertext
return ciphertext;
}
case DIRECTION::DECIPHER: {
// Rename our input into ciphertext
const Block& ciphertext = input;
// First, decipher our ciphertext, and then xor it with our last block
Block cleartext = feistel.Decipher(ciphertext) ^ lastBlock;
// Now set our lastBLock to the ciphertext of this block
lastBlock = ciphertext;
// Now return the cleartext
return cleartext;
}
}
throw std::runtime_error("Unreachable branch reached.");
}
// These pragmas only work for MSVC and g++, as far as i know. Beware!!!
#if defined _WIN32 || defined _WIN64
#pragma optimize("", off )
#elif defined __GNUG__
#pragma GCC push_options
#pragma GCC optimize ("O0")
#endif
void GCipher::ZeroKeyMemory() {
key.reset();
return;
}
#if defined _WIN32 || defined _WIN64
#pragma optimize("", on )
#elif defined __GNUG__
#pragma GCC pop_options
#endif
}

View File

@ -1,5 +1,5 @@
#include "GCrypt/GCryptWrapper.h" #include "GCrypt/GCryptWrapper.h"
#include "GCrypt/Cipher.h" #include "GCrypt/GCipher.h"
#include "GCrypt/Util.h" #include "GCrypt/Util.h"
namespace Leonetienne::GCrypt { namespace Leonetienne::GCrypt {
@ -12,7 +12,7 @@ namespace Leonetienne::GCrypt {
const Flexblock cleartext_bits = StringToBits(cleartext); const Flexblock cleartext_bits = StringToBits(cleartext);
// Encrypt our cleartext bits // Encrypt our cleartext bits
const Flexblock ciphertext_bits = DigestFlexblock(cleartext_bits, key, Cipher::CIPHER_DIRECTION::ENCIPHER); const Flexblock ciphertext_bits = DigestFlexblock(cleartext_bits, key, GCipher::DIRECTION::ENCIPHER);
// Recode the ciphertext bits to a hex-string // Recode the ciphertext bits to a hex-string
const std::string ciphertext = BitsToHexstring(ciphertext_bits); const std::string ciphertext = BitsToHexstring(ciphertext_bits);
@ -29,7 +29,7 @@ namespace Leonetienne::GCrypt {
const Flexblock ciphertext_bits = HexstringToBits(ciphertext); const Flexblock ciphertext_bits = HexstringToBits(ciphertext);
// Decrypt the ciphertext bits // Decrypt the ciphertext bits
const std::string cleartext_bits = DigestFlexblock(ciphertext_bits, key, Cipher::CIPHER_DIRECTION::DECIPHER); const std::string cleartext_bits = DigestFlexblock(ciphertext_bits, key, GCipher::DIRECTION::DECIPHER);
// Recode the cleartext bits to an ascii-string // Recode the cleartext bits to an ascii-string
const std::string cleartext = BitsToString(cleartext_bits); const std::string cleartext = BitsToString(cleartext_bits);
@ -47,7 +47,7 @@ namespace Leonetienne::GCrypt {
const Block key = PasswordToKey(password); const Block key = PasswordToKey(password);
// Encrypt our cleartext bits // Encrypt our cleartext bits
const Flexblock ciphertext_bits = DigestFlexblock(cleartext_bits, key, Cipher::CIPHER_DIRECTION::ENCIPHER); const Flexblock ciphertext_bits = DigestFlexblock(cleartext_bits, key, GCipher::DIRECTION::ENCIPHER);
// Write our ciphertext bits to file // Write our ciphertext bits to file
WriteBitsToFile(filename_out, ciphertext_bits); WriteBitsToFile(filename_out, ciphertext_bits);
@ -68,7 +68,7 @@ namespace Leonetienne::GCrypt {
const Block key = PasswordToKey(password); const Block key = PasswordToKey(password);
// Decrypt the ciphertext bits // Decrypt the ciphertext bits
const Flexblock cleartext_bits = DigestFlexblock(ciphertext_bits, key, Cipher::CIPHER_DIRECTION::DECIPHER); const Flexblock cleartext_bits = DigestFlexblock(ciphertext_bits, key, GCipher::DIRECTION::DECIPHER);
// Write our cleartext bits to file // Write our cleartext bits to file
WriteBitsToFile(filename_out, cleartext_bits); WriteBitsToFile(filename_out, cleartext_bits);
@ -80,7 +80,7 @@ namespace Leonetienne::GCrypt {
} }
} }
Flexblock GCryptWrapper::DigestFlexblock(const Flexblock& data, const Block& key, const Cipher::CIPHER_DIRECTION direction) { Flexblock GCryptWrapper::DigestFlexblock(const Flexblock& data, const Block& key, const GCipher::DIRECTION direction) {
// Split input into blocks // Split input into blocks
std::vector<Block> blocks; std::vector<Block> blocks;
@ -91,9 +91,8 @@ namespace Leonetienne::GCrypt {
} }
// Create cipher instance // Create cipher instance
Cipher cipher(key, direction); GCipher cipher(key, direction);
// Digest all blocks
for (Block& block : blocks) { for (Block& block : blocks) {
block = cipher.Digest(block); block = cipher.Digest(block);
} }

View File

@ -8,14 +8,14 @@ namespace Leonetienne::GCrypt {
// Initialize our cipher with a static, but randomly distributed key. // Initialize our cipher with a static, but randomly distributed key.
cipher( cipher(
StringToBitblock("CfRtNdMTP4Y5CWRd"), StringToBitblock("CfRtNdMTP4Y5CWRd"),
Cipher::CIPHER_DIRECTION::ENCIPHER GCipher::DIRECTION::ENCIPHER
) { ) {
block = InitializationVector(StringToBitblock("3J7IipfQTDJbO8jtasz9PgWui6faPaEMOuVuAqyhB1S2CRcLw5caawewgDUEG1WN")); block = InitializationVector(StringToBitblock("3J7IipfQTDJbO8jtasz9PgWui6faPaEMOuVuAqyhB1S2CRcLw5caawewgDUEG1WN"));
return; return;
} }
void Hasher::Digest(const Block& data) { void Hasher::DigestBlock(const Block& data) {
// Encipher the current block, and xor it on the current hashsum // Encipher the current block, and xor it on the current hashsum
block ^= cipher.Digest(data); block ^= cipher.Digest(data);
return; return;
@ -46,7 +46,7 @@ namespace Leonetienne::GCrypt {
// Digest all blocks // Digest all blocks
for (Block& block : blocks) { for (Block& block : blocks) {
hasher.Digest(block); hasher.DigestBlock(block);
} }
// Return the total hashsum // Return the total hashsum

View File

@ -11,7 +11,7 @@ TEST_CASE(__FILE__"/SingleBlock_NoPadding", "[Encryption/Decryption consistency]
// Instanciate our cipher and supply a key // Instanciate our cipher and supply a key
const Block key = PasswordToKey("1234"); const Block key = PasswordToKey("1234");
const Cipher cipher(key); const Cipher cipher(key, Cipher::CIPHER_DIRECTION::Encryption);
// Recode the ascii-string to bits // Recode the ascii-string to bits
const Flexblock cleartext_bits = const Flexblock cleartext_bits =