diff --git a/GCryptLib/include/GCrypt/Block.h b/GCryptLib/include/GCrypt/Block.h index 3fefbd5..d6c2b8c 100644 --- a/GCryptLib/include/GCrypt/Block.h +++ b/GCryptLib/include/GCrypt/Block.h @@ -123,6 +123,9 @@ namespace Leonetienne::GCrypt { //! Will zero all data void Reset(); + //! Will return the state of any given bit + [[nodiscard]] bool GetBit(const std::size_t index) const; + //! Returns 32-bit chunks of data, indexed by matrix coordinates (0-3) [[nodiscard]] 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) diff --git a/GCryptLib/src/Block.cpp b/GCryptLib/src/Block.cpp index bd16dd1..b2b5660 100644 --- a/GCryptLib/src/Block.cpp +++ b/GCryptLib/src/Block.cpp @@ -1,4 +1,5 @@ #include "GCrypt/Block.h" +#include #include "GCrypt/Config.h" #include #include @@ -447,6 +448,16 @@ namespace Leonetienne::GCrypt { return *this; } + bool Block::GetBit(const std::size_t index) const { + // Fetch index of integer the bit is located in + const std::size_t intIndex = index / CHUNK_SIZE_BITS; + + // Fetch bit index relative to that int + const std::size_t relBitIndex = index - (intIndex * CHUNK_SIZE_BITS); + + return data[intIndex] & (1 << (CHUNK_SIZE_BITS - relBitIndex - 1)); + } + std::uint32_t& Block::Get(const std::uint8_t row, const std::uint8_t column){ return data[MAT_INDEX(row, column)]; } diff --git a/GCryptLib/test/Block.cpp b/GCryptLib/test/Block.cpp index 09730f7..0a9976b 100644 --- a/GCryptLib/test/Block.cpp +++ b/GCryptLib/test/Block.cpp @@ -633,3 +633,18 @@ TEST_CASE(__FILE__"/multiple-combined-shifts-and-additions-can-be-undone", "[Blo REQUIRE(a == initial_a); } +// Tests that the get-bit method works +TEST_CASE(__FILE__"/get-bit", "[Block]") { + // Setup + Block a = Key::FromPassword("Halleluja"); + + // Exercise + std::stringstream ss; + for (std::size_t i = 0; i < 512; i++) { + ss << a.GetBit(i); + } + + // Verify + REQUIRE(ss.str() == a.ToString()); +} +