[Progress:] Completely re-done Block class to not use bitsets, and provide custom operators.
This commit is contained in:
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/Block.h>
|
||||
#include <GCrypt/Config.h>
|
||||
#include <unordered_map>
|
||||
#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.
|
||||
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
|
||||
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);
|
||||
|
||||
// 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
|
||||
if (keys.find(newKey) != keys.cend()) {
|
||||
if (keys.find(newKeyBits) != keys.cend()) {
|
||||
std::cout << "Collision found between password \""
|
||||
<< password
|
||||
<< "\" and \""
|
||||
<< keys[newKey]
|
||||
<< keys[newKeyBits]
|
||||
<< "\". The key is \""
|
||||
<< newKey
|
||||
<< newKeyBits
|
||||
<< "\".";
|
||||
|
||||
FAIL();
|
||||
}
|
||||
|
||||
// All good? Insert it into our map
|
||||
keys[newKey] = password;
|
||||
keys[newKeyBits] = password;
|
||||
}
|
||||
|
||||
return;
|
||||
|
Reference in New Issue
Block a user