Implemented digestion (feeding one block at a time)

This commit is contained in:
Leonetienne 2022-05-21 20:41:09 +02:00
parent 71de8270d8
commit f3b6dc155c
No known key found for this signature in database
GPG Key ID: 0297FC11AD9236EF
6 changed files with 111 additions and 48 deletions

View File

@ -3,37 +3,42 @@
#include "GCrypt/Flexblock.h" #include "GCrypt/Flexblock.h"
namespace Leonetienne::GCrypt { namespace Leonetienne::GCrypt {
/** Class to apply a block 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 Cipher {
public: public:
explicit Cipher(const Block& key); //! Describes the direction the cipher runs in
explicit Cipher(const std::string& password); enum class CIPHER_DIRECTION {
ENCIPHER,
DECIPHER
};
//! Will initialize this cipher with a key
explicit Cipher(const Block& key, const CIPHER_DIRECTION direction);
//! Will initialize this cipher with a key
explicit Cipher(const std::string& password, const CIPHER_DIRECTION direction);
// Disable copying
Cipher(const Cipher& other) = delete; Cipher(const Cipher& other) = delete;
Cipher(Cipher&& other) noexcept = delete; Cipher(Cipher&& other) noexcept = delete;
~Cipher(); ~Cipher();
//! Will set the key //! Will digest a data block, and return it
void SetKey(const Block& key); Block Digest(const Block& input);
//! Will set the key from a password
void SetPassword(const std::string& password);
//! Will encipher a flexblock of data
Flexblock Encipher(const Flexblock& data, bool printProgress = false) const;
//! Will decipher a flexblock of data
Flexblock Decipher(const Flexblock& data, bool printProgress = false) const;
private: private:
Block key; Block key;
const CIPHER_DIRECTION direction;
//! The feistel instance to be used
Feistel feistel;
//! The last block, required for CBC.
Block lastBlock;
//! Will zero the memory used by the key //! Will zero the memory used by the key
void ZeroKeyMemory(); void ZeroKeyMemory();
// Initial value for cipher block chaining
Block initializationVector;
}; };
} }

View File

@ -1,5 +1,8 @@
#pragma once #pragma once
#include <string> #include <string>
#include "GCrypt/Flexblock.h"
#include "GCrypt/Block.h"
#include "GCrypt/Cipher.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
@ -26,6 +29,10 @@ namespace Leonetienne::GCrypt {
static bool DecryptFile(const std::string& filename_in, const std::string& filename_out, const std::string& password, bool printProgressReport = false); static bool DecryptFile(const std::string& filename_in, const std::string& filename_out, const std::string& password, bool printProgressReport = false);
private: private:
//! Will digest a flexblock with a key
static Flexblock DigestFlexblock(const Flexblock& data, const Block& key, const Cipher::CIPHER_DIRECTION direction);
// No instanciation! >:( // No instanciation! >:(
GCryptWrapper(); GCryptWrapper();
}; };

View File

@ -2,6 +2,7 @@
#include <bitset> #include <bitset>
#include <ostream> #include <ostream>
#include <istream> #include <istream>
#include <vector>
namespace Leonetienne::GCrypt { namespace Leonetienne::GCrypt {
/** Wrapper for std::bitset<T> that zeroes memory upon deletion. /** Wrapper for std::bitset<T> that zeroes memory upon deletion.
@ -32,7 +33,7 @@ namespace Leonetienne::GCrypt {
SecureBitset<T>& operator^=(const SecureBitset<T>& other); SecureBitset<T>& operator^=(const SecureBitset<T>& other);
SecureBitset<T> operator&(const SecureBitset<T>& other); SecureBitset<T> operator&(const SecureBitset<T>& other);
SecureBitset<T> operator|(const SecureBitset<T>& other); SecureBitset<T> operator|(const SecureBitset<T>& other);
SecureBitset<T> operator^(const SecureBitset<T>& other); SecureBitset<T> operator^(const SecureBitset<T>& other) const;
SecureBitset<T> operator~() const; SecureBitset<T> operator~() const;
SecureBitset<T>& operator<<=(const std::size_t offset); SecureBitset<T>& operator<<=(const std::size_t offset);
SecureBitset<T>& operator>>=(const std::size_t offset); SecureBitset<T>& operator>>=(const std::size_t offset);
@ -174,7 +175,7 @@ namespace Leonetienne::GCrypt {
} }
template<std::size_t T> template<std::size_t T>
inline SecureBitset<T> SecureBitset<T>::operator^(const SecureBitset<T>& other) { inline SecureBitset<T> SecureBitset<T>::operator^(const SecureBitset<T>& other) const {
SecureBitset bs; SecureBitset bs;
bs.bitset = bitset ^ other.bitset; bs.bitset = bitset ^ other.bitset;
return bs; return bs;

View File

@ -241,7 +241,7 @@ namespace Leonetienne::GCrypt {
// To provide confusion, xor the blocks together // To provide confusion, xor the blocks together
// To provide diffusion, hash fragment to fragment' first // To provide diffusion, hash fragment to fragment' first
b ^= Block(Cipher(fragment).Encipher(fragment.to_string())); b ^= Block(Cipher(fragment, Cipher::CIPHER_DIRECTION::ENCIPHER).Digest(fragment).to_string());
} }
return b; return b;
@ -258,7 +258,7 @@ namespace Leonetienne::GCrypt {
// To provide confusion, xor the blocks together // To provide confusion, xor the blocks together
// To provide diffusion, hash fragment to fragment' first // To provide diffusion, hash fragment to fragment' first
b ^= Block(Cipher(fragment).Encipher(fragment.to_string())); b ^= Block(Cipher(fragment, Cipher::CIPHER_DIRECTION::ENCIPHER).Digest(fragment).to_string());
} }
return b; return b;

View File

@ -6,18 +6,22 @@
namespace Leonetienne::GCrypt { namespace Leonetienne::GCrypt {
Cipher::Cipher(const Block& key) Cipher::Cipher(const Block& key, const CIPHER_DIRECTION direction)
: :
key { key }, key { key },
initializationVector(InitializationVector(key)) { direction { direction },
lastBlock(InitializationVector(key)), // Initialize our lastBlock with some deterministic initial value, based on the key
feistel(key) {
return; return;
} }
Cipher::Cipher(const std::string& password) Cipher::Cipher(const std::string& password, const CIPHER_DIRECTION direction)
: :
key { PasswordToKey(password) }, key { PasswordToKey(password) },
initializationVector(InitializationVector(key)) { direction { direction },
lastBlock(InitializationVector(key)), // Initialize our lastBlock with some deterministic initial value, based on the key feistel(key) {
feistel(key) {
return; return;
} }
@ -28,20 +32,42 @@ namespace Leonetienne::GCrypt {
return; return;
} }
void Cipher::SetKey(const Block& key) { Block Cipher::Digest(const Block& input) {
ZeroKeyMemory();
this->key = key; switch (direction) {
return; 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;
} }
void Cipher::SetPassword(const std::string& password) { case CIPHER_DIRECTION::DECIPHER: {
ZeroKeyMemory(); // Rename our input into ciphertext
const Block& ciphertext = input;
key = PasswordToKey(password); // First, decipher our ciphertext, and then xor it with our last block
return; Block cleartext = feistel.Decipher(ciphertext) ^ lastBlock;
// Now set our lastBLock to the ciphertext of this block
lastBlock = ciphertext;
// Now return the cleartext
return cleartext;
}
} }
}
/*
Flexblock Cipher::Encipher(const Flexblock& data, bool printProgress) const { Flexblock Cipher::Encipher(const Flexblock& data, bool printProgress) const {
// Split cleartext into blocks // Split cleartext into blocks
std::vector<Block> blocks; std::vector<Block> blocks;
@ -113,6 +139,7 @@ namespace Leonetienne::GCrypt {
// Return it // Return it
return ss.str(); return ss.str();
} }
*/
// These pragmas only work for MSVC and g++, as far as i know. Beware!!! // These pragmas only work for MSVC and g++, as far as i know. Beware!!!
#if defined _WIN32 || defined _WIN64 #if defined _WIN32 || defined _WIN64

View File

@ -5,15 +5,14 @@
namespace Leonetienne::GCrypt { namespace Leonetienne::GCrypt {
std::string GCryptWrapper::EncryptString(const std::string& cleartext, const std::string& password) { std::string GCryptWrapper::EncryptString(const std::string& cleartext, const std::string& password) {
// Instanciate our cipher and supply a key // Transform the password to a key
const Block key = PasswordToKey(password); const Block key = PasswordToKey(password);
Cipher cipher(key);
// Recode the ascii-string to bits // Recode the ascii-string to bits
const Flexblock cleartext_bits = StringToBits(cleartext); const Flexblock cleartext_bits = StringToBits(cleartext);
// Encrypt our cleartext bits // Encrypt our cleartext bits
const Flexblock ciphertext_bits = cipher.Encipher(cleartext_bits); const Flexblock ciphertext_bits = DigestFlexblock(cleartext_bits, key, Cipher::CIPHER_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);
@ -23,15 +22,14 @@ namespace Leonetienne::GCrypt {
} }
std::string GCryptWrapper::DecryptString(const std::string& ciphertext, const std::string& password) { std::string GCryptWrapper::DecryptString(const std::string& ciphertext, const std::string& password) {
// Instanciate our cipher and supply a key // Transform the password to a key
const Block key = PasswordToKey(password); const Block key = PasswordToKey(password);
Cipher cipher(key);
// Recode the hex-string to bits // Recode the hex-string to bits
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 = cipher.Decipher(ciphertext_bits); const std::string cleartext_bits = DigestFlexblock(ciphertext_bits, key, Cipher::CIPHER_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);
@ -45,12 +43,11 @@ namespace Leonetienne::GCrypt {
// Read the file to bits // Read the file to bits
const Flexblock cleartext_bits = ReadFileToBits(filename_in); const Flexblock cleartext_bits = ReadFileToBits(filename_in);
// Instanciate our cipher and supply a key // Transform the password to a key
const Block key = PasswordToKey(password); const Block key = PasswordToKey(password);
Cipher cipher(key);
// Encrypt our cleartext bits // Encrypt our cleartext bits
const Flexblock ciphertext_bits = cipher.Encipher(cleartext_bits, printProgressReport); const Flexblock ciphertext_bits = DigestFlexblock(cleartext_bits, key, Cipher::CIPHER_DIRECTION::ENCIPHER);
// Write our ciphertext bits to file // Write our ciphertext bits to file
WriteBitsToFile(filename_out, ciphertext_bits); WriteBitsToFile(filename_out, ciphertext_bits);
@ -67,12 +64,11 @@ namespace Leonetienne::GCrypt {
// Read the file to bits // Read the file to bits
const Flexblock ciphertext_bits = ReadFileToBits(filename_in); const Flexblock ciphertext_bits = ReadFileToBits(filename_in);
// Instanciate our cipher and supply a key // Transform the password to a key
const Block key = PasswordToKey(password); const Block key = PasswordToKey(password);
Cipher cipher(key);
// Decrypt the ciphertext bits // Decrypt the ciphertext bits
const Flexblock cleartext_bits = cipher.Decipher(ciphertext_bits, printProgressReport); const Flexblock cleartext_bits = DigestFlexblock(ciphertext_bits, key, Cipher::CIPHER_DIRECTION::DECIPHER);
// Write our cleartext bits to file // Write our cleartext bits to file
WriteBitsToFile(filename_out, cleartext_bits); WriteBitsToFile(filename_out, cleartext_bits);
@ -84,5 +80,32 @@ namespace Leonetienne::GCrypt {
} }
} }
Flexblock GCryptWrapper::DigestFlexblock(const Flexblock& data, const Block& key, const Cipher::CIPHER_DIRECTION direction) {
// Split input 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))
);
}
// Create cipher instance
Cipher cipher(key, direction);
// Digest all blocks
for (Block& block : blocks) {
block = cipher.Digest(block);
}
// Concatenate ciphertext blocks back into a flexblock
std::stringstream ss;
for (Block& b : blocks) {
ss << b;
}
// Return it
return ss.str();
}
} }