2022-06-01 16:54:14 +02:00

217 lines
7.9 KiB
C++

#ifndef GCRYPT_BLOCK_H
#define GCRYPT_BLOCK_H
#include <cstdint>
#include <array>
#include <string>
#include <iosfwd>
#include <bitset>
namespace Leonetienne::GCrypt {
/** This class represents a block of data,
* and provides functions to manipulate it
*/
template <typename T>
class Basic_Block {
public:
//! Will constuct an uninitialized data block
Basic_Block();
//! Will construct this block from a string like "101010".. Length MUST be 512.
Basic_Block(const std::string& other);
//! Copy-ctor
Basic_Block(const Basic_Block<T>& other);
~Basic_Block();
//! Will construct this block from a string like "011101..".
void FromBinaryString(const std::string& str);
//! Will construct this block from a hexstring
void FromHexString(const std::string& str);
//! Will construct this block from a bytestring (any characters)
void FromByteString(const std::string& str);
//! Will construct this block from a textstring (any length)
void FromTextString(const std::string& str);
//! Will create a bitset-compatible string ("0101110..") representation
//! of this block. Length will always be 512.
std::string ToBinaryString() const;
//! Will create a hexstring representation of this block.
std::string ToHexString() const;
//! Will create a bytestring representation of this block.
std::string ToByteString() const;
//! Will create a textstring representation of this block.
//! The difference to a bytestring is that it gets trimmed after a nullterminator.
std::string ToTextString() 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.
[[nodiscard]] Basic_Block<T> MMul(const Basic_Block<T>& other) const;
[[nodiscard]] Basic_Block<T> operator*(const Basic_Block<T>& 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 Basic_Block<T>& other);
Basic_Block<T>& operator*=(const Basic_Block<T>& other);
//! Will xor two blocks together
[[nodiscard]] Basic_Block<T> Xor(const Basic_Block<T>& other) const;
//! Will xor two blocks together
[[nodiscard]] Basic_Block<T> operator^(const Basic_Block<T>& other) const;
//! Will xor two blocks together, inplace
void XorInplace(const Basic_Block<T>& other);
//! Will xor two blocks together, inplace
Basic_Block<T>& operator^=(const Basic_Block<T>& other);
//! Will add all the integer making up this block, one by one
[[nodiscard]] Basic_Block<T> Add(const Basic_Block<T>& other) const;
//! Will add all the integer making up this block, one by one
[[nodiscard]] Basic_Block<T> operator+(const Basic_Block<T>& other) const;
//! Will add all the integer making up this block, one by one, inplace
void AddInplace(const Basic_Block<T>& other);
//! Will add all the integer making up this block, one by one, inplace
Basic_Block<T>& operator+=(const Basic_Block<T>& other);
//! Will subtract all the integer making up this block, one by one
[[nodiscard]] Basic_Block<T> Sub(const Basic_Block<T>& other) const;
//! Will subtract all the integer making up this block, one by one
[[nodiscard]] Basic_Block<T> operator-(const Basic_Block<T>& other) const;
//! Will subtract all the integer making up this block, one by one, inplace
void SubInplace(const Basic_Block<T>& other);
//! Will subtract all the integer making up this block, one by one, inplace
Basic_Block<T>& operator-=(const Basic_Block<T>& other);
//! Will shift rows upwards by 1
[[nodiscard]] Basic_Block<T> ShiftRowsUp() const;
//! Will shift rows upwards by 1
void ShiftRowsUpInplace();
//! Will shift matrix rows downwards by 1
[[nodiscard]] Basic_Block<T> ShiftRowsDown() const;
//! Will shift matrix rows downwards by 1
void ShiftRowsDownInplace();
//! Will shift matrix columns to the left by 1
[[nodiscard]] Basic_Block<T> ShiftColumnsLeft() const;
//! Will shift matrix columns to the left by 1
void ShiftColumnsLeftInplace();
//! Will shift matrix columns to the right by 1
[[nodiscard]] Basic_Block<T> ShiftColumnsRight() const;
//! Will shift matrix columns to the right by 1
void ShiftColumnsRightInplace();
//! Will shift array cells to the left by 1
[[nodiscard]] Basic_Block<T> ShiftCellsLeft() const;
//! Will shift array cells to the left by 1
void ShiftCellsLeftInplace();
//! Will shift array cells to the right by 1
[[nodiscard]] Basic_Block<T> ShiftCellsRight() const;
//! Will shift array cells to the right by 1
void ShiftCellsRightInplace();
//! Will copy a block
Basic_Block<T>& operator=(const Basic_Block<T>& other);
//! Will compare whether or not two blocks are equal
[[nodiscard]] bool operator==(const Basic_Block<T>& other) const;
//! Will compare whether or not two blocks are unequal
[[nodiscard]] bool operator!=(const Basic_Block<T>& other) const;
//! Will zero all data
void Reset();
//! Will return the state of any given bit
[[nodiscard]] bool GetBit(const std::size_t index) const;
//! Will set the state of any given bit
void SetBit(const std::size_t index, const bool state);
//! Will flip the state of any given bit
void FlipBit(const std::size_t index);
//! Will shift all bits to the left by 1
[[nodiscard]] Basic_Block<T> ShiftBitsLeft() const;
//! Will shift all bits to the left by 1, inplace
void ShiftBitsLeftInplace();
//! Will shift all bits to the right by 1
[[nodiscard]] Basic_Block<T> ShiftBitsRight() const;
//! Will shift all bits to the right by 1, inplace
void ShiftBitsRightInplace();
//! Returns 32-bit chunks of data, indexed by matrix coordinates (0-3)
[[nodiscard]] T& Get(const std::uint8_t row, const std::uint8_t column);
//! Returns 32-bit chunks of data, indexed by matrix coordinates (0-3)
[[nodiscard]] const 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)
[[nodiscard]] T& Get(const std::uint8_t index);
//! Returns 32-bit chunks of data, indexed by a 1d-index (0-16)
[[nodiscard]] const T& Get(const std::uint8_t index) const;
//! Returns 32-bit chunks of data, indexed by a 1d-index (0-16)
[[nodiscard]] T& operator[](const std::uint8_t index);
//! Returns 32-bit chunks of data, indexed by a 1d-index (0-16)
[[nodiscard]] const T& operator[](const std::uint8_t index) const;
//! Will return a reference to the data array
T* Data() noexcept;
//! Will return a reference to the data array
const T* Data() const noexcept;
static constexpr std::size_t CHUNK_SIZE = sizeof(T);
static constexpr std::size_t CHUNK_SIZE_BITS = CHUNK_SIZE * 8;
static constexpr std::size_t BLOCK_SIZE = CHUNK_SIZE * 16;
static constexpr std::size_t BLOCK_SIZE_BITS = CHUNK_SIZE_BITS * 16;
friend std::ostream& operator<<(std::ostream& os, const Basic_Block<T>& b) {
for (std::size_t i = 0; i < b.data.size(); i++) {
os << std::bitset<Basic_Block<T>::CHUNK_SIZE_BITS>(b.data[i]).to_string();
}
return os;
}
private:
std::array<T, 16> data;
};
//! This a full-sized 512-bit block
typedef Basic_Block<std::uint32_t> Block;
//! This is a half-block used within the feistel class
typedef Basic_Block<std::uint16_t> Halfblock;
}
#endif