Implemented digestion (feeding one block at a time)
This commit is contained in:
parent
71de8270d8
commit
f3b6dc155c
@ -3,37 +3,42 @@
|
||||
#include "GCrypt/Flexblock.h"
|
||||
|
||||
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 {
|
||||
public:
|
||||
explicit Cipher(const Block& key);
|
||||
explicit Cipher(const std::string& password);
|
||||
//! Describes the direction the cipher runs in
|
||||
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(Cipher&& other) noexcept = delete;
|
||||
|
||||
~Cipher();
|
||||
|
||||
//! Will set the key
|
||||
void SetKey(const Block& key);
|
||||
|
||||
//! 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;
|
||||
//! Will digest a data block, and return it
|
||||
Block Digest(const Block& input);
|
||||
|
||||
private:
|
||||
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
|
||||
void ZeroKeyMemory();
|
||||
|
||||
// Initial value for cipher block chaining
|
||||
Block initializationVector;
|
||||
};
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include "GCrypt/Flexblock.h"
|
||||
#include "GCrypt/Block.h"
|
||||
#include "GCrypt/Cipher.h"
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
/** 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);
|
||||
|
||||
private:
|
||||
|
||||
//! Will digest a flexblock with a key
|
||||
static Flexblock DigestFlexblock(const Flexblock& data, const Block& key, const Cipher::CIPHER_DIRECTION direction);
|
||||
|
||||
// No instanciation! >:(
|
||||
GCryptWrapper();
|
||||
};
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <bitset>
|
||||
#include <ostream>
|
||||
#include <istream>
|
||||
#include <vector>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
/** 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) const;
|
||||
SecureBitset<T> operator~() const;
|
||||
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>
|
||||
inline SecureBitset<T> SecureBitset<T>::operator^(const SecureBitset<T>& other) {
|
||||
inline SecureBitset<T> SecureBitset<T>::operator^(const SecureBitset<T>& other) const {
|
||||
SecureBitset bs;
|
||||
bs.bitset = bitset ^ other.bitset;
|
||||
return bs;
|
||||
|
@ -241,7 +241,7 @@ namespace Leonetienne::GCrypt {
|
||||
|
||||
// To provide confusion, xor the blocks together
|
||||
// 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;
|
||||
@ -258,7 +258,7 @@ namespace Leonetienne::GCrypt {
|
||||
|
||||
// To provide confusion, xor the blocks together
|
||||
// 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;
|
||||
|
@ -6,18 +6,22 @@
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
Cipher::Cipher(const Block& key)
|
||||
Cipher::Cipher(const Block& key, const CIPHER_DIRECTION direction)
|
||||
:
|
||||
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;
|
||||
}
|
||||
|
||||
Cipher::Cipher(const std::string& password)
|
||||
Cipher::Cipher(const std::string& password, const CIPHER_DIRECTION direction)
|
||||
:
|
||||
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;
|
||||
}
|
||||
|
||||
@ -28,20 +32,42 @@ namespace Leonetienne::GCrypt {
|
||||
return;
|
||||
}
|
||||
|
||||
void Cipher::SetKey(const Block& key) {
|
||||
ZeroKeyMemory();
|
||||
Block Cipher::Digest(const Block& input) {
|
||||
|
||||
this->key = key;
|
||||
return;
|
||||
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;
|
||||
}
|
||||
|
||||
void Cipher::SetPassword(const std::string& password) {
|
||||
ZeroKeyMemory();
|
||||
case CIPHER_DIRECTION::DECIPHER: {
|
||||
// Rename our input into ciphertext
|
||||
const Block& ciphertext = input;
|
||||
|
||||
key = PasswordToKey(password);
|
||||
return;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Flexblock Cipher::Encipher(const Flexblock& data, bool printProgress) const {
|
||||
// Split cleartext into blocks
|
||||
std::vector<Block> blocks;
|
||||
@ -113,6 +139,7 @@ namespace Leonetienne::GCrypt {
|
||||
// Return it
|
||||
return ss.str();
|
||||
}
|
||||
*/
|
||||
|
||||
// These pragmas only work for MSVC and g++, as far as i know. Beware!!!
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
|
@ -5,15 +5,14 @@
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
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);
|
||||
Cipher cipher(key);
|
||||
|
||||
// Recode the ascii-string to bits
|
||||
const Flexblock cleartext_bits = StringToBits(cleartext);
|
||||
|
||||
// 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
|
||||
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) {
|
||||
// Instanciate our cipher and supply a key
|
||||
// Transform the password to a key
|
||||
const Block key = PasswordToKey(password);
|
||||
Cipher cipher(key);
|
||||
|
||||
// Recode the hex-string to bits
|
||||
const Flexblock ciphertext_bits = HexstringToBits(ciphertext);
|
||||
|
||||
// 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
|
||||
const std::string cleartext = BitsToString(cleartext_bits);
|
||||
@ -45,12 +43,11 @@ namespace Leonetienne::GCrypt {
|
||||
// Read the file to bits
|
||||
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);
|
||||
Cipher cipher(key);
|
||||
|
||||
// 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
|
||||
WriteBitsToFile(filename_out, ciphertext_bits);
|
||||
@ -67,12 +64,11 @@ namespace Leonetienne::GCrypt {
|
||||
// Read the file to bits
|
||||
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);
|
||||
Cipher cipher(key);
|
||||
|
||||
// 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
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user