diff --git a/GCryptLib/include/GCrypt/BlockMatrix.h b/GCryptLib/include/GCrypt/BlockMatrix.h new file mode 100644 index 0000000..6f28a84 --- /dev/null +++ b/GCryptLib/include/GCrypt/BlockMatrix.h @@ -0,0 +1,49 @@ +#ifndef GCRYPT_BLOCKMATRIX_H +#define GCRYPT_BLOCKMATRIX_H + +#include "GCrypt/Block.h" +#include +#include + +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 data; + }; + +} + + +#endif + diff --git a/GCryptLib/include/GCrypt/Config.h b/GCryptLib/include/GCrypt/Config.h index dd56656..0bcac82 100644 --- a/GCryptLib/include/GCrypt/Config.h +++ b/GCryptLib/include/GCrypt/Config.h @@ -8,7 +8,7 @@ namespace Leonetienne::GCrypt { constexpr std::size_t BLOCK_SIZE = 512; // MUST BE > 2 - constexpr std::size_t N_ROUNDS = 400; + constexpr std::size_t N_ROUNDS = 10; } #endif diff --git a/GCryptLib/include/GCrypt/Version.h b/GCryptLib/include/GCrypt/Version.h index ff66ec4..256c32b 100644 --- a/GCryptLib/include/GCrypt/Version.h +++ b/GCryptLib/include/GCrypt/Version.h @@ -1,7 +1,7 @@ #ifndef GCRYPT_VERSION_H #define GCRYPT_VERSION_H -#define GCRYPT_VERSION 0.23 +#define GCRYPT_VERSION 0.231 #endif diff --git a/GCryptLib/src/BlockMatrix.cpp b/GCryptLib/src/BlockMatrix.cpp new file mode 100644 index 0000000..e1915c9 --- /dev/null +++ b/GCryptLib/src/BlockMatrix.cpp @@ -0,0 +1,114 @@ +#include "GCrypt/BlockMatrix.h" +#include + +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(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(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; + } +} + diff --git a/GCryptLib/src/Feistel.cpp b/GCryptLib/src/Feistel.cpp index 9ac75da..31d916d 100644 --- a/GCryptLib/src/Feistel.cpp +++ b/GCryptLib/src/Feistel.cpp @@ -1,6 +1,7 @@ #include #include "GCrypt/Feistel.h" #include "GCrypt/Util.h" +#include "GCrypt/BlockMatrix.h" #include "GCrypt/Config.h" namespace Leonetienne::GCrypt { @@ -69,8 +70,8 @@ namespace Leonetienne::GCrypt { // Shift to left by 1 m_expanded = Shiftl(m_expanded, 1); - // Xor with key - m_expanded ^= key; + // Matrix-mult with key + m_expanded = (BlockMatrix(m_expanded) * BlockMatrix(key)).ToBlock(); // Non-linearly apply subsitution boxes std::stringstream ss;