Got rid of flexblocks
This commit is contained in:
parent
143ec19bf3
commit
e7c1e17e2c
@ -10,6 +10,10 @@ namespace Leonetienne::GCrypt {
|
||||
*/
|
||||
class Feistel {
|
||||
public:
|
||||
//! Empty initializer. If you use this, you must call SetKey()!
|
||||
Feistel();
|
||||
|
||||
//! Will initialize the feistel cipher with a key
|
||||
explicit Feistel(const Key& key);
|
||||
|
||||
Feistel(const Feistel& other) = delete;
|
||||
@ -59,6 +63,8 @@ namespace Leonetienne::GCrypt {
|
||||
void ZeroKeyMemory();
|
||||
|
||||
Keyset roundKeys;
|
||||
|
||||
bool isInitialized = false;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,16 +0,0 @@
|
||||
#ifndef GCRYPT_FLEXBLOCK_H
|
||||
#define GCRYPT_FLEXBLOCK_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
//! A type used for conveying "bitstrings". e.g. "10101001001"
|
||||
//! These should generally not be used, as they are really really slow.
|
||||
//! The only valid usecase I can think of is when using GHash for example, because for hashing
|
||||
//! an absolute input length is required.
|
||||
//! If you need to, you can use the StringToBits() and BitsToString() functions defined in Util.h.
|
||||
typedef std::string Flexblock;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -2,7 +2,6 @@
|
||||
#define GCRYPT_GCIPHER_H
|
||||
|
||||
#include "GCrypt/Feistel.h"
|
||||
#include "GCrypt/Flexblock.h"
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
/** Class to apply a block/-stream cipher to messages of arbitrary length in a distributed manner
|
||||
@ -15,6 +14,9 @@ namespace Leonetienne::GCrypt {
|
||||
DECIPHER
|
||||
};
|
||||
|
||||
//! Empty initializer. If you use this, you must call Initialize()!
|
||||
GCipher();
|
||||
|
||||
//! Will initialize this cipher with a key
|
||||
explicit GCipher(const Key& key, const DIRECTION direction);
|
||||
|
||||
@ -30,6 +32,11 @@ namespace Leonetienne::GCrypt {
|
||||
|
||||
void operator=(const GCipher& other);
|
||||
|
||||
|
||||
//! Will initialize the cipher with a key, and a mode.
|
||||
//! If called on an existing object, it will reset its state.
|
||||
void Initialize(const Key& key, const DIRECTION direction);
|
||||
|
||||
private:
|
||||
DIRECTION direction;
|
||||
|
||||
@ -38,6 +45,8 @@ namespace Leonetienne::GCrypt {
|
||||
|
||||
//! The last block, required for CBC.
|
||||
Block lastBlock;
|
||||
|
||||
bool isInitialized = false;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
#ifndef GCRYPT_GHASH_H
|
||||
#define GCRYPT_GHASH_H
|
||||
|
||||
#include "GCrypt/Flexblock.h"
|
||||
#include "GCrypt/Block.h"
|
||||
#include "GCrypt/GCipher.h"
|
||||
#include <vector>
|
||||
|
@ -36,7 +36,12 @@ namespace Leonetienne::GCrypt {
|
||||
}
|
||||
|
||||
// Transform to bytes
|
||||
const std::string bytes = BitsToBytes(ss.str());
|
||||
const std::string bits = ss.str();
|
||||
ss.str("");
|
||||
for (std::size_t i = 0; i < bits.size(); i += 8) {
|
||||
ss << (char)std::bitset<8>(bits.substr(i, 8)).to_ulong();
|
||||
}
|
||||
const std::string bytes = ss.str();
|
||||
|
||||
// Cram bytes into type
|
||||
T t;
|
||||
|
@ -1,10 +1,11 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include "GCrypt/Flexblock.h"
|
||||
#ifndef GCRYPT_GWRAPPER_H
|
||||
#define GCRYPT_GWRAPPER_H
|
||||
|
||||
#include "GCrypt/Block.h"
|
||||
#include "GCrypt/GCipher.h"
|
||||
#include "GCrypt/Key.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
/** This class is a wrapper to make working with the GhettoCipher
|
||||
@ -31,7 +32,7 @@ namespace Leonetienne::GCrypt {
|
||||
static bool DecryptFile(const std::string& filename_in, const std::string& filename_out, const Key& key, bool printProgressReport = false);
|
||||
|
||||
//! Will enncrypt or decrypt an entire flexblock of binary data, given a key.
|
||||
static Flexblock CipherFlexblock(const Flexblock& data, const Key& key, const GCipher::DIRECTION direction);
|
||||
static std::vector<Block> CipherBlocks(const std::vector<Block>& data, const Key& key, const GCipher::DIRECTION direction);
|
||||
|
||||
private:
|
||||
|
||||
@ -40,3 +41,5 @@ namespace Leonetienne::GCrypt {
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include "GCrypt/Block.h"
|
||||
#include "GCrypt/Flexblock.h"
|
||||
#include "GCrypt/Config.h"
|
||||
#include "GCrypt/GCipher.h"
|
||||
#include "GCrypt/InitializationVector.h"
|
||||
@ -21,56 +20,16 @@ namespace Leonetienne::GCrypt {
|
||||
//! Will pad a string to a set length with a certain character
|
||||
std::string PadStringToLength(const std::string& str, const std::size_t len, const char pad, const bool padLeft = true);
|
||||
|
||||
//! Will convert a string to a fixed-size data block
|
||||
//! @s: The string to pad
|
||||
//! padLeft: should padding be added to the left? If not, to the right.
|
||||
Block StringToBitblock(const std::string& s, bool padLeft = true);
|
||||
|
||||
//! Will convert a string to a flexible data block
|
||||
Flexblock StringToBits(const std::string& s);
|
||||
|
||||
//! Will convert a string to a vector of blocks
|
||||
std::vector<Block> StringToBitblocks(const std::string& str);
|
||||
|
||||
//! Will convert a fixed-size data block to a bytestring
|
||||
std::string BitblockToBytes(const Block& block);
|
||||
|
||||
//! Will convert an array of data blocks to a bytestring
|
||||
std::string BitblocksToBytes(const std::vector<Block>& bits);
|
||||
|
||||
//! Will convert a fixed-size data blocks to a textstring
|
||||
//! The difference to BitblockToBytes() is, that it strips excess nullbytes
|
||||
std::string BitblockToString(const Block& block);
|
||||
|
||||
//! Will convert an array of blocks to a character-string
|
||||
//! The difference to BitblocksToBytes() is, that it strips excess nullbytes
|
||||
std::string BitblocksToString(const std::vector<Block>& blocks);
|
||||
|
||||
//! Will convert a flexible data block to a bytestring
|
||||
std::string BitsToBytes(const Flexblock& bits);
|
||||
|
||||
//! Will convert a flexible data block to a string
|
||||
//! The difference to BitsToBytes() is, that it strips excess nullbytes
|
||||
std::string BitsToString(const Flexblock& bits);
|
||||
|
||||
//! Turns a fixed-size data block into a hex-string
|
||||
std::string BitblockToHexstring(const Block& b);
|
||||
|
||||
//! Turns a flexible data block into a hex-string
|
||||
std::string BitsToHexstring(const Flexblock& b);
|
||||
|
||||
//! Turns a hex string into a fixed-size data block
|
||||
Block HexstringToBitblock(const std::string& hexstring);
|
||||
|
||||
//! Turns a hex string into a flexible data block
|
||||
Flexblock HexstringToBits(const std::string& hexstring);
|
||||
|
||||
//! Will read a file into a flexblock
|
||||
Flexblock ReadFileToBits(const std::string& filepath);
|
||||
|
||||
//! Will save bits to a binary file
|
||||
void WriteBitsToFile(const std::string& filepath, const Flexblock& bits);
|
||||
|
||||
//! Will read a file directly to data blocks, and yield the amount of bytes read
|
||||
std::vector<Block> ReadFileToBlocks(const std::string& filepath, std::size_t& bytes_read);
|
||||
|
||||
|
@ -6,20 +6,20 @@
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
Feistel::Feistel() {
|
||||
}
|
||||
|
||||
Feistel::Feistel(const Key& key) {
|
||||
SetKey(key);
|
||||
return;
|
||||
}
|
||||
|
||||
Feistel::~Feistel() {
|
||||
ZeroKeyMemory();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Feistel::SetKey(const Key& key) {
|
||||
GenerateRoundKeys(key);
|
||||
return;
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
Block Feistel::Encipher(const Block& data) {
|
||||
@ -31,6 +31,10 @@ namespace Leonetienne::GCrypt {
|
||||
}
|
||||
|
||||
Block Feistel::Run(const Block& data, bool modeEncrypt) {
|
||||
if (!isInitialized) {
|
||||
throw std::runtime_error("Attempted to digest data on uninitialized GCipher!");
|
||||
}
|
||||
|
||||
const auto splitData = FeistelSplit(data);
|
||||
Halfblock l = splitData.first;
|
||||
Halfblock r = splitData.second;
|
||||
@ -245,6 +249,7 @@ namespace Leonetienne::GCrypt {
|
||||
|
||||
void Feistel::operator=(const Feistel& other) {
|
||||
roundKeys = other.roundKeys;
|
||||
isInitialized = other.isInitialized;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -7,17 +7,33 @@
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
GCipher::GCipher() {
|
||||
}
|
||||
|
||||
GCipher::GCipher(const Key& key, const DIRECTION direction) :
|
||||
direction { direction },
|
||||
lastBlock(InitializationVector(key)), // Initialize our lastBlock with some deterministic initial value, based on the key
|
||||
feistel(key)
|
||||
{
|
||||
isInitialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
void GCipher::Initialize(const Key& key, const DIRECTION direction) {
|
||||
feistel = Feistel(key);
|
||||
lastBlock = InitializationVector(key);
|
||||
this->direction = direction;
|
||||
isInitialized = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Block GCipher::Digest(const Block& input) {
|
||||
|
||||
if (!isInitialized) {
|
||||
throw std::runtime_error("Attempted to digest data on uninitialized GCipher!");
|
||||
}
|
||||
|
||||
switch (direction) {
|
||||
case DIRECTION::ENCIPHER: {
|
||||
// Rename our input to cleartext
|
||||
@ -52,6 +68,11 @@ namespace Leonetienne::GCrypt {
|
||||
}
|
||||
|
||||
void GCipher::SetKey(const Key& key) {
|
||||
|
||||
if (!isInitialized) {
|
||||
throw std::runtime_error("Attempted to set key on uninitialized GCipher!");
|
||||
}
|
||||
|
||||
feistel.SetKey(key);
|
||||
|
||||
return;
|
||||
@ -61,6 +82,7 @@ namespace Leonetienne::GCrypt {
|
||||
direction = other.direction;
|
||||
feistel = other.feistel;
|
||||
lastBlock = other.lastBlock;
|
||||
isInitialized = other.isInitialized;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -5,17 +5,23 @@
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
GHash::GHash() :
|
||||
GHash::GHash() {
|
||||
// Initialize our cipher with a static, but randomly distributed key.
|
||||
cipher(
|
||||
Block ivSeed;
|
||||
ivSeed.FromByteString("3J7IipfQTDJbO8jtasz9PgWui6faPaEMOuVuAqyhB1S2CRcLw5caawewgDUEG1WN");
|
||||
block = InitializationVector(ivSeed);
|
||||
|
||||
Key key;
|
||||
key.FromByteString("nsoCZfvdqpRkeVTt9wzvPR3TT26peOW9E2kTHh3pdPCq2M7BpskvUljJHSrobUTI");
|
||||
|
||||
cipher = GCipher(
|
||||
// The key really does not matter, as it gets changed
|
||||
// each time before digesting anything.
|
||||
Key(StringToBitblock("nsoCZfvdqpRkeVTt9wzvPR3TT26peOW9E2kTHh3pdPCq2M7BpskvUljJHSrobUTI")),
|
||||
key,
|
||||
GCipher::DIRECTION::ENCIPHER
|
||||
) {
|
||||
block = InitializationVector(StringToBitblock("3J7IipfQTDJbO8jtasz9PgWui6faPaEMOuVuAqyhB1S2CRcLw5caawewgDUEG1WN"));
|
||||
);
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
void GHash::DigestBlock(const Block& data) {
|
||||
@ -64,7 +70,8 @@ namespace Leonetienne::GCrypt {
|
||||
|
||||
std::stringstream ss;
|
||||
ss << n_bytes;
|
||||
const Block lengthBlock = StringToBitblock(ss.str());
|
||||
Block lengthBlock;
|
||||
lengthBlock.FromTextString(ss.str());
|
||||
|
||||
// Digest the length block
|
||||
hasher.DigestBlock(lengthBlock);
|
||||
|
@ -134,35 +134,25 @@ namespace Leonetienne::GCrypt {
|
||||
}
|
||||
}
|
||||
|
||||
Flexblock GWrapper::CipherFlexblock(
|
||||
const Flexblock& data,
|
||||
std::vector<Block> GWrapper::CipherBlocks(
|
||||
const std::vector<Block>& data,
|
||||
const Key& key,
|
||||
const GCipher::DIRECTION direction)
|
||||
{
|
||||
// Split input into blocks
|
||||
std::vector<Block> blocks;
|
||||
|
||||
for (std::size_t i = 0; i < data.size(); i += Block::BLOCK_SIZE_BITS) {
|
||||
blocks.push_back(Block(
|
||||
PadStringToLength(data.substr(i, Block::BLOCK_SIZE_BITS), Block::BLOCK_SIZE_BITS, '0', false))
|
||||
);
|
||||
}
|
||||
|
||||
// Create cipher instance
|
||||
GCipher cipher(key, direction);
|
||||
|
||||
for (Block& block : blocks) {
|
||||
block = cipher.Digest(block);
|
||||
}
|
||||
std::vector<Block> digested;
|
||||
digested.reserve(data.size());
|
||||
|
||||
// Concatenate ciphertext blocks back into a flexblock
|
||||
std::stringstream ss;
|
||||
for (Block& b : blocks) {
|
||||
ss << b;
|
||||
// Digest all our blocks
|
||||
for (const Block& block : data) {
|
||||
Block digestedBlock = cipher.Digest(block);
|
||||
digested.emplace_back(digestedBlock);
|
||||
}
|
||||
|
||||
// Return it
|
||||
return ss.str();
|
||||
return digested;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,58 +30,16 @@ namespace Leonetienne::GCrypt {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
Block StringToBitblock(const std::string& s, bool padLeft) {
|
||||
std::stringstream ss;
|
||||
|
||||
for (std::size_t i = 0; i < s.size(); i++) {
|
||||
ss << std::bitset<8>(s[i]);
|
||||
}
|
||||
|
||||
// Pad rest with zeores
|
||||
return Block(PadStringToLength(ss.str(), Block::BLOCK_SIZE_BITS, '0', padLeft));
|
||||
}
|
||||
|
||||
Flexblock StringToBits(const std::string& s) {
|
||||
std::stringstream ss;
|
||||
|
||||
for (std::size_t i = 0; i < s.size(); i++) {
|
||||
ss << std::bitset<8>(s[i]);
|
||||
}
|
||||
|
||||
return Flexblock(ss.str());
|
||||
}
|
||||
|
||||
std::string BitblockToBytes(const Block& block) {
|
||||
std::stringstream ss;
|
||||
|
||||
std::uint8_t* curByte = (std::uint8_t*)(void*)block.Data();
|
||||
for (std::size_t j = 0; j < Block::BLOCK_SIZE; j++) {
|
||||
ss << *curByte++;
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string BitblocksToBytes(const std::vector<Block>& blocks) {
|
||||
std::stringstream ss;
|
||||
|
||||
for (const Block& block : blocks) {
|
||||
ss << BitblockToBytes(block);
|
||||
ss << block.ToByteString();
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string BitblockToString(const Block& bits) {
|
||||
// Decode to bytes
|
||||
std::string text = BitblockToBytes(bits);
|
||||
|
||||
// Dümp excess nullbytes
|
||||
text.resize(strlen(text.data()));
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
std::string BitblocksToString(const std::vector<Block>& blocks) {
|
||||
// Decode to bytes
|
||||
std::string text = BitblocksToBytes(blocks);
|
||||
@ -92,146 +50,6 @@ namespace Leonetienne::GCrypt {
|
||||
return text;
|
||||
}
|
||||
|
||||
std::string BitsToBytes(const Flexblock& bits) {
|
||||
std::stringstream ss;
|
||||
|
||||
const std::string bitstring = bits;
|
||||
|
||||
for (std::size_t i = 0; i < bits.size(); i += 8) {
|
||||
ss << (char)std::bitset<8>(bitstring.substr(i, 8)).to_ulong();
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string BitsToString(const Flexblock& bits) {
|
||||
// Decode to bytes
|
||||
std::string text = BitsToBytes(bits);
|
||||
|
||||
// Dümp excess nullbytes
|
||||
text.resize(strlen(text.data()));
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
std::string BitblockToHexstring(const Block& b) {
|
||||
std::stringstream ss;
|
||||
const std::string charset = "0123456789abcdef";
|
||||
const std::string bstr = b.ToBinaryString();
|
||||
|
||||
for (std::size_t i = 0; i < bstr.size(); i += 4) {
|
||||
ss << charset[std::bitset<4>(bstr.substr(i, 4)).to_ulong()];
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string BitsToHexstring(const Flexblock& b) {
|
||||
std::stringstream ss;
|
||||
const std::string charset = "0123456789abcdef";
|
||||
const std::string bstr = b;
|
||||
|
||||
for (std::size_t i = 0; i < bstr.size(); i += 4) {
|
||||
ss << charset[std::bitset<4>(bstr.substr(i, 4)).to_ulong()];
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
Block HexstringToBitblock(const std::string& hexstring) {
|
||||
std::stringstream ss;
|
||||
|
||||
for (std::size_t i = 0; i < hexstring.size(); i++) {
|
||||
const char c = hexstring[i];
|
||||
|
||||
// Get value
|
||||
std::size_t value;
|
||||
if ((c >= '0') && (c <= '9')) {
|
||||
// Is it a number?
|
||||
value = ((std::size_t)c - '0') + 0;
|
||||
}
|
||||
else if ((c >= 'a') && (c <= 'f')) {
|
||||
// Else, it is a lowercase letter
|
||||
value = ((std::size_t)c - 'a') + 10;
|
||||
}
|
||||
else {
|
||||
throw std::logic_error("non-hex string detected in HexstringToBits()");
|
||||
}
|
||||
|
||||
// Append to our bits
|
||||
ss << std::bitset<4>(value).to_string();
|
||||
}
|
||||
|
||||
return Block(ss.str());
|
||||
}
|
||||
|
||||
Flexblock HexstringToBits(const std::string& hexstring) {
|
||||
std::stringstream ss;
|
||||
|
||||
for (std::size_t i = 0; i < hexstring.size(); i++) {
|
||||
const char c = hexstring[i];
|
||||
|
||||
// Get value
|
||||
std::size_t value;
|
||||
if ((c >= '0') && (c <= '9')) {
|
||||
// Is it a number?
|
||||
value = ((std::size_t)c - '0') + 0;
|
||||
}
|
||||
else if ((c >= 'a') && (c <= 'f')) {
|
||||
// Else, it is a lowercase letter
|
||||
value = ((std::size_t)c - 'a') + 10;
|
||||
}
|
||||
else {
|
||||
throw std::logic_error("non-hex string detected in HexstringToBits()");
|
||||
}
|
||||
|
||||
// Append to our bits
|
||||
ss << std::bitset<4>(value).to_string();
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
Flexblock ReadFileToBits(const std::string& filepath) {
|
||||
// Read file
|
||||
std::ifstream ifs(filepath, std::ios::binary);
|
||||
|
||||
if (!ifs.good()) {
|
||||
throw std::runtime_error("Unable to open ifilestream!");
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
std::copy(
|
||||
std::istreambuf_iterator<char>(ifs),
|
||||
std::istreambuf_iterator<char>(),
|
||||
std::ostreambuf_iterator<char>(ss)
|
||||
);
|
||||
|
||||
ifs.close();
|
||||
|
||||
const std::string bytes = ss.str();
|
||||
|
||||
// Convert bytes to bits
|
||||
return StringToBits(bytes);
|
||||
}
|
||||
|
||||
void WriteBitsToFile(const std::string& filepath, const Flexblock& bits) {
|
||||
// Convert bits to bytes
|
||||
const std::string bytes = BitsToBytes(bits);
|
||||
|
||||
// Write bits to file
|
||||
std::ofstream ofs(filepath, std::ios::binary);
|
||||
|
||||
if (!ofs.good()) {
|
||||
throw std::runtime_error("Unable to open ofilestream!");
|
||||
}
|
||||
|
||||
ofs.write(bytes.data(), bytes.length());
|
||||
ofs.close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<Block> ReadFileToBlocks(const std::string& filepath, std::size_t& bytes_read) {
|
||||
// Read file
|
||||
bytes_read = 0;
|
||||
|
@ -7,13 +7,13 @@ using namespace Leonetienne::GCrypt;
|
||||
// THESE TESTS ASSUME BLOCK_SIZE == 512
|
||||
|
||||
// Tests that encrypting a message of exactly BLOCK_SIZE yields the exact message back
|
||||
TEST_CASE(__FILE__"/SingleBlock_NoPadding", "[Encryption/Decryption consistency]") {
|
||||
TEST_CASE(__FILE__"/SingleBlock", "[Encryption/Decryption consistency]") {
|
||||
|
||||
// Instanciate our cipher and supply a key
|
||||
const Key key = Key::FromPassword("1234");
|
||||
|
||||
// Recode the ascii-string to bits
|
||||
const Flexblock cleartext_bits =
|
||||
const std::string cleartext_bits =
|
||||
"1011110011010110000010110001111000111010111101001010100100011101"
|
||||
"0101110101010010100000110100001000011000111010001001110101111111"
|
||||
"1110110101100101110001010101011110001010000010111110011011010111"
|
||||
@ -23,196 +23,65 @@ TEST_CASE(__FILE__"/SingleBlock_NoPadding", "[Encryption/Decryption consistency]
|
||||
"1101100100000100010000001011100010010001101111100100101100010001"
|
||||
"0000011110010110111010110110111110011110011010001100100111110101";
|
||||
|
||||
std::vector<Block> cleartext_blocks({Block(cleartext_bits)});
|
||||
|
||||
// Encrypt our cleartext bits
|
||||
const Flexblock ciphertext_bits = GWrapper::CipherFlexblock(cleartext_bits, key, GCipher::DIRECTION::ENCIPHER);
|
||||
const std::vector<Block> ciphertext_blocks = GWrapper::CipherBlocks(cleartext_blocks, key, GCipher::DIRECTION::ENCIPHER);
|
||||
|
||||
// Decipher it again
|
||||
const Flexblock decryptedBits = GWrapper::CipherFlexblock(ciphertext_bits, key, GCipher::DIRECTION::DECIPHER);
|
||||
const std::vector<Block> decrypted_blocks = GWrapper::CipherBlocks(ciphertext_blocks, key, GCipher::DIRECTION::DECIPHER);
|
||||
|
||||
// Assert that the decrypted text equals the plaintext
|
||||
REQUIRE(
|
||||
cleartext_bits ==
|
||||
decryptedBits
|
||||
);
|
||||
cleartext_blocks ==
|
||||
decrypted_blocks
|
||||
);
|
||||
}
|
||||
|
||||
// Tests that encrypting a message of less than BLOCK_SIZE yields the exact message plus zero-padding back
|
||||
TEST_CASE(__FILE__"/SingleBlock_Padding", "[Encryption/Decryption consistency]") {
|
||||
|
||||
// Instanciate our cipher and supply a key
|
||||
const Key key = Key::FromPassword("1234");
|
||||
|
||||
// Recode the ascii-string to bits
|
||||
const Flexblock cleartext_bits =
|
||||
"1011110011010110000010110001111000111010111101001010100100011101"
|
||||
"0101110101010010100000110100001000011000111010001001110101111111"
|
||||
"1110110101100101110001010101011110001010000010111110011011010111"
|
||||
"1100110100111000000011100101010100110010001110010011000010111001"
|
||||
"0000010000010000011001111010011110111001000000000110101000110001"
|
||||
"0110111110110110100000010100000011010001000011100100111001001011"
|
||||
"1101100100000100";
|
||||
|
||||
const Flexblock cleartext_bits_EXPECTED_RESULT =
|
||||
"1011110011010110000010110001111000111010111101001010100100011101"
|
||||
"0101110101010010100000110100001000011000111010001001110101111111"
|
||||
"1110110101100101110001010101011110001010000010111110011011010111"
|
||||
"1100110100111000000011100101010100110010001110010011000010111001"
|
||||
"0000010000010000011001111010011110111001000000000110101000110001"
|
||||
"0110111110110110100000010100000011010001000011100100111001001011"
|
||||
"1101100100000100000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000";
|
||||
|
||||
// Encrypt our cleartext bits
|
||||
const Flexblock ciphertext_bits = GWrapper::CipherFlexblock(cleartext_bits, key, GCipher::DIRECTION::ENCIPHER);
|
||||
|
||||
// Decipher it again
|
||||
const Flexblock decryptedBits = GWrapper::CipherFlexblock(ciphertext_bits, key, GCipher::DIRECTION::DECIPHER);
|
||||
|
||||
// Assert that the decrypted text equals the plaintext
|
||||
REQUIRE(
|
||||
cleartext_bits_EXPECTED_RESULT ==
|
||||
decryptedBits
|
||||
);
|
||||
}
|
||||
|
||||
// Tests that a decrypted ciphertext equals its plaintrext version, using a cleartext that requires A LOT of blocks
|
||||
// Tests that a decrypted ciphertext equals its plaintext version, using a cleartext that requires A LOT of blocks
|
||||
TEST_CASE(__FILE__"MultiBlock_NoPadding/", "[Encryption/Decryption consistency]") {
|
||||
|
||||
// Instanciate our cipher and supply a key
|
||||
const Key key = Key::FromPassword("1234");
|
||||
|
||||
// Recode the ascii-string to bits
|
||||
const Flexblock cleartext_bits =
|
||||
"1011110011010110000010110001111000111010111101001010100100011101"
|
||||
"0101110101010010100000110100001000011000111010001001110101111111"
|
||||
"1110110101100101110001010101011110001010000010111110011011010111"
|
||||
"1100110100111000000011100101010100110010001110010011000010111001"
|
||||
"0000010000010000011001111010011110111001000000000110101000110001"
|
||||
"0110111110110110100000010100000011010001000011100100111001001011"
|
||||
"1101100100000100010000001011100010010001101111100100101100010001"
|
||||
"0000011110010110111010110110111110011110011010001100100111110101"
|
||||
"1000010010000000000100101011110001000101101101100000010011111011"
|
||||
"1011111010110100100111100111110011100001111101111110000110001100"
|
||||
"0001000111000111101110000111011011101010100010100101100111010100"
|
||||
"0101111110110010110000111111011001101110101101100100100011000100"
|
||||
"1000110010101001000100001001101000011111101011111100100000100101"
|
||||
"1100001100111001011111001101000111011101011101000110010110110110"
|
||||
"0111001010011010010000010110000110010101101100101110111100100011"
|
||||
"0010111110011100010100000101100101110101101011110100100000110110"
|
||||
"1001101110101001001111111000010100011100100000101000111101101111"
|
||||
"0101111011110001101010111010001000111010101111001101100100100100"
|
||||
"1110110111001100011010110000101000011001011100101100111101110000"
|
||||
"1010101111011110000111011011011110000111010110110111111010101010"
|
||||
"0111100101111001010111101000001010100000111010111100111011111001"
|
||||
"0110111000000110100011011100101101010101101000010010011111100100"
|
||||
"0010111000001011101110000110010011101001111010100111110111110101"
|
||||
"1110111000000000101011000100101010000110110111101010011001111010"
|
||||
"1101011110001110000011010111001100001100101000000101000101000010"
|
||||
"0101000011011111010010110010000010101100001110011000110111110111"
|
||||
"1110010101011110111001100010110101101011100111100011101010001011"
|
||||
"0101110010100110101100111100010000111101111100000111000110110110"
|
||||
"1001100111000000011010100000011101011000010010011010001011110000"
|
||||
"1100100111111001001000011100110000011110001100000000010000001001"
|
||||
"1110000000110010000010011010100011011011000000000111110000110111"
|
||||
"0101110011001101010110010100011001110110000110010001100110011111";
|
||||
std::stringstream ss;
|
||||
const std::string charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
// Read 10 blocks worth of characters
|
||||
srand(time(0));
|
||||
for (std::size_t i = 0; i < 512*10; i++) {
|
||||
ss << charset[rand() % charset.length()];
|
||||
}
|
||||
const std::string cleartext_str = ss.str();
|
||||
|
||||
std::vector<Block> cleartext_blocks = StringToBitblocks(cleartext_str);
|
||||
|
||||
// Encrypt our cleartext bits
|
||||
const Flexblock ciphertext_bits = GWrapper::CipherFlexblock(cleartext_bits, key, GCipher::DIRECTION::ENCIPHER);
|
||||
std::vector<Block> ciphertext_blocks;
|
||||
ciphertext_blocks.reserve(cleartext_blocks.size());
|
||||
{
|
||||
GCipher cipher(key, GCipher::DIRECTION::ENCIPHER);
|
||||
|
||||
for (const Block& clearBlock : cleartext_blocks) {
|
||||
ciphertext_blocks.emplace_back(cipher.Digest(clearBlock));
|
||||
}
|
||||
}
|
||||
|
||||
// Decipher it again
|
||||
const Flexblock decryptedBits = GWrapper::CipherFlexblock(ciphertext_bits, key, GCipher::DIRECTION::DECIPHER);
|
||||
std::vector<Block> deciphered_blocks;
|
||||
deciphered_blocks.reserve(ciphertext_blocks.size());
|
||||
{
|
||||
GCipher cipher(key, GCipher::DIRECTION::DECIPHER);
|
||||
|
||||
for (const Block& ciphBlock : ciphertext_blocks) {
|
||||
deciphered_blocks.emplace_back(cipher.Digest(ciphBlock));
|
||||
}
|
||||
}
|
||||
|
||||
// Assert that the decrypted text equals the plaintext
|
||||
REQUIRE(
|
||||
cleartext_bits ==
|
||||
decryptedBits
|
||||
);
|
||||
}
|
||||
|
||||
// Tests that a decrypted ciphertext equals its plaintrext version, using a cleartext that requires A LOT of blocks
|
||||
TEST_CASE(__FILE__"MultiBlock_Padding/", "[Encryption/Decryption consistency]") {
|
||||
|
||||
// Instanciate our cipher and supply a key
|
||||
const Key key = Key::FromPassword("1234");
|
||||
|
||||
// Recode the ascii-string to bits
|
||||
const Flexblock cleartext_bits =
|
||||
"1011110011010110000010110001111000111010111101001010100100011101"
|
||||
"0101110101010010100000110100001000011000111010001001110101111111"
|
||||
"1110110101100101110001010101011110001010000010111110011011010111"
|
||||
"1100110100111000000011100101010100110010001110010011000010111001"
|
||||
"0000010000010000011001111010011110111001000000000110101000110001"
|
||||
"0110111110110110100000010100000011010001000011100100111001001011"
|
||||
"1101100100000100010000001011100010010001101111100100101100010001"
|
||||
"0000011110010110111010110110111110011110011010001100100111110101"
|
||||
"1000010010000000000100101011110001000101101101100000010011111011"
|
||||
"1011111010110100100111100111110011100001111101111110000110001100"
|
||||
"0001000111000111101110000111011011101010100010100101100111010100"
|
||||
"0101111110110010110000111111011001101110101101100100100011000100"
|
||||
"1000110010101001000100001001101000011111101011111100100000100101"
|
||||
"1100001100111001011111001101000111011101011101000110010110110110"
|
||||
"0111001010011010010000010110000110010101101100101110111100100011"
|
||||
"0010111110011100010100000101100101110101101011110100100000110110"
|
||||
"1001101110101001001111111000010100011100100000101000111101101111"
|
||||
"0101111011110001101010111010001000111010101111001101100100100100"
|
||||
"1110110111001100011010110000101000011001011100101100111101110000"
|
||||
"1010101111011110000111011011011110000111010110110111111010101010"
|
||||
"0111100101111001010111101000001010100000111010111100111011111001"
|
||||
"0110111000000110100011011100101101010101101000010010011111100100"
|
||||
"0010111000001011101110000110010011101001111010100111110111110101"
|
||||
"1110111000000000101011000100101010000110110111101010011001111010"
|
||||
"1101011110001110000011010111001100001100101000000101000101000010"
|
||||
"0101000011011111010010110010000010101100001110011000110111110111"
|
||||
"1110010101011110111001100010110101101011100111100011101010001011"
|
||||
"0101110010100110101100111100010000111101111100000111000110110110"
|
||||
"1001100111000000011010100000011101011000010010011010001011110000"
|
||||
"1100100111111001001000011100110000011110001100000000010000001001"
|
||||
"11100000001100100000100110101000110110110000000001111100001";
|
||||
|
||||
const Flexblock cleartext_bits_EXPECTED_RESULT =
|
||||
"1011110011010110000010110001111000111010111101001010100100011101"
|
||||
"0101110101010010100000110100001000011000111010001001110101111111"
|
||||
"1110110101100101110001010101011110001010000010111110011011010111"
|
||||
"1100110100111000000011100101010100110010001110010011000010111001"
|
||||
"0000010000010000011001111010011110111001000000000110101000110001"
|
||||
"0110111110110110100000010100000011010001000011100100111001001011"
|
||||
"1101100100000100010000001011100010010001101111100100101100010001"
|
||||
"0000011110010110111010110110111110011110011010001100100111110101"
|
||||
"1000010010000000000100101011110001000101101101100000010011111011"
|
||||
"1011111010110100100111100111110011100001111101111110000110001100"
|
||||
"0001000111000111101110000111011011101010100010100101100111010100"
|
||||
"0101111110110010110000111111011001101110101101100100100011000100"
|
||||
"1000110010101001000100001001101000011111101011111100100000100101"
|
||||
"1100001100111001011111001101000111011101011101000110010110110110"
|
||||
"0111001010011010010000010110000110010101101100101110111100100011"
|
||||
"0010111110011100010100000101100101110101101011110100100000110110"
|
||||
"1001101110101001001111111000010100011100100000101000111101101111"
|
||||
"0101111011110001101010111010001000111010101111001101100100100100"
|
||||
"1110110111001100011010110000101000011001011100101100111101110000"
|
||||
"1010101111011110000111011011011110000111010110110111111010101010"
|
||||
"0111100101111001010111101000001010100000111010111100111011111001"
|
||||
"0110111000000110100011011100101101010101101000010010011111100100"
|
||||
"0010111000001011101110000110010011101001111010100111110111110101"
|
||||
"1110111000000000101011000100101010000110110111101010011001111010"
|
||||
"1101011110001110000011010111001100001100101000000101000101000010"
|
||||
"0101000011011111010010110010000010101100001110011000110111110111"
|
||||
"1110010101011110111001100010110101101011100111100011101010001011"
|
||||
"0101110010100110101100111100010000111101111100000111000110110110"
|
||||
"1001100111000000011010100000011101011000010010011010001011110000"
|
||||
"1100100111111001001000011100110000011110001100000000010000001001"
|
||||
"1110000000110010000010011010100011011011000000000111110000100000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000";
|
||||
|
||||
// Encrypt our cleartext bits
|
||||
const Flexblock ciphertext_bits = GWrapper::CipherFlexblock(cleartext_bits, key, GCipher::DIRECTION::ENCIPHER);
|
||||
|
||||
// Decipher it again
|
||||
const Flexblock decryptedBits = GWrapper::CipherFlexblock(ciphertext_bits, key, GCipher::DIRECTION::DECIPHER);
|
||||
|
||||
// Assert that the decrypted text equals the plaintext
|
||||
REQUIRE(
|
||||
cleartext_bits_EXPECTED_RESULT ==
|
||||
decryptedBits
|
||||
);
|
||||
cleartext_blocks ==
|
||||
deciphered_blocks
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,12 @@
|
||||
#include <GCrypt/GWrapper.h>
|
||||
#include <GCrypt/Flexblock.h>
|
||||
#include <GCrypt/Util.h>
|
||||
#include "Catch2.h"
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
// Tests that encrypting and decrypting strings using the wrapper works.
|
||||
// Tests that encrypting and decrypting short strings using the wrapper works.
|
||||
// This test will start from scratch after encryption, to ensure EVERYTHING has to be re-calculated.
|
||||
TEST_CASE(__FILE__"/Encrypting and decrypting strings works", "[Wrapper]") {
|
||||
TEST_CASE(__FILE__"/Encrypting and decrypting strings works, Single block", "[Wrapper]") {
|
||||
|
||||
// Setup
|
||||
const std::string plaintext = "Hello, World!";
|
||||
@ -26,6 +25,37 @@ TEST_CASE(__FILE__"/Encrypting and decrypting strings works", "[Wrapper]") {
|
||||
REQUIRE(plaintext == decrypted);
|
||||
}
|
||||
|
||||
// Tests that encrypting and decrypting very long strings using the wrapper works.
|
||||
// This test will start from scratch after encryption, to ensure EVERYTHING has to be re-calculated.
|
||||
TEST_CASE(__FILE__"/Encrypting and decrypting strings works, Many blocks block", "[Wrapper]") {
|
||||
|
||||
// Setup
|
||||
|
||||
// Read an not-multiple-of-blocksize amount of random chars, that's very large (about 200kb long string)
|
||||
srand(time(0));
|
||||
|
||||
std::stringstream ss;
|
||||
const std::string charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
for (std::size_t i = 0; i < 198273; i++) {
|
||||
ss << charset[rand() % charset.length()];
|
||||
}
|
||||
|
||||
const std::string plaintext = ss.str();
|
||||
const Key key = Key::FromPassword("Der Affe will Zucker");
|
||||
|
||||
std::string ciphertext;
|
||||
std::string decrypted;
|
||||
|
||||
// Encryption
|
||||
ciphertext = GWrapper::EncryptString(plaintext, key);
|
||||
|
||||
// Decryption
|
||||
decrypted = GWrapper::DecryptString(ciphertext, key);
|
||||
|
||||
// Assertion
|
||||
REQUIRE(plaintext == decrypted);
|
||||
}
|
||||
|
||||
// Tests that encrypting and decrypting files using the wrapper works.
|
||||
// This test will start from scratch after encryption, to ensure EVERYTHING has to be re-calculated.
|
||||
TEST_CASE(__FILE__"/Encrypting and decrypting files works", "[Wrapper]") {
|
||||
|
Loading…
x
Reference in New Issue
Block a user