diff --git a/GCryptLib/test/Password2Key_CollisionResistance.cpp b/GCryptLib/test/Password2Key_CollisionResistance.cpp index dbd0e19..8cad00a 100644 --- a/GCryptLib/test/Password2Key_CollisionResistance.cpp +++ b/GCryptLib/test/Password2Key_CollisionResistance.cpp @@ -1,112 +1,93 @@ -/* -#include "CppUnitTest.h" -#include "../GhettoCrypt/Util.h" -#include "../GhettoCrypt/Config.h" +#include +#include #include -#include #include +#include +#include "Catch2.h" -using namespace Microsoft::VisualStudio::CppUnitTestFramework; -using namespace GhettoCipher; +using namespace Leonetienne::GCrypt; // We can generate passwords by just translating a decimal number to base "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" -inline std::string Base10_2_X(const unsigned long long int i, const std::string set, unsigned int padding) -{ - if (set.length() == 0) - return ""; // Return empty string, if set is empty. Play stupid games, win stupid prizes. +// So this is just a helper function to generate random passwords +inline std::string Base10_2_X(const unsigned long long int i, const std::string set, unsigned int padding) { + if (set.length() == 0) + return ""; // Return empty string, if set is empty. Play stupid games, win stupid prizes. - std::stringstream ss; + std::stringstream ss; - if (i != 0) - { - { - unsigned long long int buf = i; - while (buf != 0) - { - const unsigned long long int mod = buf % set.length(); - buf /= set.length(); - ss << set[(std::size_t)mod]; - } - } - { - const std::string buf = ss.str(); - ss.str(""); - for (long long int i = buf.length() - 1; i >= 0; i--) - ss << buf[(std::size_t)i]; - } - } - else - { - ss << set[0]; // If i is 0, just pass a null-value. The algorithm would hang otherwise. - } + if (i != 0) { + { + unsigned long long int buf = i; + while (buf != 0) { + const unsigned long long int mod = buf % set.length(); + buf /= set.length(); + ss << set[(std::size_t)mod]; + } + } + { + const std::string buf = ss.str(); + ss.str(""); + for (long long int i = buf.length() - 1; i >= 0; i--) { + ss << buf[(std::size_t)i]; + } + } + } + else { + ss << set[0]; // If i is 0, just pass a null-value. The algorithm would hang otherwise. + } - // Add as much null-values to the left as requested. - if (ss.str().length() < padding) - { - const std::size_t cachedLen = ss.str().length(); - const std::string cachedStr = ss.str(); - ss.str(""); - for (std::size_t i = 0; i < padding - cachedLen; i++) - ss << set[0]; - ss << cachedStr; - } + // Add as much null-values to the left as requested. + if (ss.str().length() < padding) { + const std::size_t cachedLen = ss.str().length(); + const std::string cachedStr = ss.str(); + ss.str(""); + for (std::size_t i = 0; i < padding - cachedLen; i++) { + ss << set[0]; + } + ss << cachedStr; + } - return ss.str(); + return ss.str(); } -using convert_t = std::codecvt_utf8; +// Run a few thousand random passwords through the keygen and see if we'll find a collision. +// This test passing does NOT mean that it's resistant! Maybe good, maybe shit! But if it fails, it's definitely shit. +// Already validated range: Password 0 - 1.000.000 +TEST_CASE(__FILE__"/Password to key transformation collision resistance", "[Key extrapolation]") { -namespace SimpleTests -{ - TEST_CLASS(Password2Key) - { - public: + // To test resistence set this to a high number around a million. + // 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 = 1000; - // Run a few thousand random passwords through the keygen and see if we'll find a collision. - // This test passing does NOT mean that it's resistant! Maybe good, maybe shit! But if it fails, it's definitely shit. - // Already validated range: Password 0 - 1.000.000 - TEST_METHOD(CollisionResistance) - { - // To test resistence set this to a high number around a million. - // 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 = 1000; + std::unordered_map, std::string> keys; // - std::unordered_map, std::string> keys; // + // Try NUM_RUN_TESTS passwords + const std::string charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - // Try NUM_RUN_TESTS passwords - const std::string charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + for (std::size_t i = 0; i < NUM_RUN_TESTS; i++) { + // Get password + const std::string password = Base10_2_X(i, charset, 0); - std::wstring_convert strconverter; + // Generate key + const std::bitset newKey = PasswordToKey(password).Get(); - for (std::size_t i = 0; i < NUM_RUN_TESTS; i++) - { - // Get password - const std::string password = Base10_2_X(i, charset, 0); - - // Generate key - const std::bitset newKey = PasswordToKey(password).Get(); + // Check if this block is already in our map + if (keys.find(newKey) != keys.cend()) { + std::cout << "Collision found between password \"" + << password + << "\" and \"" + << keys[newKey] + << "\". The key is \"" + << newKey + << "\"."; - // Check if this block is already in our map - if (keys.find(newKey) != keys.cend()) - { - std::wstringstream wss; - wss << "Collision found between password \"" - << strconverter.from_bytes(password) - << "\" and \"" - << strconverter.from_bytes(keys[newKey]) - << "\". The key is \"" - << newKey - << "\"."; + FAIL(); + } - Assert::Fail(wss.str().c_str()); - } + // All good? Insert it into our map + keys[newKey] = password; + } - // All good? Insert it into our map - keys[newKey] = password; - } - - return; - } - }; + return; } -*/ +