[Progress:] Completely re-done Block class to not use bitsets, and provide custom operators.
This commit is contained in:
parent
ed45b69342
commit
939df4731b
@ -1,12 +1,126 @@
|
|||||||
#ifndef GCRYPT_BLOCK_H
|
#ifndef GCRYPT_BLOCK_H
|
||||||
#define GCRYPT_BLOCK_H
|
#define GCRYPT_BLOCK_H
|
||||||
|
|
||||||
#include "GCrypt/SecureBitset.h"
|
#include <cstdint>
|
||||||
#include "GCrypt/Config.h"
|
#include <array>
|
||||||
|
#include <string>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
namespace Leonetienne::GCrypt {
|
namespace Leonetienne::GCrypt {
|
||||||
typedef SecureBitset<BLOCK_SIZE> Block;
|
|
||||||
|
/* This class represents a block of data,
|
||||||
|
* and provides functions to manipulate it
|
||||||
|
*/
|
||||||
|
class Block {
|
||||||
|
public:
|
||||||
|
//! Will constuct an uninitialized data block
|
||||||
|
Block();
|
||||||
|
|
||||||
|
//! Will construct this block from a string like "101010".. Length MUST be 512.
|
||||||
|
Block(const std::string& other);
|
||||||
|
|
||||||
|
//! Copy-ctor
|
||||||
|
Block(const Block& other);
|
||||||
|
|
||||||
|
~Block();
|
||||||
|
|
||||||
|
//! Will construct this block from a string like "011101..". Length MUST be 512.
|
||||||
|
void FromString(const std::string& str);
|
||||||
|
|
||||||
|
//! Will create a bitset-compatible string ("0101110..") representation
|
||||||
|
//! of this block. Length will always be 512.
|
||||||
|
std::string ToString() const;
|
||||||
|
|
||||||
|
//! Will matrix-multiply two blocks together.
|
||||||
|
//! Since the matrices values are pretty much sudo-random,
|
||||||
|
//! they will most likely integer-overflow.
|
||||||
|
//! So see this as a one-way function.
|
||||||
|
Block MMul(const Block& other) const;
|
||||||
|
Block operator*(const Block& other) const;
|
||||||
|
|
||||||
|
//! Will matrix-multiply two blocks together,
|
||||||
|
//! and directly write into this same block.
|
||||||
|
//! Since the matrices values are pretty much sudo-random,
|
||||||
|
//! they will most likely integer-overflow.
|
||||||
|
//! So see this as a one-way function.
|
||||||
|
void MMulInplace(const Block& other);
|
||||||
|
Block& operator*=(const Block& other);
|
||||||
|
|
||||||
|
//! Will xor two blocks together
|
||||||
|
Block Xor(const Block& other) const;
|
||||||
|
//! Will xor two blocks together
|
||||||
|
Block operator^(const Block& other) const;
|
||||||
|
|
||||||
|
//! Will xor two blocks together, inplace
|
||||||
|
void XorInplace(const Block& other);
|
||||||
|
//! Will xor two blocks together, inplace
|
||||||
|
Block& operator^=(const Block& other);
|
||||||
|
|
||||||
|
// # TO BE IMPLEMENTED
|
||||||
|
//! Will shift rows upwards by n
|
||||||
|
void ShiftRowsUp(const std::size_t n);
|
||||||
|
|
||||||
|
// # TO BE IMPLEMENTED
|
||||||
|
//! Will shift matrix rows downwards by n
|
||||||
|
void ShiftRowsDown(const std::size_t n);
|
||||||
|
|
||||||
|
// # TO BE IMPLEMENTED
|
||||||
|
//! Will shift matrix columns to the left by n
|
||||||
|
void ShiftColumnsLeft(const std::size_t n);
|
||||||
|
|
||||||
|
// # TO BE IMPLEMENTED
|
||||||
|
//! Will shift matrix columns to the right by n
|
||||||
|
void ShiftColumnsRight(const std::size_t n);
|
||||||
|
|
||||||
|
// # TO BE IMPLEMENTED
|
||||||
|
//! Will shift array cells to the left by n
|
||||||
|
void ShiftCellsLeft(const std::size_t n);
|
||||||
|
|
||||||
|
// # TO BE IMPLEMENTED
|
||||||
|
//! Will shift array cells to the right by n
|
||||||
|
void ShiftCellsRight(const std::size_t n);
|
||||||
|
|
||||||
|
//! Will copy a block
|
||||||
|
Block& operator=(const Block& other);
|
||||||
|
|
||||||
|
//! Will compare whether or not two blocks are equal
|
||||||
|
bool operator==(const Block& other) const;
|
||||||
|
//! Will compare whether or not two blocks are unequal
|
||||||
|
bool operator!=(const Block& other) const;
|
||||||
|
|
||||||
|
//! Will zero all data
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
|
||||||
|
//! Returns 32-bit chunks of data, indexed by matrix coordinates (0-3)
|
||||||
|
std::uint32_t& Get(const std::uint8_t row, const std::uint8_t column);
|
||||||
|
//! Returns 32-bit chunks of data, indexed by matrix coordinates (0-3)
|
||||||
|
const std::uint32_t& Get(const std::uint8_t row, const std::uint8_t column) const;
|
||||||
|
|
||||||
|
//! Returns 32-bit chunks of data, indexed by a 1d-index (0-16)
|
||||||
|
std::uint32_t& Get(const std::uint8_t index);
|
||||||
|
|
||||||
|
//! Returns 32-bit chunks of data, indexed by a 1d-index (0-16)
|
||||||
|
const std::uint32_t& Get(const std::uint8_t index) const;
|
||||||
|
|
||||||
|
//! Returns 32-bit chunks of data, indexed by a 1d-index (0-16)
|
||||||
|
std::uint32_t& operator[](const std::uint8_t index);
|
||||||
|
|
||||||
|
//! Returns 32-bit chunks of data, indexed by a 1d-index (0-16)
|
||||||
|
const std::uint32_t& operator[](const std::uint8_t index) const;
|
||||||
|
|
||||||
|
static constexpr std::size_t CHUNK_SIZE = sizeof(std::uint32_t);
|
||||||
|
static constexpr std::size_t CHUNK_SIZE_BITS = CHUNK_SIZE * 8;
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& os, const Block& b);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::array<std::uint32_t, 16> data;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
#ifndef GCRYPT_BLOCKMATRIX_H
|
|
||||||
#define GCRYPT_BLOCKMATRIX_H
|
|
||||||
|
|
||||||
#include "GCrypt/Block.h"
|
|
||||||
#include <cstdint>
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
namespace Leonetienne::GCrypt {
|
|
||||||
|
|
||||||
/* This class represents a block as a matrix,
|
|
||||||
* providing typical matrix operations
|
|
||||||
*/
|
|
||||||
class BlockMatrix {
|
|
||||||
public:
|
|
||||||
BlockMatrix();
|
|
||||||
BlockMatrix(const Block& block);
|
|
||||||
BlockMatrix(const BlockMatrix& other);
|
|
||||||
|
|
||||||
//! Will calculate the product of two matrices.
|
|
||||||
//! Since the matrices values are pretty much sudo-random,
|
|
||||||
//! they will most likely integer-overflow.
|
|
||||||
//! So see this as a one-way function.
|
|
||||||
BlockMatrix MMult(const BlockMatrix& other) const;
|
|
||||||
BlockMatrix operator*(const BlockMatrix& other) const;
|
|
||||||
|
|
||||||
//! Will do a regular matrix-mult, but instead of
|
|
||||||
//! adding, and multiplying, all ints get xored.
|
|
||||||
BlockMatrix MXor(const BlockMatrix& other) const;
|
|
||||||
|
|
||||||
bool operator==(const BlockMatrix& other) const;
|
|
||||||
bool operator!=(const BlockMatrix& other) const;
|
|
||||||
|
|
||||||
void FromBlock(const Block& block);
|
|
||||||
Block ToBlock() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
//! Returns items of data, indexed by 4x4 coordinates
|
|
||||||
std::uint32_t& Get(const std::uint8_t row, const std::uint8_t column);
|
|
||||||
//! Returns items of data, indexed by 4x4 coordinates
|
|
||||||
const std::uint32_t& Get(const std::uint8_t row, const std::uint8_t column) const;
|
|
||||||
|
|
||||||
std::array<std::uint32_t, 16> data;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef GCRYPT_VERSION_H
|
#ifndef GCRYPT_VERSION_H
|
||||||
#define GCRYPT_VERSION_H
|
#define GCRYPT_VERSION_H
|
||||||
|
|
||||||
#define GCRYPT_VERSION 0.231
|
#define GCRYPT_VERSION 0.232
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
220
GCryptLib/src/Block.cpp
Normal file
220
GCryptLib/src/Block.cpp
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
#include "GCrypt/Block.h"
|
||||||
|
#include "GCrypt/Config.h"
|
||||||
|
#include <sstream>
|
||||||
|
#include <bitset>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace Leonetienne::GCrypt {
|
||||||
|
|
||||||
|
Block::Block() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Block::Block(const std::string& str) {
|
||||||
|
FromString(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
Block::Block(const Block& other) {
|
||||||
|
data = other.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Block::FromString(const std::string& str) {
|
||||||
|
|
||||||
|
assert(str.length() == BLOCK_SIZE);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < data.size(); i++) {
|
||||||
|
data[i] = std::bitset<CHUNK_SIZE_BITS>(
|
||||||
|
str.substr(i*CHUNK_SIZE_BITS, CHUNK_SIZE_BITS)
|
||||||
|
).to_ulong();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Block::ToString() const {
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
for (std::size_t i = 0; i < data.size(); i++) {
|
||||||
|
ss << std::bitset<CHUNK_SIZE_BITS>(data[i]).to_string();
|
||||||
|
}
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
Block Block::MMul(const Block& o) const {
|
||||||
|
|
||||||
|
Block m;
|
||||||
|
|
||||||
|
m.Get(0, 0) = (this->Get(0, 0) * o.Get(0, 0)) + (this->Get(0, 1) * o.Get(1, 0)) + (this->Get(0, 2) * o.Get(2, 0)) + (this->Get(0, 3) * o.Get(3, 0));
|
||||||
|
m.Get(0, 1) = (this->Get(0, 0) * o.Get(0, 1)) + (this->Get(0, 1) * o.Get(1, 1)) + (this->Get(0, 2) * o.Get(2, 1)) + (this->Get(0, 3) * o.Get(3, 1));
|
||||||
|
m.Get(0, 2) = (this->Get(0, 0) * o.Get(0, 2)) + (this->Get(0, 1) * o.Get(1, 2)) + (this->Get(0, 2) * o.Get(2, 2)) + (this->Get(0, 3) * o.Get(3, 2));
|
||||||
|
m.Get(0, 3) = (this->Get(0, 0) * o.Get(0, 3)) + (this->Get(0, 1) * o.Get(1, 3)) + (this->Get(0, 2) * o.Get(2, 3)) + (this->Get(0, 3) * o.Get(3, 3));
|
||||||
|
|
||||||
|
m.Get(1, 0) = (this->Get(1, 0) * o.Get(0, 0)) + (this->Get(1, 1) * o.Get(1, 0)) + (this->Get(1, 2) * o.Get(2, 0)) + (this->Get(1, 3) * o.Get(3, 0));
|
||||||
|
m.Get(1, 1) = (this->Get(1, 0) * o.Get(0, 1)) + (this->Get(1, 1) * o.Get(1, 1)) + (this->Get(1, 2) * o.Get(2, 1)) + (this->Get(1, 3) * o.Get(3, 1));
|
||||||
|
m.Get(1, 2) = (this->Get(1, 0) * o.Get(0, 2)) + (this->Get(1, 1) * o.Get(1, 2)) + (this->Get(1, 2) * o.Get(2, 2)) + (this->Get(1, 3) * o.Get(3, 2));
|
||||||
|
m.Get(1, 3) = (this->Get(1, 0) * o.Get(0, 3)) + (this->Get(1, 1) * o.Get(1, 3)) + (this->Get(1, 2) * o.Get(2, 3)) + (this->Get(1, 3) * o.Get(3, 3));
|
||||||
|
|
||||||
|
m.Get(2, 0) = (this->Get(2, 0) * o.Get(0, 0)) + (this->Get(2, 1) * o.Get(1, 0)) + (this->Get(2, 2) * o.Get(2, 0)) + (this->Get(2, 3) * o.Get(3, 0));
|
||||||
|
m.Get(2, 1) = (this->Get(2, 0) * o.Get(0, 1)) + (this->Get(2, 1) * o.Get(1, 1)) + (this->Get(2, 2) * o.Get(2, 1)) + (this->Get(2, 3) * o.Get(3, 1));
|
||||||
|
m.Get(2, 2) = (this->Get(2, 0) * o.Get(0, 2)) + (this->Get(2, 1) * o.Get(1, 2)) + (this->Get(2, 2) * o.Get(2, 2)) + (this->Get(2, 3) * o.Get(3, 2));
|
||||||
|
m.Get(2, 3) = (this->Get(2, 0) * o.Get(0, 3)) + (this->Get(2, 1) * o.Get(1, 3)) + (this->Get(2, 2) * o.Get(2, 3)) + (this->Get(2, 3) * o.Get(3, 3));
|
||||||
|
|
||||||
|
m.Get(3, 0) = (this->Get(3, 0) * o.Get(0, 0)) + (this->Get(3, 1) * o.Get(1, 0)) + (this->Get(3, 2) * o.Get(2, 0)) + (this->Get(3, 3) * o.Get(3, 0));
|
||||||
|
m.Get(3, 1) = (this->Get(3, 0) * o.Get(0, 1)) + (this->Get(3, 1) * o.Get(1, 1)) + (this->Get(3, 2) * o.Get(2, 1)) + (this->Get(3, 3) * o.Get(3, 1));
|
||||||
|
m.Get(3, 2) = (this->Get(3, 0) * o.Get(0, 2)) + (this->Get(3, 1) * o.Get(1, 2)) + (this->Get(3, 2) * o.Get(2, 2)) + (this->Get(3, 3) * o.Get(3, 2));
|
||||||
|
m.Get(3, 3) = (this->Get(3, 0) * o.Get(0, 3)) + (this->Get(3, 1) * o.Get(1, 3)) + (this->Get(3, 2) * o.Get(2, 3)) + (this->Get(3, 3) * o.Get(3, 3));
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block Block::operator*(const Block& other) const {
|
||||||
|
return this->MMul(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Block::MMulInplace(const Block& o) {
|
||||||
|
|
||||||
|
Block m = *this;
|
||||||
|
|
||||||
|
this->Get(0, 0) = (m.Get(0, 0) * o.Get(0, 0)) + (m.Get(0, 1) * o.Get(1, 0)) + (m.Get(0, 2) * o.Get(2, 0)) + (m.Get(0, 3) * o.Get(3, 0));
|
||||||
|
this->Get(0, 1) = (m.Get(0, 0) * o.Get(0, 1)) + (m.Get(0, 1) * o.Get(1, 1)) + (m.Get(0, 2) * o.Get(2, 1)) + (m.Get(0, 3) * o.Get(3, 1));
|
||||||
|
this->Get(0, 2) = (m.Get(0, 0) * o.Get(0, 2)) + (m.Get(0, 1) * o.Get(1, 2)) + (m.Get(0, 2) * o.Get(2, 2)) + (m.Get(0, 3) * o.Get(3, 2));
|
||||||
|
this->Get(0, 3) = (m.Get(0, 0) * o.Get(0, 3)) + (m.Get(0, 1) * o.Get(1, 3)) + (m.Get(0, 2) * o.Get(2, 3)) + (m.Get(0, 3) * o.Get(3, 3));
|
||||||
|
|
||||||
|
this->Get(1, 0) = (m.Get(1, 0) * o.Get(0, 0)) + (m.Get(1, 1) * o.Get(1, 0)) + (m.Get(1, 2) * o.Get(2, 0)) + (m.Get(1, 3) * o.Get(3, 0));
|
||||||
|
this->Get(1, 1) = (m.Get(1, 0) * o.Get(0, 1)) + (m.Get(1, 1) * o.Get(1, 1)) + (m.Get(1, 2) * o.Get(2, 1)) + (m.Get(1, 3) * o.Get(3, 1));
|
||||||
|
this->Get(1, 2) = (m.Get(1, 0) * o.Get(0, 2)) + (m.Get(1, 1) * o.Get(1, 2)) + (m.Get(1, 2) * o.Get(2, 2)) + (m.Get(1, 3) * o.Get(3, 2));
|
||||||
|
this->Get(1, 3) = (m.Get(1, 0) * o.Get(0, 3)) + (m.Get(1, 1) * o.Get(1, 3)) + (m.Get(1, 2) * o.Get(2, 3)) + (m.Get(1, 3) * o.Get(3, 3));
|
||||||
|
|
||||||
|
this->Get(2, 0) = (m.Get(2, 0) * o.Get(0, 0)) + (m.Get(2, 1) * o.Get(1, 0)) + (m.Get(2, 2) * o.Get(2, 0)) + (m.Get(2, 3) * o.Get(3, 0));
|
||||||
|
this->Get(2, 1) = (m.Get(2, 0) * o.Get(0, 1)) + (m.Get(2, 1) * o.Get(1, 1)) + (m.Get(2, 2) * o.Get(2, 1)) + (m.Get(2, 3) * o.Get(3, 1));
|
||||||
|
this->Get(2, 2) = (m.Get(2, 0) * o.Get(0, 2)) + (m.Get(2, 1) * o.Get(1, 2)) + (m.Get(2, 2) * o.Get(2, 2)) + (m.Get(2, 3) * o.Get(3, 2));
|
||||||
|
this->Get(2, 3) = (m.Get(2, 0) * o.Get(0, 3)) + (m.Get(2, 1) * o.Get(1, 3)) + (m.Get(2, 2) * o.Get(2, 3)) + (m.Get(2, 3) * o.Get(3, 3));
|
||||||
|
|
||||||
|
this->Get(3, 0) = (m.Get(3, 0) * o.Get(0, 0)) + (m.Get(3, 1) * o.Get(1, 0)) + (m.Get(3, 2) * o.Get(2, 0)) + (m.Get(3, 3) * o.Get(3, 0));
|
||||||
|
this->Get(3, 1) = (m.Get(3, 0) * o.Get(0, 1)) + (m.Get(3, 1) * o.Get(1, 1)) + (m.Get(3, 2) * o.Get(2, 1)) + (m.Get(3, 3) * o.Get(3, 1));
|
||||||
|
this->Get(3, 2) = (m.Get(3, 0) * o.Get(0, 2)) + (m.Get(3, 1) * o.Get(1, 2)) + (m.Get(3, 2) * o.Get(2, 2)) + (m.Get(3, 3) * o.Get(3, 2));
|
||||||
|
this->Get(3, 3) = (m.Get(3, 0) * o.Get(0, 3)) + (m.Get(3, 1) * o.Get(1, 3)) + (m.Get(3, 2) * o.Get(2, 3)) + (m.Get(3, 3) * o.Get(3, 3));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block& Block::operator*=(const Block& other) {
|
||||||
|
MMulInplace(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block Block::Xor(const Block& other) const {
|
||||||
|
|
||||||
|
Block m;
|
||||||
|
for (std::size_t i = 0; i < data.size(); i++) {
|
||||||
|
m.Get(i) = this->Get(i) ^ other.Get(i);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block Block::operator^(const Block& other) const {
|
||||||
|
return Xor(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Block::XorInplace(const Block& other) {
|
||||||
|
for (std::size_t i = 0; i < data.size(); i++) {
|
||||||
|
this->Get(i) ^= other.Get(i);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block& Block::operator^=(const Block& other) {
|
||||||
|
XorInplace(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShiftRowsUp(const std::size_t n) {
|
||||||
|
// TO BE IMPLEMENTED
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShiftRowsDown(const std::size_t n) {
|
||||||
|
// TO BE IMPLEMENTED
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShiftColumnsLeft(const std::size_t n) {
|
||||||
|
// TO BE IMPLEMENTED
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShiftColumnsRight(const std::size_t n) {
|
||||||
|
// TO BE IMPLEMENTED
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShiftCellsLeft(const std::size_t n) {
|
||||||
|
// TO BE IMPLEMENTED
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShiftCellsRight(const std::size_t n) {
|
||||||
|
// TO BE IMPLEMENTED
|
||||||
|
}
|
||||||
|
|
||||||
|
Block& Block::operator=(const Block& other) {
|
||||||
|
data = other.data;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t& Block::Get(const std::uint8_t row, const std::uint8_t column){
|
||||||
|
return data[column*4 + row];
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::uint32_t& Block::Get(const std::uint8_t row, const std::uint8_t column) const {
|
||||||
|
return data[column*4 + row];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t& Block::Get(const std::uint8_t index) {
|
||||||
|
return data[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::uint32_t& Block::Get(const std::uint8_t index) const {
|
||||||
|
return data[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t& Block::operator[](const std::uint8_t index) {
|
||||||
|
return data[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::uint32_t& Block::operator[](const std::uint8_t index) const {
|
||||||
|
return data[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Block::operator==(const Block& other) const {
|
||||||
|
return data == other.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Block::operator!=(const Block& other) const {
|
||||||
|
return data != other.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, const Block& b) {
|
||||||
|
for (std::size_t i = 0; i < b.data.size(); i++) {
|
||||||
|
os << std::bitset<b.CHUNK_SIZE_BITS>(b.data[i]).to_string();
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined _WIN32 || defined _WIN64
|
||||||
|
#pragma optimize("", off )
|
||||||
|
#elif defined __GNUG__
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC optimize ("O0")
|
||||||
|
#endif
|
||||||
|
Block::~Block() {
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Block::Reset() {
|
||||||
|
memset(data.data(), 0, CHUNK_SIZE*data.size());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined _WIN32 || defined _WIN64
|
||||||
|
#pragma optimize("", on )
|
||||||
|
#elif defined __GNUG__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
@ -1,114 +0,0 @@
|
|||||||
#include "GCrypt/BlockMatrix.h"
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace Leonetienne::GCrypt {
|
|
||||||
|
|
||||||
BlockMatrix::BlockMatrix() {
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockMatrix::BlockMatrix(const Block& block) {
|
|
||||||
FromBlock(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockMatrix::BlockMatrix(const BlockMatrix& other) {
|
|
||||||
data = other.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockMatrix::FromBlock(const Block& block) {
|
|
||||||
|
|
||||||
const std::string blockstr = block.to_string();
|
|
||||||
constexpr std::size_t cellSize = sizeof(std::uint32_t)*8;
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < 16; i++) {
|
|
||||||
data[i] = std::bitset<cellSize>(blockstr.substr(i*cellSize, cellSize)).to_ulong();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Block BlockMatrix::ToBlock() const {
|
|
||||||
|
|
||||||
std::stringstream ss;
|
|
||||||
constexpr std::size_t cellSize = sizeof(std::uint32_t)*8;
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < 16; i++) {
|
|
||||||
ss << std::bitset<cellSize>(data[i]).to_string();
|
|
||||||
}
|
|
||||||
return Block(ss.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockMatrix BlockMatrix::MMult(const BlockMatrix& o) const {
|
|
||||||
|
|
||||||
BlockMatrix m;
|
|
||||||
|
|
||||||
m.Get(0, 0) = (this->Get(0, 0) * o.Get(0, 0)) + (this->Get(0, 1) * o.Get(1, 0)) + (this->Get(0, 2) * o.Get(2, 0)) + (this->Get(0, 3) * o.Get(3, 0));
|
|
||||||
m.Get(0, 1) = (this->Get(0, 0) * o.Get(0, 1)) + (this->Get(0, 1) * o.Get(1, 1)) + (this->Get(0, 2) * o.Get(2, 1)) + (this->Get(0, 3) * o.Get(3, 1));
|
|
||||||
m.Get(0, 2) = (this->Get(0, 0) * o.Get(0, 2)) + (this->Get(0, 1) * o.Get(1, 2)) + (this->Get(0, 2) * o.Get(2, 2)) + (this->Get(0, 3) * o.Get(3, 2));
|
|
||||||
m.Get(0, 3) = (this->Get(0, 0) * o.Get(0, 3)) + (this->Get(0, 1) * o.Get(1, 3)) + (this->Get(0, 2) * o.Get(2, 3)) + (this->Get(0, 3) * o.Get(3, 3));
|
|
||||||
|
|
||||||
m.Get(1, 0) = (this->Get(1, 0) * o.Get(0, 0)) + (this->Get(1, 1) * o.Get(1, 0)) + (this->Get(1, 2) * o.Get(2, 0)) + (this->Get(1, 3) * o.Get(3, 0));
|
|
||||||
m.Get(1, 1) = (this->Get(1, 0) * o.Get(0, 1)) + (this->Get(1, 1) * o.Get(1, 1)) + (this->Get(1, 2) * o.Get(2, 1)) + (this->Get(1, 3) * o.Get(3, 1));
|
|
||||||
m.Get(1, 2) = (this->Get(1, 0) * o.Get(0, 2)) + (this->Get(1, 1) * o.Get(1, 2)) + (this->Get(1, 2) * o.Get(2, 2)) + (this->Get(1, 3) * o.Get(3, 2));
|
|
||||||
m.Get(1, 3) = (this->Get(1, 0) * o.Get(0, 3)) + (this->Get(1, 1) * o.Get(1, 3)) + (this->Get(1, 2) * o.Get(2, 3)) + (this->Get(1, 3) * o.Get(3, 3));
|
|
||||||
|
|
||||||
m.Get(2, 0) = (this->Get(2, 0) * o.Get(0, 0)) + (this->Get(2, 1) * o.Get(1, 0)) + (this->Get(2, 2) * o.Get(2, 0)) + (this->Get(2, 3) * o.Get(3, 0));
|
|
||||||
m.Get(2, 1) = (this->Get(2, 0) * o.Get(0, 1)) + (this->Get(2, 1) * o.Get(1, 1)) + (this->Get(2, 2) * o.Get(2, 1)) + (this->Get(2, 3) * o.Get(3, 1));
|
|
||||||
m.Get(2, 2) = (this->Get(2, 0) * o.Get(0, 2)) + (this->Get(2, 1) * o.Get(1, 2)) + (this->Get(2, 2) * o.Get(2, 2)) + (this->Get(2, 3) * o.Get(3, 2));
|
|
||||||
m.Get(2, 3) = (this->Get(2, 0) * o.Get(0, 3)) + (this->Get(2, 1) * o.Get(1, 3)) + (this->Get(2, 2) * o.Get(2, 3)) + (this->Get(2, 3) * o.Get(3, 3));
|
|
||||||
|
|
||||||
m.Get(3, 0) = (this->Get(3, 0) * o.Get(0, 0)) + (this->Get(3, 1) * o.Get(1, 0)) + (this->Get(3, 2) * o.Get(2, 0)) + (this->Get(3, 3) * o.Get(3, 0));
|
|
||||||
m.Get(3, 1) = (this->Get(3, 0) * o.Get(0, 1)) + (this->Get(3, 1) * o.Get(1, 1)) + (this->Get(3, 2) * o.Get(2, 1)) + (this->Get(3, 3) * o.Get(3, 1));
|
|
||||||
m.Get(3, 2) = (this->Get(3, 0) * o.Get(0, 2)) + (this->Get(3, 1) * o.Get(1, 2)) + (this->Get(3, 2) * o.Get(2, 2)) + (this->Get(3, 3) * o.Get(3, 2));
|
|
||||||
m.Get(3, 3) = (this->Get(3, 0) * o.Get(0, 3)) + (this->Get(3, 1) * o.Get(1, 3)) + (this->Get(3, 2) * o.Get(2, 3)) + (this->Get(3, 3) * o.Get(3, 3));
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockMatrix BlockMatrix::operator*(const BlockMatrix& other) const {
|
|
||||||
return this->MMult(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockMatrix BlockMatrix::MXor(const BlockMatrix& o) const {
|
|
||||||
|
|
||||||
BlockMatrix m;
|
|
||||||
|
|
||||||
m.Get(0, 0) = this->Get(0, 0) ^ o.Get(0, 0) ^ this->Get(0, 1) ^ o.Get(1, 0) ^ this->Get(0, 2) ^ o.Get(2, 0) ^ this->Get(0, 3) ^ o.Get(3, 0);
|
|
||||||
m.Get(0, 1) = this->Get(0, 0) ^ o.Get(0, 1) ^ this->Get(0, 1) ^ o.Get(1, 1) ^ this->Get(0, 2) ^ o.Get(2, 1) ^ this->Get(0, 3) ^ o.Get(3, 1);
|
|
||||||
m.Get(0, 2) = this->Get(0, 0) ^ o.Get(0, 2) ^ this->Get(0, 1) ^ o.Get(1, 2) ^ this->Get(0, 2) ^ o.Get(2, 2) ^ this->Get(0, 3) ^ o.Get(3, 2);
|
|
||||||
m.Get(0, 3) = this->Get(0, 0) ^ o.Get(0, 3) ^ this->Get(0, 1) ^ o.Get(1, 3) ^ this->Get(0, 2) ^ o.Get(2, 3) ^ this->Get(0, 3) ^ o.Get(3, 3);
|
|
||||||
|
|
||||||
m.Get(1, 0) = this->Get(1, 0) ^ o.Get(0, 0) ^ this->Get(1, 1) ^ o.Get(1, 0) ^ this->Get(1, 2) ^ o.Get(2, 0) ^ this->Get(1, 3) ^ o.Get(3, 0);
|
|
||||||
m.Get(1, 1) = this->Get(1, 0) ^ o.Get(0, 1) ^ this->Get(1, 1) ^ o.Get(1, 1) ^ this->Get(1, 2) ^ o.Get(2, 1) ^ this->Get(1, 3) ^ o.Get(3, 1);
|
|
||||||
m.Get(1, 2) = this->Get(1, 0) ^ o.Get(0, 2) ^ this->Get(1, 1) ^ o.Get(1, 2) ^ this->Get(1, 2) ^ o.Get(2, 2) ^ this->Get(1, 3) ^ o.Get(3, 2);
|
|
||||||
m.Get(1, 3) = this->Get(1, 0) ^ o.Get(0, 3) ^ this->Get(1, 1) ^ o.Get(1, 3) ^ this->Get(1, 2) ^ o.Get(2, 3) ^ this->Get(1, 3) ^ o.Get(3, 3);
|
|
||||||
|
|
||||||
m.Get(2, 0) = this->Get(2, 0) ^ o.Get(0, 0) ^ this->Get(2, 1) ^ o.Get(1, 0) ^ this->Get(2, 2) ^ o.Get(2, 0) ^ this->Get(2, 3) ^ o.Get(3, 0);
|
|
||||||
m.Get(2, 1) = this->Get(2, 0) ^ o.Get(0, 1) ^ this->Get(2, 1) ^ o.Get(1, 1) ^ this->Get(2, 2) ^ o.Get(2, 1) ^ this->Get(2, 3) ^ o.Get(3, 1);
|
|
||||||
m.Get(2, 2) = this->Get(2, 0) ^ o.Get(0, 2) ^ this->Get(2, 1) ^ o.Get(1, 2) ^ this->Get(2, 2) ^ o.Get(2, 2) ^ this->Get(2, 3) ^ o.Get(3, 2);
|
|
||||||
m.Get(2, 3) = this->Get(2, 0) ^ o.Get(0, 3) ^ this->Get(2, 1) ^ o.Get(1, 3) ^ this->Get(2, 2) ^ o.Get(2, 3) ^ this->Get(2, 3) ^ o.Get(3, 3);
|
|
||||||
|
|
||||||
m.Get(3, 0) = this->Get(3, 0) ^ o.Get(0, 0) ^ this->Get(3, 1) ^ o.Get(1, 0) ^ this->Get(3, 2) ^ o.Get(2, 0) ^ this->Get(3, 3) ^ o.Get(3, 0);
|
|
||||||
m.Get(3, 1) = this->Get(3, 0) ^ o.Get(0, 1) ^ this->Get(3, 1) ^ o.Get(1, 1) ^ this->Get(3, 2) ^ o.Get(2, 1) ^ this->Get(3, 3) ^ o.Get(3, 1);
|
|
||||||
m.Get(3, 2) = this->Get(3, 0) ^ o.Get(0, 2) ^ this->Get(3, 1) ^ o.Get(1, 2) ^ this->Get(3, 2) ^ o.Get(2, 2) ^ this->Get(3, 3) ^ o.Get(3, 2);
|
|
||||||
m.Get(3, 3) = this->Get(3, 0) ^ o.Get(0, 3) ^ this->Get(3, 1) ^ o.Get(1, 3) ^ this->Get(3, 2) ^ o.Get(2, 3) ^ this->Get(3, 3) ^ o.Get(3, 3);
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::uint32_t& BlockMatrix::Get(const std::uint8_t row, const std::uint8_t column) const {
|
|
||||||
return data[column*4 + row];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint32_t& BlockMatrix::Get(const std::uint8_t row, const std::uint8_t column){
|
|
||||||
return data[column*4 + row];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BlockMatrix::operator==(const BlockMatrix& other) const {
|
|
||||||
return data == other.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BlockMatrix::operator!=(const BlockMatrix& other) const {
|
|
||||||
return data != other.data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -68,25 +68,27 @@ namespace Leonetienne::GCrypt {
|
|||||||
Block m_expanded = ExpansionFunction(m);
|
Block m_expanded = ExpansionFunction(m);
|
||||||
|
|
||||||
// Shift to left by 1
|
// Shift to left by 1
|
||||||
m_expanded = Shiftl(m_expanded, 1);
|
//m_expanded = Shiftl(m_expanded, 1);
|
||||||
|
m_expanded = (m_expanded);
|
||||||
|
|
||||||
// Matrix-mult with key
|
// Matrix-mult with key
|
||||||
m_expanded = (BlockMatrix(m_expanded) * BlockMatrix(key)).ToBlock();
|
m_expanded *= key;
|
||||||
|
|
||||||
// Non-linearly apply subsitution boxes
|
// Non-linearly apply subsitution boxes
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
const std::string m_str = m_expanded.to_string();
|
const std::string m_str = m_expanded.ToString();
|
||||||
for (std::size_t i = 0; i < BLOCK_SIZE; i += 4) {
|
for (std::size_t i = 0; i < BLOCK_SIZE; i += 4) {
|
||||||
ss << SBox(m_str.substr(i, 4));
|
ss << SBox(m_str.substr(i, 4));
|
||||||
}
|
}
|
||||||
m_expanded = Block(ss.str());
|
m_expanded = Block(ss.str());
|
||||||
|
|
||||||
// Return the compressed version, shifted by 3
|
// Return the compressed version, shifted by 3
|
||||||
return Shiftl(CompressionFunction(m_expanded), 3);
|
//return Shiftl(CompressionFunction(m_expanded), 3);
|
||||||
|
return (CompressionFunction(m_expanded));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Halfblock, Halfblock> Feistel::FeistelSplit(const Block& block) {
|
std::pair<Halfblock, Halfblock> Feistel::FeistelSplit(const Block& block) {
|
||||||
const std::string bits = block.to_string();
|
const std::string bits = block.ToString();
|
||||||
|
|
||||||
Halfblock l(bits.substr(0, bits.size() / 2));
|
Halfblock l(bits.substr(0, bits.size() / 2));
|
||||||
Halfblock r(bits.substr(bits.size() / 2));
|
Halfblock r(bits.substr(bits.size() / 2));
|
||||||
@ -119,7 +121,7 @@ namespace Leonetienne::GCrypt {
|
|||||||
|
|
||||||
Halfblock Feistel::CompressionFunction(const Block& block) {
|
Halfblock Feistel::CompressionFunction(const Block& block) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
const std::string bits = block.to_string();
|
const std::string bits = block.ToString();
|
||||||
|
|
||||||
std::unordered_map<std::string, std::string> compressionMap;
|
std::unordered_map<std::string, std::string> compressionMap;
|
||||||
compressionMap["0000"] = "10";
|
compressionMap["0000"] = "10";
|
||||||
@ -184,7 +186,8 @@ namespace Leonetienne::GCrypt {
|
|||||||
// Compress- substitute, and expand the seed key to form the initial and the second-initial round key
|
// Compress- substitute, and expand the seed key to form the initial and the second-initial round key
|
||||||
// This action is non-linear and irreversible, and thus strenghtens security.
|
// This action is non-linear and irreversible, and thus strenghtens security.
|
||||||
Halfblock compressedSeed1 = CompressionFunction(seedKey);
|
Halfblock compressedSeed1 = CompressionFunction(seedKey);
|
||||||
Halfblock compressedSeed2 = CompressionFunction(Shiftl(seedKey, 1)); // Shifting one key by 1 will result in a completely different compression
|
//Halfblock compressedSeed2 = CompressionFunction(Shiftl(seedKey, 1)); // Shifting one key by 1 will result in a completely different compression
|
||||||
|
Halfblock compressedSeed2 = CompressionFunction((seedKey)); // Shifting one key by 1 will result in a completely different compression
|
||||||
|
|
||||||
// To add further confusion, let's shift seed1 by 1 aswell (after compression, but before substitution)
|
// To add further confusion, let's shift seed1 by 1 aswell (after compression, but before substitution)
|
||||||
// but only if the total number of bits set are a multiple of 3
|
// but only if the total number of bits set are a multiple of 3
|
||||||
@ -192,10 +195,11 @@ namespace Leonetienne::GCrypt {
|
|||||||
const std::size_t setBits1 = compressedSeed1.count();
|
const std::size_t setBits1 = compressedSeed1.count();
|
||||||
|
|
||||||
if (setBits1 % 4 == 0) {
|
if (setBits1 % 4 == 0) {
|
||||||
compressedSeed1 = Shiftr(compressedSeed1, 1);
|
//compressedSeed1 = Shiftr(compressedSeed1, 1);
|
||||||
|
compressedSeed1 = (compressedSeed1);
|
||||||
}
|
}
|
||||||
else if (setBits1 % 3 == 0) {
|
else if (setBits1 % 3 == 0) {
|
||||||
compressedSeed1 = Shiftl(compressedSeed1, 1);
|
compressedSeed1 = (compressedSeed1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now apply substitution
|
// Now apply substitution
|
||||||
@ -224,7 +228,8 @@ namespace Leonetienne::GCrypt {
|
|||||||
Block newKey = roundKeys[i - 1];
|
Block newKey = roundKeys[i - 1];
|
||||||
|
|
||||||
// Shift to left by how many bits are set, modulo 8
|
// Shift to left by how many bits are set, modulo 8
|
||||||
newKey = Shiftl(newKey, newKey.count() % 8); // This action is irreversible
|
//newKey = Shiftl(newKey, newKey.count() % 8); // This action is irreversible
|
||||||
|
newKey = (newKey); // This action is irreversible
|
||||||
|
|
||||||
// Split into two halfblocks,
|
// Split into two halfblocks,
|
||||||
// apply F() to one halfblock with rk[i-2],
|
// apply F() to one halfblock with rk[i-2],
|
||||||
@ -255,7 +260,7 @@ namespace Leonetienne::GCrypt {
|
|||||||
#endif
|
#endif
|
||||||
void Feistel::ZeroKeyMemory() {
|
void Feistel::ZeroKeyMemory() {
|
||||||
for (Key& key : roundKeys) {
|
for (Key& key : roundKeys) {
|
||||||
key.reset();
|
key.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -52,14 +52,14 @@ namespace Leonetienne::GCrypt {
|
|||||||
// Slurp up the rest of the current block
|
// Slurp up the rest of the current block
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
const std::size_t bitsLeft = BLOCK_SIZE - nextBit;
|
const std::size_t bitsLeft = BLOCK_SIZE - nextBit;
|
||||||
ss << hasher.GetHashsum().to_string().substr(nextBit, bitsLeft);
|
ss << hasher.GetHashsum().ToString().substr(nextBit, bitsLeft);
|
||||||
|
|
||||||
// Now we have to advance to the next block
|
// Now we have to advance to the next block
|
||||||
AdvanceBlock();
|
AdvanceBlock();
|
||||||
|
|
||||||
// Now, grab the remaining bits
|
// Now, grab the remaining bits
|
||||||
const std::size_t remainingBits = BLOCK_SIZE - bitsLeft;
|
const std::size_t remainingBits = BLOCK_SIZE - bitsLeft;
|
||||||
ss << hasher.GetHashsum().to_string().substr(0, remainingBits);
|
ss << hasher.GetHashsum().ToString().substr(0, remainingBits);
|
||||||
|
|
||||||
// Assert that we have the correct number of bits
|
// Assert that we have the correct number of bits
|
||||||
assert(ss.str().length() == BLOCK_SIZE);
|
assert(ss.str().length() == BLOCK_SIZE);
|
||||||
|
@ -67,7 +67,7 @@ namespace Leonetienne::GCrypt {
|
|||||||
|
|
||||||
void Key::WriteToFile(const std::string& path) {
|
void Key::WriteToFile(const std::string& path) {
|
||||||
// Transform key to bytes
|
// Transform key to bytes
|
||||||
const std::string keybytes = BitsToBytes(to_string());
|
const std::string keybytes = BitsToBytes(ToString());
|
||||||
|
|
||||||
// Create an ofilestream
|
// Create an ofilestream
|
||||||
std::ofstream ofs(path, std::ios::out | std::ios::binary);
|
std::ofstream ofs(path, std::ios::out | std::ios::binary);
|
||||||
|
@ -53,7 +53,7 @@ namespace Leonetienne::GCrypt {
|
|||||||
std::string BitblockToBytes(const Block& bits) {
|
std::string BitblockToBytes(const Block& bits) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
const std::string bitstring = bits.to_string();
|
const std::string bitstring = bits.ToString();
|
||||||
|
|
||||||
for (std::size_t i = 0; i < BLOCK_SIZE; i += 8) {
|
for (std::size_t i = 0; i < BLOCK_SIZE; i += 8) {
|
||||||
ss << (char)std::bitset<8>(bitstring.substr(i, 8)).to_ulong();
|
ss << (char)std::bitset<8>(bitstring.substr(i, 8)).to_ulong();
|
||||||
@ -97,7 +97,7 @@ namespace Leonetienne::GCrypt {
|
|||||||
std::string BitblockToHexstring(const Block& b) {
|
std::string BitblockToHexstring(const Block& b) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
const std::string charset = "0123456789abcdef";
|
const std::string charset = "0123456789abcdef";
|
||||||
const std::string bstr = b.to_string();
|
const std::string bstr = b.ToString();
|
||||||
|
|
||||||
for (std::size_t i = 0; i < bstr.size(); i += 4) {
|
for (std::size_t i = 0; i < bstr.size(); i += 4) {
|
||||||
ss << charset[std::bitset<4>(bstr.substr(i, 4)).to_ulong()];
|
ss << charset[std::bitset<4>(bstr.substr(i, 4)).to_ulong()];
|
||||||
@ -139,7 +139,7 @@ namespace Leonetienne::GCrypt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Append to our bits
|
// Append to our bits
|
||||||
ss << std::bitset<4>(value);
|
ss << std::bitset<4>(value).to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Block(ss.str());
|
return Block(ss.str());
|
||||||
@ -166,7 +166,7 @@ namespace Leonetienne::GCrypt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Append to our bits
|
// Append to our bits
|
||||||
ss << std::bitset<4>(value);
|
ss << std::bitset<4>(value).to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
251
GCryptLib/test/Block.cpp
Normal file
251
GCryptLib/test/Block.cpp
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
#include <GCrypt/Block.h>
|
||||||
|
#include "Catch2.h"
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
using namespace Leonetienne::GCrypt;
|
||||||
|
|
||||||
|
// Tests that writing and retrieving data from a block works
|
||||||
|
TEST_CASE(__FILE__"/Write-read", "[Block]") {
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
Block block;
|
||||||
|
|
||||||
|
// Exercise
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
block.Get(i) = i * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
REQUIRE(block.Get(i) == i * 1024);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that the copy constructor works
|
||||||
|
TEST_CASE(__FILE__"/CCtor", "[Block]") {
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
Block block;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
block.Get(i) = i * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exercise
|
||||||
|
Block block2(block);
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
REQUIRE(block2.Get(i) == i * 1024);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that operator= works
|
||||||
|
TEST_CASE(__FILE__"/operator=", "[Block]") {
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
Block block;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
block.Get(i) = i * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exercise
|
||||||
|
Block block2;
|
||||||
|
block2 = block;
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
REQUIRE(block2.Get(i) == i * 1024);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that converting to, and from, strings works
|
||||||
|
TEST_CASE(__FILE__"/StringConversion", "[Block]") {
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
srand(time(0));
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < 512; i++) {
|
||||||
|
ss << (rand()%2 == 0 ? '1' : '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exercise
|
||||||
|
Block block(ss.str());
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
REQUIRE(block.ToString() == ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that operator* is the same as *=
|
||||||
|
TEST_CASE(__FILE__"/operator*&=", "[Block]") {
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
Block block1;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
block1.Get(i) = i * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block block2;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
block2.Get(i) = i * 1024 * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exercise
|
||||||
|
Block block3 = block1 * block2;
|
||||||
|
block1 *= block2;
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
REQUIRE(block1 == block3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that operator^ (xor) works
|
||||||
|
TEST_CASE(__FILE__"/xor", "[Block]") {
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
Block block;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
block.Get(i) = i * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block xorRH;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
xorRH.Get(i) = i * 5099;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exercise
|
||||||
|
Block result = block ^ xorRH;
|
||||||
|
|
||||||
|
Block manualResult;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
manualResult.Get(i) = (i * 1024) ^ (i * 5099);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
REQUIRE(result == manualResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that operator^ is the same as ^=
|
||||||
|
TEST_CASE(__FILE__"/operator^&=", "[Block]") {
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
Block block1;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
block1.Get(i) = i * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block block2;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
block2.Get(i) = i * 5099 * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exercise
|
||||||
|
Block block3 = block1 ^ block2;
|
||||||
|
block1 ^= block2;
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
REQUIRE(block1 == block3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that operator== works correctly
|
||||||
|
TEST_CASE(__FILE__"/operator==", "[Block]") {
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
Block block;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
block.Get(i) = i * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Expected true") {
|
||||||
|
Block sameBlock;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
sameBlock.Get(i) = i * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRE(block == sameBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Expected false") {
|
||||||
|
Block otherBlock;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
otherBlock.Get(i) = i * 1024 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRE_FALSE(block == otherBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that operator!= works correctly
|
||||||
|
TEST_CASE(__FILE__"/operator!=", "[Block]") {
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
Block block;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
block.Get(i) = i * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Expected false") {
|
||||||
|
Block sameBlock;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
sameBlock.Get(i) = i * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRE_FALSE(block != sameBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Expected true") {
|
||||||
|
Block otherBlock;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
otherBlock.Get(i) = i * 1024 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
REQUIRE(block != otherBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that getting the data via the matrix accessor works
|
||||||
|
TEST_CASE(__FILE__"/matrix-accessor", "[Block]") {
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
Block block;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
block.Get(i) = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exercise
|
||||||
|
REQUIRE(block.Get(0,0) == 0);
|
||||||
|
REQUIRE(block.Get(1,0) == 1);
|
||||||
|
REQUIRE(block.Get(2,0) == 2);
|
||||||
|
REQUIRE(block.Get(3,0) == 3);
|
||||||
|
REQUIRE(block.Get(0,1) == 4);
|
||||||
|
REQUIRE(block.Get(1,1) == 5);
|
||||||
|
REQUIRE(block.Get(2,1) == 6);
|
||||||
|
REQUIRE(block.Get(3,1) == 7);
|
||||||
|
REQUIRE(block.Get(0,2) == 8);
|
||||||
|
REQUIRE(block.Get(1,2) == 9);
|
||||||
|
REQUIRE(block.Get(2,2) == 10);
|
||||||
|
REQUIRE(block.Get(3,2) == 11);
|
||||||
|
REQUIRE(block.Get(0,3) == 12);
|
||||||
|
REQUIRE(block.Get(1,3) == 13);
|
||||||
|
REQUIRE(block.Get(2,3) == 14);
|
||||||
|
REQUIRE(block.Get(3,3) == 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that the reset method works
|
||||||
|
TEST_CASE(__FILE__"/reset", "[Block]") {
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
Block block;
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
block.Get(i) = i + 33;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exercise
|
||||||
|
block.Reset();
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
for (std::size_t i = 0; i < 16; i++) {
|
||||||
|
REQUIRE(block[i] == 0);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
#include <GCrypt/Util.h>
|
#include <GCrypt/Util.h>
|
||||||
|
#include <GCrypt/Block.h>
|
||||||
#include <GCrypt/Config.h>
|
#include <GCrypt/Config.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -59,7 +60,7 @@ TEST_CASE(__FILE__"/Password to key transformation collision resistance", "[Key
|
|||||||
// This will take a LONG while to execute though (about 2.5hrs on my machine), hence why it's set so low.
|
// This will take a LONG while to execute though (about 2.5hrs on my machine), hence why it's set so low.
|
||||||
constexpr std::size_t NUM_RUN_TESTS = 10;
|
constexpr std::size_t NUM_RUN_TESTS = 10;
|
||||||
|
|
||||||
std::unordered_map<std::bitset<BLOCK_SIZE>, std::string> keys; // <key, password>
|
std::unordered_map<std::string, std::string> keys; // <key, password>
|
||||||
|
|
||||||
// Try NUM_RUN_TESTS passwords
|
// Try NUM_RUN_TESTS passwords
|
||||||
const std::string charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
const std::string charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
@ -69,23 +70,23 @@ TEST_CASE(__FILE__"/Password to key transformation collision resistance", "[Key
|
|||||||
const std::string password = Base10_2_X(i, charset, 0);
|
const std::string password = Base10_2_X(i, charset, 0);
|
||||||
|
|
||||||
// Generate key
|
// Generate key
|
||||||
const std::bitset<BLOCK_SIZE> newKey = Key::FromPassword(password).Get();
|
const std::string newKeyBits = Key::FromPassword(password).ToString();
|
||||||
|
|
||||||
// Check if this block is already in our map
|
// Check if this block is already in our map
|
||||||
if (keys.find(newKey) != keys.cend()) {
|
if (keys.find(newKeyBits) != keys.cend()) {
|
||||||
std::cout << "Collision found between password \""
|
std::cout << "Collision found between password \""
|
||||||
<< password
|
<< password
|
||||||
<< "\" and \""
|
<< "\" and \""
|
||||||
<< keys[newKey]
|
<< keys[newKeyBits]
|
||||||
<< "\". The key is \""
|
<< "\". The key is \""
|
||||||
<< newKey
|
<< newKeyBits
|
||||||
<< "\".";
|
<< "\".";
|
||||||
|
|
||||||
FAIL();
|
FAIL();
|
||||||
}
|
}
|
||||||
|
|
||||||
// All good? Insert it into our map
|
// All good? Insert it into our map
|
||||||
keys[newKey] = password;
|
keys[newKeyBits] = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user