From f511299dfd050e069dbf4de51025e07eeaeefdb1 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Fri, 7 Mar 2025 18:50:50 +0100 Subject: [PATCH 01/46] fix cmake project not including key class --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d76f4b3..a6aff9b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,7 @@ add_executable(RSA-Encryptor main.cpp utility.cpp - keys.cpp + key.cpp encryption.cpp cli.cpp ) From 417b0a3695dcd2875b34dba0ec960ce35d24868b Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 9 Mar 2025 14:26:45 +0100 Subject: [PATCH 02/46] remove old files --- src/keys.cpp | 30 ------------------------------ src/keys.h | 13 ------------- 2 files changed, 43 deletions(-) delete mode 100644 src/keys.cpp delete mode 100644 src/keys.h diff --git a/src/keys.cpp b/src/keys.cpp deleted file mode 100644 index a8a51e2..0000000 --- a/src/keys.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include "keys.h" - - -void keys::createRSAKey() { - std::string keyName; - - std::cout << "Enter the name of the key: "; - std::cin >> keyName; - - // Navigate to the root directory of the project - std::filesystem::path programRootPath = std::filesystem::current_path().parent_path(); - std::filesystem::path keysFolder = programRootPath / KEY_FOLDER; - - // Check if keys folder exists - if (!std::filesystem::exists(keysFolder)) { - // Create the "RSA-Keys" directory in the root folder fo the program - std::filesystem::create_directory(keysFolder); - } - - std::cout << "You can find your newly created key here: " << keysFolder << std::endl; -} - -std::pair getPrivateKey(std::string& name) { - return {647'090'566'899, 234'099'456'876'004}; -} - -std::pair getPublicKey(std::string& name) { - return {143'548'453'234, 234'099'456'876'004}; -} \ No newline at end of file diff --git a/src/keys.h b/src/keys.h deleted file mode 100644 index 670fc4d..0000000 --- a/src/keys.h +++ /dev/null @@ -1,13 +0,0 @@ -#include - -#define KEY_FOLDER "rsa-keys" - - -class keys { - -public: - static void createRSAKey(); - - std::pair getPrivateKey(std::string& name); - std::pair getPublicKey(std::string& name); -}; \ No newline at end of file From dcdaa6310b4bdaae014070a6c63c3ddf5808f40a Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 9 Mar 2025 15:07:06 +0100 Subject: [PATCH 03/46] refactor namespace key inside namespace cli into keyManager --- src/cli.cpp | 10 +++++----- src/cli.h | 2 +- src/main.cpp | 24 ++++-------------------- 3 files changed, 10 insertions(+), 26 deletions(-) diff --git a/src/cli.cpp b/src/cli.cpp index 7ece695..750ab30 100644 --- a/src/cli.cpp +++ b/src/cli.cpp @@ -1,18 +1,18 @@ #include #include "cli.h" -#include "keys.h" +#include "key.h" void cli::help() { std::cout << "Welcome to RSA-Encryptor" << std::endl; } -void cli::key::create() { - keys::createRSAKey(); +void cli::keyManager::create() { + key::createRSAKey(); } -void cli::key::list() { +void cli::keyManager::list() { } -void cli::key::print(const std::string& name, bool publicKey, bool privateKey) { +void cli::keyManager::print(const std::string& name, bool publicKey, bool privateKey) { } diff --git a/src/cli.h b/src/cli.h index 972d471..1fa9354 100644 --- a/src/cli.h +++ b/src/cli.h @@ -1,7 +1,7 @@ namespace cli { void help(); - namespace key { + namespace keyManager { void create(); void list(); void print(const std::string& name, bool publicKey, bool privateKey); diff --git a/src/main.cpp b/src/main.cpp index 07b69a1..bfd2a4b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include "utility.h" #include "cli.h" +#include "key.h" #include "vec/operations.h" int main(int argc, char* argv[]) { @@ -31,19 +32,17 @@ int main(int argc, char* argv[]) { } } - std::cout << arguments.publicKey << std::endl; - std::string feature = argv[1]; if (feature == "key" && argv[2] != nullptr) { std::string subFeature = argv[2]; if (subFeature == "create") { - cli::key::create(); + cli::keyManager::create(); } else if (subFeature == "list") { - cli::key::list(); + cli::keyManager::list(); } else if (subFeature == "print") { - cli::key::print(argv[3], arguments.publicKey, arguments.privateKey); + cli::keyManager::print(argv[3], arguments.publicKey, arguments.privateKey); } } else if (feature == "help") { @@ -55,20 +54,5 @@ int main(int argc, char* argv[]) { cli::help(); } - // std::cout << util.checkForPrime(54557) << std::endl; - // std::cout << util.checkForPrime(29) << std::endl; - //std::vector num1 = {255, 255, 255}; // 16777215 in dezimal - //std::vector num2 = {0x01}; // Add one - - std::vector num1 = convertToVector(16777215); // 16777215 in dezimal - std::vector num2 = convertToVector(1); // Add one - - std::vector result = add(num1, num2); - - // This gives out the result as a hex number - for (auto it = result.rbegin(); it != result.rend(); ++it) { - printf("%02X", *it); - } - std::cout << std::endl; return 0; } From 9d629f0ac264d2734efb7b66dde15c38bb3f5ff9 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 9 Mar 2025 15:07:30 +0100 Subject: [PATCH 04/46] add base64Encode functionality --- src/key.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++------- src/key.h | 11 +++++++++-- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index 237d242..05725ca 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -12,6 +12,7 @@ std::filesystem::path key::keysPath() { } int key::keyExists(std::string name) { + // TODO fix function not case sensitive /* 0: key doesn't exist * 1: only publicKey exists * 2: only privateKey exists @@ -39,16 +40,21 @@ int key::keyExists(std::string name) { return status; } -int key::writeKey(const std::string& name, const unsigned long int data, const bool isPublic) { +int key::writeKey(const std::string& name, std::vector data, const bool isPublic) { std::filesystem::path keysFolder = keysPath(); std::filesystem::path keyFile = keysFolder / (name + (isPublic? ".pub":"")); + // load file in memory std::ofstream outFile(keyFile); + // key in base64 format + std::string base64Data = base64Encode(data); + if (outFile.is_open()) { - std::string dataStr = std::to_string(data); outFile << "-----BEGIN RSA " << (isPublic? "PUBLIC":"PRIVATE") << " KEY-----\n"; - outFile << base64_encode(dataStr) << "\n"; + for (int i = 0; i < base64Data.size(); i += 64) { + outFile << base64Data.substr(i, 64) << "\n"; + } outFile << "-----END RSA " << (isPublic? "PUBLIC":"PRIVATE") << " KEY-----\n"; outFile.close(); } else { @@ -59,9 +65,43 @@ int key::writeKey(const std::string& name, const unsigned long int data, const b return 1; } -std::string key::base64_encode(std::string &data) { - //TODO Add base 64 encode function - return data; +std::string key::base64Encode(std::vector data) { + + const unsigned int charCount = data.size() * 1.5; + char* result = new char[charCount]; + unsigned int resultIndex = charCount - 1; + + while (!data.empty()) { + + uint32_t dataSegment = 0; + + // pop 3 numbers from the data vector and store it as one block in dataSegment + for (int i = 0; i < 3; i++) { + if (data.size() < 1) break; + uint8_t number = data.back(); + data.pop_back(); + dataSegment += number << i * 8; + } + + // 4 times, put 6 bits from dataSegment into result array + for (int j = 0; j < 4; j++) { + if (resultIndex < 1) break; + result[resultIndex--] = static_cast(dataSegment & 0b00111111); + dataSegment >>= 6; + } + } + + std::string outString; + + // convert the numeric value to the corresponding char of the base64 charset + for (char& c : std::string(result, charCount)) { + outString += base64Chars[c]; + } + + // free memory space + delete[] result; + + return outString; } void key::createRSAKey() { @@ -84,7 +124,7 @@ void key::createRSAKey() { return; } - if (writeKey(keyName, 0, true) == 1 && writeKey(keyName, 0, false) == 1) { + if (writeKey(keyName, {0}, true) == 1 && writeKey(keyName, {0}, false) == 1) { std::cout << keyName + " key successfully created!\n"; std::cout << "You can find your newly created key here: " << keysFolder << std::endl; } else { diff --git a/src/key.h b/src/key.h index 823741a..f315277 100644 --- a/src/key.h +++ b/src/key.h @@ -1,5 +1,7 @@ #include #include +#include +#include #define KEY_FOLDER "rsa-keys" @@ -10,17 +12,22 @@ enum { BOTH }; +const char base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + class key { private: static std::filesystem::path keysPath(); static int keyExists(std::string name); static void generatePublicFromPrivate(); - static int writeKey(const std::string &name, unsigned long int data, bool isPublic); - static std::string base64_encode(std::string &data); + static int writeKey(const std::string &name, std::vector data, bool isPublic); + static std::vector base64Decode(std::string data); public: static void createRSAKey(); + // TODO + static std::string base64Encode(std::vector data); + static std::pair getPrivateKey(std::string &name); static std::pair getPublicKey(std::string &name); }; \ No newline at end of file From 0a9cd890dd3c9c517162786f31719dd53ef9e813 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 9 Mar 2025 18:22:53 +0100 Subject: [PATCH 05/46] add base64 Decode logic --- src/key.cpp | 78 ++++++++++++++++++++++++++++++++++++++++------------ src/key.h | 9 +++--- src/main.cpp | 2 ++ 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index 05725ca..c5dab74 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -65,45 +65,89 @@ int key::writeKey(const std::string& name, std::vector data, const bool return 1; } -std::string key::base64Encode(std::vector data) { +std::string key::base64Encode(const std::vector &data) { + // TODO the encoding might not work if the data size is not dividable by 3 + if (data.size() % 3 != 0) std::cerr << "Encoding data size not dividable by 3" << std::endl; - const unsigned int charCount = data.size() * 1.5; - char* result = new char[charCount]; - unsigned int resultIndex = charCount - 1; + std::vector result; + int index = 0; - while (!data.empty()) { + while (index < data.size()) { uint32_t dataSegment = 0; - // pop 3 numbers from the data vector and store it as one block in dataSegment - for (int i = 0; i < 3; i++) { - if (data.size() < 1) break; - uint8_t number = data.back(); - data.pop_back(); + // take 3 numbers from the vector + for (int i = 2; i >= 0; i--) { + // prevent from reading outside the vector + if (index > data.size() - 1) break; + + uint8_t number = data.at(index++); dataSegment += number << i * 8; } // 4 times, put 6 bits from dataSegment into result array for (int j = 0; j < 4; j++) { - if (resultIndex < 1) break; - result[resultIndex--] = static_cast(dataSegment & 0b00111111); - dataSegment >>= 6; + dataSegment <<= 6; + result.push_back(static_cast((dataSegment & 0b00111111 << 24) >> 24)); } } std::string outString; // convert the numeric value to the corresponding char of the base64 charset - for (char& c : std::string(result, charCount)) { + for (auto c : result) { outString += base64Chars[c]; } - // free memory space - delete[] result; - return outString; } +std::vector key::base64Decode(std::string data) { + // TODO the decoding might not work if the data size is not dividable by 4 + if (data.size() % 4 != 0) std::cerr << "Decoding data size not dividable by 4" << std::endl; + + std::vector result; + + while (!data.empty()) { + // remove 4 chars from the string + std::string letterSegment = data.substr(0, 4); + data.erase(0, 4); + + u_int32_t dataSegment = 0; + + // put 4 chars in one binary string + for (int i = 3; i >= 0; i--) { + // check if there are remaining letters + if (i > letterSegment.length() - 1) continue; + + const uint8_t number = getBase64Index(letterSegment.at(3 - i)); + + // check for valid char code + if (number > 0b111111) { + std::cerr << "trying to Decode not falis char: " << letterSegment.at(i) << std::endl; + continue; + } + dataSegment += number << i * 6; + } + + // read data from binary string + for (int j = 0; j < 3; j++) { + dataSegment <<= 8; + result.push_back((dataSegment & 0xFF << 24) >> 24); + } + } + return result; +} + +uint8_t key::getBase64Index(char letter) { + for (int i = 0; base64Chars[i] != '\0'; i++) { + if (base64Chars[i] == letter) { + return i; + } + } + return 0; +} + void key::createRSAKey() { std::string keyName; diff --git a/src/key.h b/src/key.h index f315277..df2be62 100644 --- a/src/key.h +++ b/src/key.h @@ -20,14 +20,15 @@ class key { static int keyExists(std::string name); static void generatePublicFromPrivate(); static int writeKey(const std::string &name, std::vector data, bool isPublic); - static std::vector base64Decode(std::string data); + + + static uint8_t getBase64Index(char letter); public: + static std::string base64Encode(const std::vector &data); + static std::vector base64Decode(std::string data); static void createRSAKey(); - // TODO - static std::string base64Encode(std::vector data); - static std::pair getPrivateKey(std::string &name); static std::pair getPublicKey(std::string &name); }; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index bfd2a4b..6e45fd8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,5 +54,7 @@ int main(int argc, char* argv[]) { cli::help(); } + std::vector test = key::base64Decode(key::base64Encode({255, 0, 128, 144, 54, 12, 1})); + return 0; } From 0155549a3992739ecbc16afe0c7ca6b3a9acba83 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 9 Mar 2025 19:23:32 +0100 Subject: [PATCH 06/46] implement read key from file, rework dummy create key --- src/key.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++++------ src/key.h | 14 ++++++--- src/main.cpp | 3 +- 3 files changed, 89 insertions(+), 17 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index c5dab74..6109ebb 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -40,7 +40,9 @@ int key::keyExists(std::string name) { return status; } -int key::writeKey(const std::string& name, std::vector data, const bool isPublic) { +int key::writeKey(const std::string& name, std::vector *data, const bool isPublic) { + if (data == nullptr) return -1; + std::filesystem::path keysFolder = keysPath(); std::filesystem::path keyFile = keysFolder / (name + (isPublic? ".pub":"")); @@ -48,7 +50,7 @@ int key::writeKey(const std::string& name, std::vector data, const bool std::ofstream outFile(keyFile); // key in base64 format - std::string base64Data = base64Encode(data); + std::string base64Data = base64Encode(*data); if (outFile.is_open()) { outFile << "-----BEGIN RSA " << (isPublic? "PUBLIC":"PRIVATE") << " KEY-----\n"; @@ -59,9 +61,45 @@ int key::writeKey(const std::string& name, std::vector data, const bool outFile.close(); } else { std::cerr << "Could not write to file: " << keyFile << std::endl; - return 0; + return -1; + } + + return 1; +} + +int key::readKey(const std::string &name, std::vector *data, bool isPublic) { + std::filesystem::path keysFolder = keysPath(); + + std::filesystem::path keyFile = keysFolder / (name + (isPublic? ".pub":"")); + // load file in memory + std::ifstream inFile(keyFile); + + // check if file is loaded correctly + if (!inFile.is_open()) { + std::cerr << "Die Datei konnte nicht geladen werden!" << std::endl; + return -1; + } + + std::string currentLine; + std::string keyString; + + while (getline (inFile, currentLine)) { + + if (currentLine.empty()) continue; + if (currentLine.at(0) == '-') continue; + + keyString += currentLine; } + // remove any line breaks + for (int c = keyString.length() - 1; c >= 0; c--) { + if (keyString.at(c) == '\n') { + keyString.erase(c); + } + } + + *data = base64Decode(keyString); + return 1; } @@ -124,7 +162,7 @@ std::vector key::base64Decode(std::string data) { // check for valid char code if (number > 0b111111) { - std::cerr << "trying to Decode not falis char: " << letterSegment.at(i) << std::endl; + std::cerr << "trying to Decode not valid char: " << letterSegment.at(i) << std::endl; continue; } dataSegment += number << i * 6; @@ -148,6 +186,28 @@ uint8_t key::getBase64Index(char letter) { return 0; } +int key::createKey(std::vector *keyPublic, std::vector *keyPrivate) { + *keyPublic = { + 23, 87, 45, 190, 12, 78, 34, 210, 56, 89, + 123, 67, 90, 150, 32, 76, 54, 200, 11, 99, + 101, 145, 67, 189, 43, 88, 29, 176, 58, 92, + 111, 134, 78, 201, 15, 84, 39, 220, 66, 97, + 105, 142, 71, 185, 49, 81, 27, 170, 53, 95, + 41 + }; + *keyPrivate = { + 34, 78, 123, 56, 89, 210, 45, 190, 12, 87, + 67, 150, 32, 76, 54, 200, 11, 99, 101, 145, + 67, 189, 43, 88, 29, 176, 58, 92, 111, 134, + 78, 201, 15, 84, 39, 220, 66, 97, 105, 142, + 71, 185, 49, 81, 27, 170, 53, 95, 102, 147, + 68, 191, 44, 85, 30, 177, 59, 93, 112, 135, + 79, 202, 16, 85, 40, 221, 67, 98, 23, 87, + 91, 65 + }; + return 1; +} + void key::createRSAKey() { std::string keyName; @@ -168,7 +228,12 @@ void key::createRSAKey() { return; } - if (writeKey(keyName, {0}, true) == 1 && writeKey(keyName, {0}, false) == 1) { + auto* keyPublic = new std::vector(); + auto* keyPrivate = new std::vector(); + + createKey(keyPublic, keyPrivate); + + if (writeKey(keyName, keyPublic, true) == 1 && writeKey(keyName, keyPrivate, false) == 1) { std::cout << keyName + " key successfully created!\n"; std::cout << "You can find your newly created key here: " << keysFolder << std::endl; } else { @@ -176,10 +241,14 @@ void key::createRSAKey() { } } -std::pair getPrivateKey(std::string& name) { - return {647'090'566'899, 234'099'456'876'004}; +std::vector * key::getPrivateKey(std::string &name) { + std::vector* data = new std::vector; + readKey(name, data, false); + return data; } -std::pair getPublicKey(std::string& name) { - return {143'548'453'234, 234'099'456'876'004}; -} \ No newline at end of file +std::vector * key::getPublicKey(std::string &name) { + std::vector* data = new std::vector; + readKey(name, data, true); + return data; +} diff --git a/src/key.h b/src/key.h index df2be62..436d158 100644 --- a/src/key.h +++ b/src/key.h @@ -19,16 +19,20 @@ class key { static std::filesystem::path keysPath(); static int keyExists(std::string name); static void generatePublicFromPrivate(); - static int writeKey(const std::string &name, std::vector data, bool isPublic); + static int writeKey(const std::string &name, std::vector *data, bool isPublic); + static int readKey(const std::string &name, std::vector *data, bool isPublic); + + static std::string base64Encode(const std::vector &data); + static std::vector base64Decode(std::string data); static uint8_t getBase64Index(char letter); + static int createKey(std::vector *keyPublic, std::vector *keyPrivate); + public: - static std::string base64Encode(const std::vector &data); - static std::vector base64Decode(std::string data); static void createRSAKey(); - static std::pair getPrivateKey(std::string &name); - static std::pair getPublicKey(std::string &name); + static std::vector* getPrivateKey(std::string &name); + static std::vector* getPublicKey(std::string &name); }; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 6e45fd8..d5c80c7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,7 +41,7 @@ int main(int argc, char* argv[]) { cli::keyManager::create(); } else if (subFeature == "list") { cli::keyManager::list(); - } else if (subFeature == "print") { + } else if (subFeature == "print" && argv[3] != nullptr) { cli::keyManager::print(argv[3], arguments.publicKey, arguments.privateKey); } @@ -54,7 +54,6 @@ int main(int argc, char* argv[]) { cli::help(); } - std::vector test = key::base64Decode(key::base64Encode({255, 0, 128, 144, 54, 12, 1})); return 0; } From e92bcc7403de5f86183ffadbfc4b079f5077e8c5 Mon Sep 17 00:00:00 2001 From: Jochen <97750753+Jochengehtab@users.noreply.github.com> Date: Mon, 10 Mar 2025 19:22:08 +0100 Subject: [PATCH 07/46] Implement mul function for vec --- src/key.cpp | 2 +- src/main.cpp | 11 +++++++ src/vec/operations.h | 72 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 71 insertions(+), 14 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index 6109ebb..84414a8 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -151,7 +151,7 @@ std::vector key::base64Decode(std::string data) { std::string letterSegment = data.substr(0, 4); data.erase(0, 4); - u_int32_t dataSegment = 0; + uint32_t dataSegment = 0; // put 4 chars in one binary string for (int i = 3; i >= 0; i--) { diff --git a/src/main.cpp b/src/main.cpp index d5c80c7..28f5f5c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,6 +54,17 @@ int main(int argc, char* argv[]) { cli::help(); } + std::vector num1 = convertToVector(55555555); + std::vector num2 = convertToVector(45678); + + std::vector result = mul(num1, num2); + + // This gives out the result as a hex number + for (auto it = result.rbegin(); it != result.rend(); ++it) { + printf("%02X", *it); + } + std::cout << std::endl; + return 0; } diff --git a/src/vec/operations.h b/src/vec/operations.h index ed69c75..b238e85 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -1,13 +1,19 @@ #include + #include + #include -[[nodiscard]] std::vector add(const std::vector& a, const std::vector& b) { +[[nodiscard]] std::vector add( + const std::vector &a, + const std::vector &b) noexcept +{ + // Time complexity O(iterations) // Initialize the result vector to store the sum - std::vector result; + std::vector result; // Get the max iterations based on the largest vector - int iterations = std::max(a.size(), b.size()); + const int iterations = std::max(a.size(), b.size()); // Carry to handle overflow between bytes std::uint16_t carry = 0; @@ -22,14 +28,14 @@ { sum += a[i]; } - + // Only add to sum if we actually have a value in b if (i < b.size()) { sum += b[i]; } - // Calculate the carry for the next byte (overflow beyond 255) + // Calculate the carry which is the overflow beyond 255 carry = sum >> 8; // Clear out everything except the lsb @@ -42,26 +48,27 @@ sum &= 0xFF; // Append the least significant byte of the sum to the result - result.push_back(static_cast(sum)); + result.push_back(static_cast(sum)); } // If we got a carry we append this as well if (carry) { - result.push_back(static_cast(carry)); + result.push_back(static_cast(carry)); } return result; } -[[nodiscard]] std::vector convertToVector(std::uint64_t number) { - - std::vector result; +[[nodiscard]] std::vector convertToVector(std::uint64_t number) noexcept { + + std::vector result; // Loop until the whole number is zero - while (number) { + while (number) + { // We only care for the lsb - result.push_back(static_cast(number & 0xFF)); + result.push_back(static_cast(number & 0xFF)); // Shift the number by 8 to the right number >>= 8; @@ -70,7 +77,46 @@ return result; } -[[nodiscard]] std::vector mul(const std::vector& a, const std::vector& b) { +[[nodiscard]] std::vector mul( + const std::vector &a, + const std::vector &b) noexcept +{ + // Time complexity O(aSize * bSize) + const std::uint64_t aSize = a.size(); + const std::uint64_t bSize = b.size(); + + // Initialize the result vector with zeros, with the size of aSize + bSize + std::vector result(aSize + bSize, 0); + + for (std::uint64_t i = 0; i < aSize; i++) + { + // Set up the carry value for each iteration + std::uint16_t carry = 0; + + for (uint64_t x = 0; x < bSize; x++) + { + // Calculate the product by adding up the previous result, the carry, and the new product + std::uint16_t product = result[i + x] + carry + (a[i] * b[x]); + + // Calculate the carry which is the overflow beyond 255 + carry = product >> 8; + + // Store the least significant byte (lsb) of the product in the result + result[i + x] = static_cast(product & 0xFF); + } + + // If there is a carry, append it to the result + // But with the offset of bSize because of the previous inner loop + result[i + bSize] += static_cast(carry); + } + + return result; +} + +[[nodiscard]] std::vector div( + const std::vector &a, + const std::vector &b) noexcept +{ std::vector result; return result; } From b7541565cbded80ae41be7f066e04c21d4d99ade Mon Sep 17 00:00:00 2001 From: Jochen <97750753+Jochengehtab@users.noreply.github.com> Date: Mon, 10 Mar 2025 19:37:02 +0100 Subject: [PATCH 08/46] format --- src/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 28f5f5c..bd1ce00 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -65,6 +65,5 @@ int main(int argc, char* argv[]) { } std::cout << std::endl; - return 0; } From 31971d7615fe426cb952be7e2aa2fcb0252f2632 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 16 Mar 2025 17:06:24 +0100 Subject: [PATCH 09/46] add header guards --- src/cli.h | 7 ++++++- src/encryption.h | 7 ++++++- src/key.h | 7 ++++++- src/utility.h | 4 ++++ src/vec/operations.h | 7 +++++-- 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/cli.h b/src/cli.h index 1fa9354..9b1ed5b 100644 --- a/src/cli.h +++ b/src/cli.h @@ -1,3 +1,6 @@ +#ifndef CLI_H +#define CLI_H + namespace cli { void help(); @@ -6,4 +9,6 @@ namespace cli { void list(); void print(const std::string& name, bool publicKey, bool privateKey); } -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/src/encryption.h b/src/encryption.h index 00e9feb..d4b13b9 100644 --- a/src/encryption.h +++ b/src/encryption.h @@ -1,3 +1,6 @@ +#ifndef ENCRYPTION_H +#define ENCRYPTION_H + #include #include @@ -6,4 +9,6 @@ class encryption private: public: std::int8_t encrypt(std::uint8_t data, unsigned long int e, unsigned long N); -}; \ No newline at end of file +}; + +#endif \ No newline at end of file diff --git a/src/key.h b/src/key.h index 436d158..abdd808 100644 --- a/src/key.h +++ b/src/key.h @@ -1,3 +1,6 @@ +#ifndef KEY_H +#define KEY_H + #include #include #include @@ -35,4 +38,6 @@ class key { static std::vector* getPrivateKey(std::string &name); static std::vector* getPublicKey(std::string &name); -}; \ No newline at end of file +}; + +#endif \ No newline at end of file diff --git a/src/utility.h b/src/utility.h index 7c835fa..29dd202 100644 --- a/src/utility.h +++ b/src/utility.h @@ -1,3 +1,6 @@ +#ifndef UTILITY_H +#define UTILITY_H + #include class utility @@ -10,3 +13,4 @@ class utility bool checkForPrime(int number); }; +#endif \ No newline at end of file diff --git a/src/vec/operations.h b/src/vec/operations.h index b238e85..327dd70 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -1,7 +1,8 @@ -#include +#ifndef VEC_OPERATIONS_H +#define VEC_OPERATIONS_H +#include #include - #include [[nodiscard]] std::vector add( @@ -120,3 +121,5 @@ std::vector result; return result; } + +#endif From f2dce96d464106efe1dcbc7ab062471d96913c06 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 16 Mar 2025 17:07:44 +0100 Subject: [PATCH 10/46] fix documentation --- src/key.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/key.cpp b/src/key.cpp index 84414a8..44b4b23 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -123,7 +123,7 @@ std::string key::base64Encode(const std::vector &data) { dataSegment += number << i * 8; } - // 4 times, put 6 bits from dataSegment into result array + // 4 times, put 6 bits from dataSegment into result vector for (int j = 0; j < 4; j++) { dataSegment <<= 6; result.push_back(static_cast((dataSegment & 0b00111111 << 24) >> 24)); From 04d08d7762e2c09d5b3d0a862e2e651dbb62a408 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Mon, 17 Mar 2025 22:09:29 +0100 Subject: [PATCH 11/46] implement pow operation --- src/vec/operations.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/vec/operations.h b/src/vec/operations.h index 327dd70..9f19ec2 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -122,4 +122,20 @@ return result; } +[[nodiscard]] std::vector pow( + const std::vector &a, + const uint64_t &pow) noexcept +{ + // copy the value from a into result while keeping a constant + std::vector result; + std::copy(a.begin(), a.end(), std::back_inserter(result)); + + // start the loop at 1, because the first number is already assigned to result + for (int i = 1; i < pow; i++) { + result = mul(result, a); + } + + return result; +} + #endif From 751f2836027e23b8c53617036cf03fb737529fc2 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Mon, 17 Mar 2025 22:10:27 +0100 Subject: [PATCH 12/46] implement zero check for vector based numbers --- src/vec/operations.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/vec/operations.h b/src/vec/operations.h index 9f19ec2..98a51a9 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -5,6 +5,14 @@ #include #include +[[nodiscard]] bool isZero (const std::vector &a) { + for (auto number: a) { + if (number != 0) return false; + } + + return true; +} + [[nodiscard]] std::vector add( const std::vector &a, const std::vector &b) noexcept From f3b6ce6a3efd8eca3d976ee858907e07203c0c5e Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Tue, 18 Mar 2025 07:26:02 +0100 Subject: [PATCH 13/46] create isEqual logic for vector numbers and dummy function for isBigger --- src/vec/operations.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/vec/operations.h b/src/vec/operations.h index 98a51a9..86be253 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -13,6 +13,33 @@ return true; } +[[nodiscard]] bool isEqual ( + const std::vector &a, + const std::vector &b) noexcept +{ + const uint64_t iterations = a.size() > b.size() ? a.size() : b.size(); + // in case both numbers are the same length these variables could point ot the same vector + const std::vector shortest = a.size() < b.size() ? a : b; + const std::vector longest = a.size() > b.size() ? a : b; + + for (uint64_t i = 0; i < iterations; i++) { + if (i >= shortest.size()) { + if (longest[i] != 0) return false; + } else { + if (a[i] != b[i]) return false; + } + } + + return true; +} + +[[nodiscard]] bool isBigger ( + const std::vector &a, + const std::vector &b) noexcept +{ + return true; +} + [[nodiscard]] std::vector add( const std::vector &a, const std::vector &b) noexcept From 4d69b54aa0e201b3cf2843120a4e973dcece2062 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Tue, 18 Mar 2025 13:22:00 +0100 Subject: [PATCH 14/46] implement getStartBitIndex --- src/vec/operations.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/vec/operations.h b/src/vec/operations.h index 86be253..bce36f3 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -5,6 +5,33 @@ #include #include +[[nodiscard]] uint64_t getStartBitIndex (const std::vector &a) { + uint64_t index = 0; + uint64_t bitsSince1 = 0; + + for (auto number: a) { + // skip 8 bits if all zero + if (number == 0) { + bitsSince1 += 8; + continue; + } + // go over every bit in number + for (int i = 0; i < sizeof(uint8_t) * 8; i++) { + // select the current bit using a bitmask + if ((number & 0b1 << i) != 0) { + // increment the index by the bits since the last increment + index += bitsSince1 + 1; + bitsSince1 = 0; + } else { + bitsSince1++; + } + } + } + + // returns position of the first bit needed for the number + return index - 1; +} + [[nodiscard]] bool isZero (const std::vector &a) { for (auto number: a) { if (number != 0) return false; From 8ddf21787854660bab9b166330b4ca1d53b8258b Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Tue, 18 Mar 2025 19:45:14 +0100 Subject: [PATCH 15/46] implement subtract --- src/vec/operations.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/vec/operations.h b/src/vec/operations.h index bce36f3..6a839fd 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -123,6 +123,48 @@ return result; } +// the return value can only be positive, if it would be negative, 0 is returned +[[nodiscard]] std::vector sub( + const std::vector &a, + const std::vector &b) noexcept +{ + // prevent from ending the subtraction before going over the hole subtractor and stop if the result can only be negative + if (getStartBitIndex(b) > getStartBitIndex(a)) return {0}; + + std::vector result; + + // handle an underflow when subtracting + bool borrow = false; + + for (int i = 0; i < a.size(); i++) + { + std::int32_t subtract; + // check for the end of the subtractor + if (i >= b.size()) { + subtract = borrow; + } else { + subtract = borrow + b[i]; + } + borrow = false; + + if (a[i] >= subtract) { + // if the current number is as least as big as subtract + uint8_t number = a[i] - subtract; + result.push_back(number); + } else { + // borrow from the next number + subtract -= 256; + borrow = true; + + // here subtract can only be 0 or negative + uint8_t number = a[i] - subtract; + result.push_back(number); + } + } + + return result; +} + [[nodiscard]] std::vector convertToVector(std::uint64_t number) noexcept { std::vector result; From b19c9fa9b3bd6221f821ab686769dddf886e30e9 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Tue, 18 Mar 2025 21:37:52 +0100 Subject: [PATCH 16/46] move into namespace operations --- src/vec/operations.h | 375 ++++++++++++++++++++++--------------------- 1 file changed, 192 insertions(+), 183 deletions(-) diff --git a/src/vec/operations.h b/src/vec/operations.h index 6a839fd..e2c3093 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -5,241 +5,250 @@ #include #include -[[nodiscard]] uint64_t getStartBitIndex (const std::vector &a) { - uint64_t index = 0; - uint64_t bitsSince1 = 0; - - for (auto number: a) { - // skip 8 bits if all zero - if (number == 0) { - bitsSince1 += 8; - continue; - } - // go over every bit in number - for (int i = 0; i < sizeof(uint8_t) * 8; i++) { - // select the current bit using a bitmask - if ((number & 0b1 << i) != 0) { - // increment the index by the bits since the last increment - index += bitsSince1 + 1; - bitsSince1 = 0; - } else { - bitsSince1++; +namespace operations { + [[nodiscard]] uint64_t getStartBitIndex (const std::vector &a) { + uint64_t index = 0; + uint64_t bitsSince1 = 0; + + for (auto number: a) { + // skip 8 bits if all zero + if (number == 0) { + bitsSince1 += 8; + continue; + } + // go over every bit in number + for (int i = 0; i < sizeof(uint8_t) * 8; i++) { + // select the current bit using a bitmask + if ((number & 0b1 << i) != 0) { + // increment the index by the bits since the last increment + index += bitsSince1 + 1; + bitsSince1 = 0; + } else { + bitsSince1++; + } } } + + // returns position of the first bit needed for the number + return index - 1; } - // returns position of the first bit needed for the number - return index - 1; -} + [[nodiscard]] bool isZero (const std::vector &a) { + for (auto number: a) { + if (number != 0) return false; + } -[[nodiscard]] bool isZero (const std::vector &a) { - for (auto number: a) { - if (number != 0) return false; + return true; } - return true; -} - -[[nodiscard]] bool isEqual ( - const std::vector &a, - const std::vector &b) noexcept -{ - const uint64_t iterations = a.size() > b.size() ? a.size() : b.size(); - // in case both numbers are the same length these variables could point ot the same vector - const std::vector shortest = a.size() < b.size() ? a : b; - const std::vector longest = a.size() > b.size() ? a : b; - - for (uint64_t i = 0; i < iterations; i++) { - if (i >= shortest.size()) { - if (longest[i] != 0) return false; - } else { - if (a[i] != b[i]) return false; + [[nodiscard]] bool isEqual ( + const std::vector &a, + const std::vector &b) noexcept + { + const uint64_t iterations = a.size() > b.size() ? a.size() : b.size(); + // in case both numbers are the same length these variables could point ot the same vector + const std::vector shortest = a.size() < b.size() ? a : b; + const std::vector longest = a.size() > b.size() ? a : b; + + for (uint64_t i = 0; i < iterations; i++) { + if (i >= shortest.size()) { + if (longest[i] != 0) return false; + } else { + if (a[i] != b[i]) return false; + } } + + return true; } - return true; -} + [[nodiscard]] bool isBigger ( + const std::vector &a, + const std::vector &b) noexcept + { + return true; + } -[[nodiscard]] bool isBigger ( - const std::vector &a, - const std::vector &b) noexcept -{ - return true; -} + [[nodiscard]] std::vector add( + const std::vector &a, + const std::vector &b) noexcept + { + // Time complexity O(iterations) + // Initialize the result vector to store the sum + std::vector result; -[[nodiscard]] std::vector add( - const std::vector &a, - const std::vector &b) noexcept -{ - // Time complexity O(iterations) - // Initialize the result vector to store the sum - std::vector result; + // Get the max iterations based on the largest vector + const int iterations = std::max(a.size(), b.size()); - // Get the max iterations based on the largest vector - const int iterations = std::max(a.size(), b.size()); + // Carry to handle overflow between bytes + std::uint16_t carry = 0; - // Carry to handle overflow between bytes - std::uint16_t carry = 0; + for (int i = 0; i < iterations; i++) + { + // Set up a holder for the sum + std::uint16_t sum = carry; - for (int i = 0; i < iterations; i++) - { - // Set up a holder for the sum - std::uint16_t sum = carry; + // Only add to sum if we actually have a value in a + if (i < a.size()) + { + sum += a[i]; + } - // Only add to sum if we actually have a value in a - if (i < a.size()) - { - sum += a[i]; + // Only add to sum if we actually have a value in b + if (i < b.size()) + { + sum += b[i]; + } + + // Calculate the carry which is the overflow beyond 255 + carry = sum >> 8; + + // Clear out everything except the lsb + // This is done by masking the sum with 255 + // For example + // 0000000101111111 (=383) + // 0000000011111111 (=255) + // ---------------- + // 0000000100000000 + sum &= 0xFF; + + // Append the least significant byte of the sum to the result + result.push_back(static_cast(sum)); } - // Only add to sum if we actually have a value in b - if (i < b.size()) + // If we got a carry we append this as well + if (carry) { - sum += b[i]; + result.push_back(static_cast(carry)); } - // Calculate the carry which is the overflow beyond 255 - carry = sum >> 8; - - // Clear out everything except the lsb - // This is done by masking the sum with 255 - // For example - // 0000000101111111 (=383) - // 0000000011111111 (=255) - // ---------------- - // 0000000100000000 - sum &= 0xFF; - - // Append the least significant byte of the sum to the result - result.push_back(static_cast(sum)); + return result; } - // If we got a carry we append this as well - if (carry) + // the return value can only be positive, if it would be negative, 0 is returned + [[nodiscard]] std::vector sub( + const std::vector &a, + const std::vector &b) noexcept { - result.push_back(static_cast(carry)); - } + // prevent from ending the subtraction before going over the hole subtractor and stop if the result can only be negative + if (getStartBitIndex(b) > getStartBitIndex(a)) return {0}; - return result; -} + std::vector result; -// the return value can only be positive, if it would be negative, 0 is returned -[[nodiscard]] std::vector sub( - const std::vector &a, - const std::vector &b) noexcept -{ - // prevent from ending the subtraction before going over the hole subtractor and stop if the result can only be negative - if (getStartBitIndex(b) > getStartBitIndex(a)) return {0}; + // handle an underflow when subtracting + bool borrow = false; - std::vector result; + for (int i = 0; i < a.size(); i++) + { + std::int32_t subtract; + // check for the end of the subtractor + if (i >= b.size()) { + subtract = borrow; + } else { + subtract = borrow + b[i]; + } + borrow = false; - // handle an underflow when subtracting - bool borrow = false; + if (a[i] >= subtract) { + // if the current number is as least as big as subtract + uint8_t number = a[i] - subtract; + result.push_back(number); + } else { + // borrow from the next number + subtract -= 256; + borrow = true; - for (int i = 0; i < a.size(); i++) - { - std::int32_t subtract; - // check for the end of the subtractor - if (i >= b.size()) { - subtract = borrow; - } else { - subtract = borrow + b[i]; - } - borrow = false; - - if (a[i] >= subtract) { - // if the current number is as least as big as subtract - uint8_t number = a[i] - subtract; - result.push_back(number); - } else { - // borrow from the next number - subtract -= 256; - borrow = true; - - // here subtract can only be 0 or negative - uint8_t number = a[i] - subtract; - result.push_back(number); + // here subtract can only be 0 or negative + uint8_t number = a[i] - subtract; + result.push_back(number); + } } + + return result; } - return result; -} + [[nodiscard]] std::vector convertToVector(std::uint64_t number) noexcept { -[[nodiscard]] std::vector convertToVector(std::uint64_t number) noexcept { + std::vector result; - std::vector result; + // Loop until the whole number is zero + while (number) + { + // We only care for the lsb + result.push_back(static_cast(number & 0xFF)); - // Loop until the whole number is zero - while (number) - { - // We only care for the lsb - result.push_back(static_cast(number & 0xFF)); + // Shift the number by 8 to the right + number >>= 8; + } - // Shift the number by 8 to the right - number >>= 8; + return result; } - return result; -} + [[nodiscard]] std::vector mul( + const std::vector &a, + const std::vector &b) noexcept + { + // Time complexity O(aSize * bSize) + const std::uint64_t aSize = a.size(); + const std::uint64_t bSize = b.size(); -[[nodiscard]] std::vector mul( - const std::vector &a, - const std::vector &b) noexcept -{ - // Time complexity O(aSize * bSize) - const std::uint64_t aSize = a.size(); - const std::uint64_t bSize = b.size(); + // Initialize the result vector with zeros, with the size of aSize + bSize + std::vector result(aSize + bSize, 0); - // Initialize the result vector with zeros, with the size of aSize + bSize - std::vector result(aSize + bSize, 0); + for (std::uint64_t i = 0; i < aSize; i++) + { + // Set up the carry value for each iteration + std::uint16_t carry = 0; - for (std::uint64_t i = 0; i < aSize; i++) - { - // Set up the carry value for each iteration - std::uint16_t carry = 0; + for (uint64_t x = 0; x < bSize; x++) + { + // Calculate the product by adding up the previous result, the carry, and the new product + std::uint16_t product = result[i + x] + carry + (a[i] * b[x]); - for (uint64_t x = 0; x < bSize; x++) - { - // Calculate the product by adding up the previous result, the carry, and the new product - std::uint16_t product = result[i + x] + carry + (a[i] * b[x]); + // Calculate the carry which is the overflow beyond 255 + carry = product >> 8; - // Calculate the carry which is the overflow beyond 255 - carry = product >> 8; + // Store the least significant byte (lsb) of the product in the result + result[i + x] = static_cast(product & 0xFF); + } - // Store the least significant byte (lsb) of the product in the result - result[i + x] = static_cast(product & 0xFF); + // If there is a carry, append it to the result + // But with the offset of bSize because of the previous inner loop + result[i + bSize] += static_cast(carry); } - // If there is a carry, append it to the result - // But with the offset of bSize because of the previous inner loop - result[i + bSize] += static_cast(carry); + return result; } - return result; -} + // a is divided by b + [[nodiscard]] std::vector div( + const std::vector &a, + const std::vector &b) noexcept + { + const std::vector dividend = a; + std::vector result; -[[nodiscard]] std::vector div( - const std::vector &a, - const std::vector &b) noexcept -{ - std::vector result; - return result; -} + while (!isZero(dividend)) { -[[nodiscard]] std::vector pow( - const std::vector &a, - const uint64_t &pow) noexcept -{ - // copy the value from a into result while keeping a constant - std::vector result; - std::copy(a.begin(), a.end(), std::back_inserter(result)); - - // start the loop at 1, because the first number is already assigned to result - for (int i = 1; i < pow; i++) { - result = mul(result, a); + } + + return result; } - return result; + [[nodiscard]] std::vector pow( + const std::vector &a, + const uint64_t &pow) noexcept + { + // copy the value from a into result while keeping a constant + std::vector result; + std::copy(a.begin(), a.end(), std::back_inserter(result)); + + // start the loop at 1, because the first number is already assigned to result + for (int i = 1; i < pow; i++) { + result = mul(result, a); + } + + return result; + } } #endif From 7b100a35c8c7fd25c55bfb3010566b23fae8d85a Mon Sep 17 00:00:00 2001 From: Jochen <97750753+Jochengehtab@users.noreply.github.com> Date: Tue, 18 Mar 2025 21:43:14 +0100 Subject: [PATCH 17/46] fix doc --- src/vec/operations.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/vec/operations.h b/src/vec/operations.h index e2c3093..3110ec3 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -11,16 +11,16 @@ namespace operations { uint64_t bitsSince1 = 0; for (auto number: a) { - // skip 8 bits if all zero + // Skip 8 bits if all zero if (number == 0) { bitsSince1 += 8; continue; } - // go over every bit in number + // Go over every bit in number for (int i = 0; i < sizeof(uint8_t) * 8; i++) { - // select the current bit using a bitmask + // Select the current bit using a bitmask if ((number & 0b1 << i) != 0) { - // increment the index by the bits since the last increment + // Increment the index by the bits since the last increment index += bitsSince1 + 1; bitsSince1 = 0; } else { @@ -29,7 +29,7 @@ namespace operations { } } - // returns position of the first bit needed for the number + // Returns position of the first bit needed for the number return index - 1; } @@ -46,7 +46,7 @@ namespace operations { const std::vector &b) noexcept { const uint64_t iterations = a.size() > b.size() ? a.size() : b.size(); - // in case both numbers are the same length these variables could point ot the same vector + // In case both numbers are the same length these variables could point ot the same vector const std::vector shortest = a.size() < b.size() ? a : b; const std::vector longest = a.size() > b.size() ? a : b; @@ -124,23 +124,23 @@ namespace operations { return result; } - // the return value can only be positive, if it would be negative, 0 is returned + // The return value can only be positive, if it would be negative, 0 is returned [[nodiscard]] std::vector sub( const std::vector &a, const std::vector &b) noexcept { - // prevent from ending the subtraction before going over the hole subtractor and stop if the result can only be negative + // Prevent from ending the subtraction before going over the hole subtractor and stop if the result can only be negative if (getStartBitIndex(b) > getStartBitIndex(a)) return {0}; std::vector result; - // handle an underflow when subtracting + // Handle an underflow when subtracting bool borrow = false; for (int i = 0; i < a.size(); i++) { std::int32_t subtract; - // check for the end of the subtractor + // Check for the end of the subtractor if (i >= b.size()) { subtract = borrow; } else { @@ -149,15 +149,15 @@ namespace operations { borrow = false; if (a[i] >= subtract) { - // if the current number is as least as big as subtract + // If the current number is as least as big as subtract uint8_t number = a[i] - subtract; result.push_back(number); } else { - // borrow from the next number + // Borrow from the next number subtract -= 256; borrow = true; - // here subtract can only be 0 or negative + // Here subtract can only be 0 or negative uint8_t number = a[i] - subtract; result.push_back(number); } @@ -238,11 +238,11 @@ namespace operations { const std::vector &a, const uint64_t &pow) noexcept { - // copy the value from a into result while keeping a constant + // Copy the value from a into result while keeping a constant std::vector result; std::copy(a.begin(), a.end(), std::back_inserter(result)); - // start the loop at 1, because the first number is already assigned to result + // Start the loop at 1, because the first number is already assigned to result for (int i = 1; i < pow; i++) { result = mul(result, a); } From 073c1febc012f99937a49dd9b698d7ed7f3c0191 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Fri, 7 Mar 2025 18:50:50 +0100 Subject: [PATCH 18/46] fix cmake project not including key class --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d76f4b3..a6aff9b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,7 @@ add_executable(RSA-Encryptor main.cpp utility.cpp - keys.cpp + key.cpp encryption.cpp cli.cpp ) From e3a616c277131eb810a7dd5108b9790dbb147232 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 9 Mar 2025 14:26:45 +0100 Subject: [PATCH 19/46] remove old files --- src/keys.cpp | 30 ------------------------------ src/keys.h | 13 ------------- 2 files changed, 43 deletions(-) delete mode 100644 src/keys.cpp delete mode 100644 src/keys.h diff --git a/src/keys.cpp b/src/keys.cpp deleted file mode 100644 index a8a51e2..0000000 --- a/src/keys.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include "keys.h" - - -void keys::createRSAKey() { - std::string keyName; - - std::cout << "Enter the name of the key: "; - std::cin >> keyName; - - // Navigate to the root directory of the project - std::filesystem::path programRootPath = std::filesystem::current_path().parent_path(); - std::filesystem::path keysFolder = programRootPath / KEY_FOLDER; - - // Check if keys folder exists - if (!std::filesystem::exists(keysFolder)) { - // Create the "RSA-Keys" directory in the root folder fo the program - std::filesystem::create_directory(keysFolder); - } - - std::cout << "You can find your newly created key here: " << keysFolder << std::endl; -} - -std::pair getPrivateKey(std::string& name) { - return {647'090'566'899, 234'099'456'876'004}; -} - -std::pair getPublicKey(std::string& name) { - return {143'548'453'234, 234'099'456'876'004}; -} \ No newline at end of file diff --git a/src/keys.h b/src/keys.h deleted file mode 100644 index 670fc4d..0000000 --- a/src/keys.h +++ /dev/null @@ -1,13 +0,0 @@ -#include - -#define KEY_FOLDER "rsa-keys" - - -class keys { - -public: - static void createRSAKey(); - - std::pair getPrivateKey(std::string& name); - std::pair getPublicKey(std::string& name); -}; \ No newline at end of file From 2fa26bcc270c84ef7ead1ff94bd3c4c991769d02 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 9 Mar 2025 15:07:06 +0100 Subject: [PATCH 20/46] refactor namespace key inside namespace cli into keyManager --- src/cli.cpp | 10 +++++----- src/cli.h | 2 +- src/main.cpp | 24 ++++-------------------- 3 files changed, 10 insertions(+), 26 deletions(-) diff --git a/src/cli.cpp b/src/cli.cpp index 7ece695..750ab30 100644 --- a/src/cli.cpp +++ b/src/cli.cpp @@ -1,18 +1,18 @@ #include #include "cli.h" -#include "keys.h" +#include "key.h" void cli::help() { std::cout << "Welcome to RSA-Encryptor" << std::endl; } -void cli::key::create() { - keys::createRSAKey(); +void cli::keyManager::create() { + key::createRSAKey(); } -void cli::key::list() { +void cli::keyManager::list() { } -void cli::key::print(const std::string& name, bool publicKey, bool privateKey) { +void cli::keyManager::print(const std::string& name, bool publicKey, bool privateKey) { } diff --git a/src/cli.h b/src/cli.h index 972d471..1fa9354 100644 --- a/src/cli.h +++ b/src/cli.h @@ -1,7 +1,7 @@ namespace cli { void help(); - namespace key { + namespace keyManager { void create(); void list(); void print(const std::string& name, bool publicKey, bool privateKey); diff --git a/src/main.cpp b/src/main.cpp index 07b69a1..bfd2a4b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include "utility.h" #include "cli.h" +#include "key.h" #include "vec/operations.h" int main(int argc, char* argv[]) { @@ -31,19 +32,17 @@ int main(int argc, char* argv[]) { } } - std::cout << arguments.publicKey << std::endl; - std::string feature = argv[1]; if (feature == "key" && argv[2] != nullptr) { std::string subFeature = argv[2]; if (subFeature == "create") { - cli::key::create(); + cli::keyManager::create(); } else if (subFeature == "list") { - cli::key::list(); + cli::keyManager::list(); } else if (subFeature == "print") { - cli::key::print(argv[3], arguments.publicKey, arguments.privateKey); + cli::keyManager::print(argv[3], arguments.publicKey, arguments.privateKey); } } else if (feature == "help") { @@ -55,20 +54,5 @@ int main(int argc, char* argv[]) { cli::help(); } - // std::cout << util.checkForPrime(54557) << std::endl; - // std::cout << util.checkForPrime(29) << std::endl; - //std::vector num1 = {255, 255, 255}; // 16777215 in dezimal - //std::vector num2 = {0x01}; // Add one - - std::vector num1 = convertToVector(16777215); // 16777215 in dezimal - std::vector num2 = convertToVector(1); // Add one - - std::vector result = add(num1, num2); - - // This gives out the result as a hex number - for (auto it = result.rbegin(); it != result.rend(); ++it) { - printf("%02X", *it); - } - std::cout << std::endl; return 0; } From bc90619d257c9130cc5c427d254286e033572a8b Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 9 Mar 2025 15:07:30 +0100 Subject: [PATCH 21/46] add base64Encode functionality --- src/key.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++------- src/key.h | 11 +++++++++-- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index 237d242..05725ca 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -12,6 +12,7 @@ std::filesystem::path key::keysPath() { } int key::keyExists(std::string name) { + // TODO fix function not case sensitive /* 0: key doesn't exist * 1: only publicKey exists * 2: only privateKey exists @@ -39,16 +40,21 @@ int key::keyExists(std::string name) { return status; } -int key::writeKey(const std::string& name, const unsigned long int data, const bool isPublic) { +int key::writeKey(const std::string& name, std::vector data, const bool isPublic) { std::filesystem::path keysFolder = keysPath(); std::filesystem::path keyFile = keysFolder / (name + (isPublic? ".pub":"")); + // load file in memory std::ofstream outFile(keyFile); + // key in base64 format + std::string base64Data = base64Encode(data); + if (outFile.is_open()) { - std::string dataStr = std::to_string(data); outFile << "-----BEGIN RSA " << (isPublic? "PUBLIC":"PRIVATE") << " KEY-----\n"; - outFile << base64_encode(dataStr) << "\n"; + for (int i = 0; i < base64Data.size(); i += 64) { + outFile << base64Data.substr(i, 64) << "\n"; + } outFile << "-----END RSA " << (isPublic? "PUBLIC":"PRIVATE") << " KEY-----\n"; outFile.close(); } else { @@ -59,9 +65,43 @@ int key::writeKey(const std::string& name, const unsigned long int data, const b return 1; } -std::string key::base64_encode(std::string &data) { - //TODO Add base 64 encode function - return data; +std::string key::base64Encode(std::vector data) { + + const unsigned int charCount = data.size() * 1.5; + char* result = new char[charCount]; + unsigned int resultIndex = charCount - 1; + + while (!data.empty()) { + + uint32_t dataSegment = 0; + + // pop 3 numbers from the data vector and store it as one block in dataSegment + for (int i = 0; i < 3; i++) { + if (data.size() < 1) break; + uint8_t number = data.back(); + data.pop_back(); + dataSegment += number << i * 8; + } + + // 4 times, put 6 bits from dataSegment into result array + for (int j = 0; j < 4; j++) { + if (resultIndex < 1) break; + result[resultIndex--] = static_cast(dataSegment & 0b00111111); + dataSegment >>= 6; + } + } + + std::string outString; + + // convert the numeric value to the corresponding char of the base64 charset + for (char& c : std::string(result, charCount)) { + outString += base64Chars[c]; + } + + // free memory space + delete[] result; + + return outString; } void key::createRSAKey() { @@ -84,7 +124,7 @@ void key::createRSAKey() { return; } - if (writeKey(keyName, 0, true) == 1 && writeKey(keyName, 0, false) == 1) { + if (writeKey(keyName, {0}, true) == 1 && writeKey(keyName, {0}, false) == 1) { std::cout << keyName + " key successfully created!\n"; std::cout << "You can find your newly created key here: " << keysFolder << std::endl; } else { diff --git a/src/key.h b/src/key.h index 823741a..f315277 100644 --- a/src/key.h +++ b/src/key.h @@ -1,5 +1,7 @@ #include #include +#include +#include #define KEY_FOLDER "rsa-keys" @@ -10,17 +12,22 @@ enum { BOTH }; +const char base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + class key { private: static std::filesystem::path keysPath(); static int keyExists(std::string name); static void generatePublicFromPrivate(); - static int writeKey(const std::string &name, unsigned long int data, bool isPublic); - static std::string base64_encode(std::string &data); + static int writeKey(const std::string &name, std::vector data, bool isPublic); + static std::vector base64Decode(std::string data); public: static void createRSAKey(); + // TODO + static std::string base64Encode(std::vector data); + static std::pair getPrivateKey(std::string &name); static std::pair getPublicKey(std::string &name); }; \ No newline at end of file From 83bbecfdbc6c299f9a1deba01e85718865999cf9 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 9 Mar 2025 18:22:53 +0100 Subject: [PATCH 22/46] add base64 Decode logic --- src/key.cpp | 78 ++++++++++++++++++++++++++++++++++++++++------------ src/key.h | 9 +++--- src/main.cpp | 2 ++ 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index 05725ca..c5dab74 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -65,45 +65,89 @@ int key::writeKey(const std::string& name, std::vector data, const bool return 1; } -std::string key::base64Encode(std::vector data) { +std::string key::base64Encode(const std::vector &data) { + // TODO the encoding might not work if the data size is not dividable by 3 + if (data.size() % 3 != 0) std::cerr << "Encoding data size not dividable by 3" << std::endl; - const unsigned int charCount = data.size() * 1.5; - char* result = new char[charCount]; - unsigned int resultIndex = charCount - 1; + std::vector result; + int index = 0; - while (!data.empty()) { + while (index < data.size()) { uint32_t dataSegment = 0; - // pop 3 numbers from the data vector and store it as one block in dataSegment - for (int i = 0; i < 3; i++) { - if (data.size() < 1) break; - uint8_t number = data.back(); - data.pop_back(); + // take 3 numbers from the vector + for (int i = 2; i >= 0; i--) { + // prevent from reading outside the vector + if (index > data.size() - 1) break; + + uint8_t number = data.at(index++); dataSegment += number << i * 8; } // 4 times, put 6 bits from dataSegment into result array for (int j = 0; j < 4; j++) { - if (resultIndex < 1) break; - result[resultIndex--] = static_cast(dataSegment & 0b00111111); - dataSegment >>= 6; + dataSegment <<= 6; + result.push_back(static_cast((dataSegment & 0b00111111 << 24) >> 24)); } } std::string outString; // convert the numeric value to the corresponding char of the base64 charset - for (char& c : std::string(result, charCount)) { + for (auto c : result) { outString += base64Chars[c]; } - // free memory space - delete[] result; - return outString; } +std::vector key::base64Decode(std::string data) { + // TODO the decoding might not work if the data size is not dividable by 4 + if (data.size() % 4 != 0) std::cerr << "Decoding data size not dividable by 4" << std::endl; + + std::vector result; + + while (!data.empty()) { + // remove 4 chars from the string + std::string letterSegment = data.substr(0, 4); + data.erase(0, 4); + + u_int32_t dataSegment = 0; + + // put 4 chars in one binary string + for (int i = 3; i >= 0; i--) { + // check if there are remaining letters + if (i > letterSegment.length() - 1) continue; + + const uint8_t number = getBase64Index(letterSegment.at(3 - i)); + + // check for valid char code + if (number > 0b111111) { + std::cerr << "trying to Decode not falis char: " << letterSegment.at(i) << std::endl; + continue; + } + dataSegment += number << i * 6; + } + + // read data from binary string + for (int j = 0; j < 3; j++) { + dataSegment <<= 8; + result.push_back((dataSegment & 0xFF << 24) >> 24); + } + } + return result; +} + +uint8_t key::getBase64Index(char letter) { + for (int i = 0; base64Chars[i] != '\0'; i++) { + if (base64Chars[i] == letter) { + return i; + } + } + return 0; +} + void key::createRSAKey() { std::string keyName; diff --git a/src/key.h b/src/key.h index f315277..df2be62 100644 --- a/src/key.h +++ b/src/key.h @@ -20,14 +20,15 @@ class key { static int keyExists(std::string name); static void generatePublicFromPrivate(); static int writeKey(const std::string &name, std::vector data, bool isPublic); - static std::vector base64Decode(std::string data); + + + static uint8_t getBase64Index(char letter); public: + static std::string base64Encode(const std::vector &data); + static std::vector base64Decode(std::string data); static void createRSAKey(); - // TODO - static std::string base64Encode(std::vector data); - static std::pair getPrivateKey(std::string &name); static std::pair getPublicKey(std::string &name); }; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index bfd2a4b..6e45fd8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,5 +54,7 @@ int main(int argc, char* argv[]) { cli::help(); } + std::vector test = key::base64Decode(key::base64Encode({255, 0, 128, 144, 54, 12, 1})); + return 0; } From 54fd87c450d26a473724d786058d1c33bf0173df Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 9 Mar 2025 19:23:32 +0100 Subject: [PATCH 23/46] implement read key from file, rework dummy create key --- src/key.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++++------ src/key.h | 14 ++++++--- src/main.cpp | 3 +- 3 files changed, 89 insertions(+), 17 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index c5dab74..6109ebb 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -40,7 +40,9 @@ int key::keyExists(std::string name) { return status; } -int key::writeKey(const std::string& name, std::vector data, const bool isPublic) { +int key::writeKey(const std::string& name, std::vector *data, const bool isPublic) { + if (data == nullptr) return -1; + std::filesystem::path keysFolder = keysPath(); std::filesystem::path keyFile = keysFolder / (name + (isPublic? ".pub":"")); @@ -48,7 +50,7 @@ int key::writeKey(const std::string& name, std::vector data, const bool std::ofstream outFile(keyFile); // key in base64 format - std::string base64Data = base64Encode(data); + std::string base64Data = base64Encode(*data); if (outFile.is_open()) { outFile << "-----BEGIN RSA " << (isPublic? "PUBLIC":"PRIVATE") << " KEY-----\n"; @@ -59,9 +61,45 @@ int key::writeKey(const std::string& name, std::vector data, const bool outFile.close(); } else { std::cerr << "Could not write to file: " << keyFile << std::endl; - return 0; + return -1; + } + + return 1; +} + +int key::readKey(const std::string &name, std::vector *data, bool isPublic) { + std::filesystem::path keysFolder = keysPath(); + + std::filesystem::path keyFile = keysFolder / (name + (isPublic? ".pub":"")); + // load file in memory + std::ifstream inFile(keyFile); + + // check if file is loaded correctly + if (!inFile.is_open()) { + std::cerr << "Die Datei konnte nicht geladen werden!" << std::endl; + return -1; + } + + std::string currentLine; + std::string keyString; + + while (getline (inFile, currentLine)) { + + if (currentLine.empty()) continue; + if (currentLine.at(0) == '-') continue; + + keyString += currentLine; } + // remove any line breaks + for (int c = keyString.length() - 1; c >= 0; c--) { + if (keyString.at(c) == '\n') { + keyString.erase(c); + } + } + + *data = base64Decode(keyString); + return 1; } @@ -124,7 +162,7 @@ std::vector key::base64Decode(std::string data) { // check for valid char code if (number > 0b111111) { - std::cerr << "trying to Decode not falis char: " << letterSegment.at(i) << std::endl; + std::cerr << "trying to Decode not valid char: " << letterSegment.at(i) << std::endl; continue; } dataSegment += number << i * 6; @@ -148,6 +186,28 @@ uint8_t key::getBase64Index(char letter) { return 0; } +int key::createKey(std::vector *keyPublic, std::vector *keyPrivate) { + *keyPublic = { + 23, 87, 45, 190, 12, 78, 34, 210, 56, 89, + 123, 67, 90, 150, 32, 76, 54, 200, 11, 99, + 101, 145, 67, 189, 43, 88, 29, 176, 58, 92, + 111, 134, 78, 201, 15, 84, 39, 220, 66, 97, + 105, 142, 71, 185, 49, 81, 27, 170, 53, 95, + 41 + }; + *keyPrivate = { + 34, 78, 123, 56, 89, 210, 45, 190, 12, 87, + 67, 150, 32, 76, 54, 200, 11, 99, 101, 145, + 67, 189, 43, 88, 29, 176, 58, 92, 111, 134, + 78, 201, 15, 84, 39, 220, 66, 97, 105, 142, + 71, 185, 49, 81, 27, 170, 53, 95, 102, 147, + 68, 191, 44, 85, 30, 177, 59, 93, 112, 135, + 79, 202, 16, 85, 40, 221, 67, 98, 23, 87, + 91, 65 + }; + return 1; +} + void key::createRSAKey() { std::string keyName; @@ -168,7 +228,12 @@ void key::createRSAKey() { return; } - if (writeKey(keyName, {0}, true) == 1 && writeKey(keyName, {0}, false) == 1) { + auto* keyPublic = new std::vector(); + auto* keyPrivate = new std::vector(); + + createKey(keyPublic, keyPrivate); + + if (writeKey(keyName, keyPublic, true) == 1 && writeKey(keyName, keyPrivate, false) == 1) { std::cout << keyName + " key successfully created!\n"; std::cout << "You can find your newly created key here: " << keysFolder << std::endl; } else { @@ -176,10 +241,14 @@ void key::createRSAKey() { } } -std::pair getPrivateKey(std::string& name) { - return {647'090'566'899, 234'099'456'876'004}; +std::vector * key::getPrivateKey(std::string &name) { + std::vector* data = new std::vector; + readKey(name, data, false); + return data; } -std::pair getPublicKey(std::string& name) { - return {143'548'453'234, 234'099'456'876'004}; -} \ No newline at end of file +std::vector * key::getPublicKey(std::string &name) { + std::vector* data = new std::vector; + readKey(name, data, true); + return data; +} diff --git a/src/key.h b/src/key.h index df2be62..436d158 100644 --- a/src/key.h +++ b/src/key.h @@ -19,16 +19,20 @@ class key { static std::filesystem::path keysPath(); static int keyExists(std::string name); static void generatePublicFromPrivate(); - static int writeKey(const std::string &name, std::vector data, bool isPublic); + static int writeKey(const std::string &name, std::vector *data, bool isPublic); + static int readKey(const std::string &name, std::vector *data, bool isPublic); + + static std::string base64Encode(const std::vector &data); + static std::vector base64Decode(std::string data); static uint8_t getBase64Index(char letter); + static int createKey(std::vector *keyPublic, std::vector *keyPrivate); + public: - static std::string base64Encode(const std::vector &data); - static std::vector base64Decode(std::string data); static void createRSAKey(); - static std::pair getPrivateKey(std::string &name); - static std::pair getPublicKey(std::string &name); + static std::vector* getPrivateKey(std::string &name); + static std::vector* getPublicKey(std::string &name); }; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 6e45fd8..d5c80c7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,7 +41,7 @@ int main(int argc, char* argv[]) { cli::keyManager::create(); } else if (subFeature == "list") { cli::keyManager::list(); - } else if (subFeature == "print") { + } else if (subFeature == "print" && argv[3] != nullptr) { cli::keyManager::print(argv[3], arguments.publicKey, arguments.privateKey); } @@ -54,7 +54,6 @@ int main(int argc, char* argv[]) { cli::help(); } - std::vector test = key::base64Decode(key::base64Encode({255, 0, 128, 144, 54, 12, 1})); return 0; } From bf0f46866770ae19bf5954ba92af012e48cbba93 Mon Sep 17 00:00:00 2001 From: Jochen <97750753+Jochengehtab@users.noreply.github.com> Date: Mon, 10 Mar 2025 19:22:08 +0100 Subject: [PATCH 24/46] Implement mul function for vec --- src/key.cpp | 2 +- src/main.cpp | 11 +++++++ src/vec/operations.h | 72 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 71 insertions(+), 14 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index 6109ebb..84414a8 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -151,7 +151,7 @@ std::vector key::base64Decode(std::string data) { std::string letterSegment = data.substr(0, 4); data.erase(0, 4); - u_int32_t dataSegment = 0; + uint32_t dataSegment = 0; // put 4 chars in one binary string for (int i = 3; i >= 0; i--) { diff --git a/src/main.cpp b/src/main.cpp index d5c80c7..28f5f5c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,6 +54,17 @@ int main(int argc, char* argv[]) { cli::help(); } + std::vector num1 = convertToVector(55555555); + std::vector num2 = convertToVector(45678); + + std::vector result = mul(num1, num2); + + // This gives out the result as a hex number + for (auto it = result.rbegin(); it != result.rend(); ++it) { + printf("%02X", *it); + } + std::cout << std::endl; + return 0; } diff --git a/src/vec/operations.h b/src/vec/operations.h index ed69c75..b238e85 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -1,13 +1,19 @@ #include + #include + #include -[[nodiscard]] std::vector add(const std::vector& a, const std::vector& b) { +[[nodiscard]] std::vector add( + const std::vector &a, + const std::vector &b) noexcept +{ + // Time complexity O(iterations) // Initialize the result vector to store the sum - std::vector result; + std::vector result; // Get the max iterations based on the largest vector - int iterations = std::max(a.size(), b.size()); + const int iterations = std::max(a.size(), b.size()); // Carry to handle overflow between bytes std::uint16_t carry = 0; @@ -22,14 +28,14 @@ { sum += a[i]; } - + // Only add to sum if we actually have a value in b if (i < b.size()) { sum += b[i]; } - // Calculate the carry for the next byte (overflow beyond 255) + // Calculate the carry which is the overflow beyond 255 carry = sum >> 8; // Clear out everything except the lsb @@ -42,26 +48,27 @@ sum &= 0xFF; // Append the least significant byte of the sum to the result - result.push_back(static_cast(sum)); + result.push_back(static_cast(sum)); } // If we got a carry we append this as well if (carry) { - result.push_back(static_cast(carry)); + result.push_back(static_cast(carry)); } return result; } -[[nodiscard]] std::vector convertToVector(std::uint64_t number) { - - std::vector result; +[[nodiscard]] std::vector convertToVector(std::uint64_t number) noexcept { + + std::vector result; // Loop until the whole number is zero - while (number) { + while (number) + { // We only care for the lsb - result.push_back(static_cast(number & 0xFF)); + result.push_back(static_cast(number & 0xFF)); // Shift the number by 8 to the right number >>= 8; @@ -70,7 +77,46 @@ return result; } -[[nodiscard]] std::vector mul(const std::vector& a, const std::vector& b) { +[[nodiscard]] std::vector mul( + const std::vector &a, + const std::vector &b) noexcept +{ + // Time complexity O(aSize * bSize) + const std::uint64_t aSize = a.size(); + const std::uint64_t bSize = b.size(); + + // Initialize the result vector with zeros, with the size of aSize + bSize + std::vector result(aSize + bSize, 0); + + for (std::uint64_t i = 0; i < aSize; i++) + { + // Set up the carry value for each iteration + std::uint16_t carry = 0; + + for (uint64_t x = 0; x < bSize; x++) + { + // Calculate the product by adding up the previous result, the carry, and the new product + std::uint16_t product = result[i + x] + carry + (a[i] * b[x]); + + // Calculate the carry which is the overflow beyond 255 + carry = product >> 8; + + // Store the least significant byte (lsb) of the product in the result + result[i + x] = static_cast(product & 0xFF); + } + + // If there is a carry, append it to the result + // But with the offset of bSize because of the previous inner loop + result[i + bSize] += static_cast(carry); + } + + return result; +} + +[[nodiscard]] std::vector div( + const std::vector &a, + const std::vector &b) noexcept +{ std::vector result; return result; } From 6ce67d39f96af196e594c550f16b942044cb1c05 Mon Sep 17 00:00:00 2001 From: Jochen <97750753+Jochengehtab@users.noreply.github.com> Date: Mon, 10 Mar 2025 19:37:02 +0100 Subject: [PATCH 25/46] format --- src/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 28f5f5c..bd1ce00 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -65,6 +65,5 @@ int main(int argc, char* argv[]) { } std::cout << std::endl; - return 0; } From 5db949a2683fb1cf96af5c85a2829477b4ceee63 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 16 Mar 2025 17:06:24 +0100 Subject: [PATCH 26/46] add header guards --- src/cli.h | 7 ++++++- src/encryption.h | 7 ++++++- src/key.h | 7 ++++++- src/utility.h | 4 ++++ src/vec/operations.h | 7 +++++-- 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/cli.h b/src/cli.h index 1fa9354..9b1ed5b 100644 --- a/src/cli.h +++ b/src/cli.h @@ -1,3 +1,6 @@ +#ifndef CLI_H +#define CLI_H + namespace cli { void help(); @@ -6,4 +9,6 @@ namespace cli { void list(); void print(const std::string& name, bool publicKey, bool privateKey); } -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/src/encryption.h b/src/encryption.h index 00e9feb..d4b13b9 100644 --- a/src/encryption.h +++ b/src/encryption.h @@ -1,3 +1,6 @@ +#ifndef ENCRYPTION_H +#define ENCRYPTION_H + #include #include @@ -6,4 +9,6 @@ class encryption private: public: std::int8_t encrypt(std::uint8_t data, unsigned long int e, unsigned long N); -}; \ No newline at end of file +}; + +#endif \ No newline at end of file diff --git a/src/key.h b/src/key.h index 436d158..abdd808 100644 --- a/src/key.h +++ b/src/key.h @@ -1,3 +1,6 @@ +#ifndef KEY_H +#define KEY_H + #include #include #include @@ -35,4 +38,6 @@ class key { static std::vector* getPrivateKey(std::string &name); static std::vector* getPublicKey(std::string &name); -}; \ No newline at end of file +}; + +#endif \ No newline at end of file diff --git a/src/utility.h b/src/utility.h index 7c835fa..29dd202 100644 --- a/src/utility.h +++ b/src/utility.h @@ -1,3 +1,6 @@ +#ifndef UTILITY_H +#define UTILITY_H + #include class utility @@ -10,3 +13,4 @@ class utility bool checkForPrime(int number); }; +#endif \ No newline at end of file diff --git a/src/vec/operations.h b/src/vec/operations.h index b238e85..327dd70 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -1,7 +1,8 @@ -#include +#ifndef VEC_OPERATIONS_H +#define VEC_OPERATIONS_H +#include #include - #include [[nodiscard]] std::vector add( @@ -120,3 +121,5 @@ std::vector result; return result; } + +#endif From dbc71e06ed4475596176a9801c41df4c9e23bc87 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 16 Mar 2025 17:07:44 +0100 Subject: [PATCH 27/46] fix documentation --- src/key.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/key.cpp b/src/key.cpp index 84414a8..44b4b23 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -123,7 +123,7 @@ std::string key::base64Encode(const std::vector &data) { dataSegment += number << i * 8; } - // 4 times, put 6 bits from dataSegment into result array + // 4 times, put 6 bits from dataSegment into result vector for (int j = 0; j < 4; j++) { dataSegment <<= 6; result.push_back(static_cast((dataSegment & 0b00111111 << 24) >> 24)); From 53b63d62a8c1f1ec785336828f9c3d3b4c7c551a Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Mon, 17 Mar 2025 22:09:29 +0100 Subject: [PATCH 28/46] implement pow operation --- src/vec/operations.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/vec/operations.h b/src/vec/operations.h index 327dd70..9f19ec2 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -122,4 +122,20 @@ return result; } +[[nodiscard]] std::vector pow( + const std::vector &a, + const uint64_t &pow) noexcept +{ + // copy the value from a into result while keeping a constant + std::vector result; + std::copy(a.begin(), a.end(), std::back_inserter(result)); + + // start the loop at 1, because the first number is already assigned to result + for (int i = 1; i < pow; i++) { + result = mul(result, a); + } + + return result; +} + #endif From d06bc8c03d9013ae906e5b9cc4e6166eed82e05c Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Mon, 17 Mar 2025 22:10:27 +0100 Subject: [PATCH 29/46] implement zero check for vector based numbers --- src/vec/operations.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/vec/operations.h b/src/vec/operations.h index 9f19ec2..98a51a9 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -5,6 +5,14 @@ #include #include +[[nodiscard]] bool isZero (const std::vector &a) { + for (auto number: a) { + if (number != 0) return false; + } + + return true; +} + [[nodiscard]] std::vector add( const std::vector &a, const std::vector &b) noexcept From c2387bc34db2430dfae793488f92a0c61763c32e Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Tue, 18 Mar 2025 07:26:02 +0100 Subject: [PATCH 30/46] create isEqual logic for vector numbers and dummy function for isBigger --- src/vec/operations.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/vec/operations.h b/src/vec/operations.h index 98a51a9..86be253 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -13,6 +13,33 @@ return true; } +[[nodiscard]] bool isEqual ( + const std::vector &a, + const std::vector &b) noexcept +{ + const uint64_t iterations = a.size() > b.size() ? a.size() : b.size(); + // in case both numbers are the same length these variables could point ot the same vector + const std::vector shortest = a.size() < b.size() ? a : b; + const std::vector longest = a.size() > b.size() ? a : b; + + for (uint64_t i = 0; i < iterations; i++) { + if (i >= shortest.size()) { + if (longest[i] != 0) return false; + } else { + if (a[i] != b[i]) return false; + } + } + + return true; +} + +[[nodiscard]] bool isBigger ( + const std::vector &a, + const std::vector &b) noexcept +{ + return true; +} + [[nodiscard]] std::vector add( const std::vector &a, const std::vector &b) noexcept From cf48952d94fdcf45a254c5f16263e22a700af5e2 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Tue, 18 Mar 2025 13:22:00 +0100 Subject: [PATCH 31/46] implement getStartBitIndex --- src/vec/operations.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/vec/operations.h b/src/vec/operations.h index 86be253..bce36f3 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -5,6 +5,33 @@ #include #include +[[nodiscard]] uint64_t getStartBitIndex (const std::vector &a) { + uint64_t index = 0; + uint64_t bitsSince1 = 0; + + for (auto number: a) { + // skip 8 bits if all zero + if (number == 0) { + bitsSince1 += 8; + continue; + } + // go over every bit in number + for (int i = 0; i < sizeof(uint8_t) * 8; i++) { + // select the current bit using a bitmask + if ((number & 0b1 << i) != 0) { + // increment the index by the bits since the last increment + index += bitsSince1 + 1; + bitsSince1 = 0; + } else { + bitsSince1++; + } + } + } + + // returns position of the first bit needed for the number + return index - 1; +} + [[nodiscard]] bool isZero (const std::vector &a) { for (auto number: a) { if (number != 0) return false; From c6df8c163bfce9d7f2a26c36950508ada8d19a5d Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Tue, 18 Mar 2025 19:45:14 +0100 Subject: [PATCH 32/46] implement subtract --- src/vec/operations.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/vec/operations.h b/src/vec/operations.h index bce36f3..6a839fd 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -123,6 +123,48 @@ return result; } +// the return value can only be positive, if it would be negative, 0 is returned +[[nodiscard]] std::vector sub( + const std::vector &a, + const std::vector &b) noexcept +{ + // prevent from ending the subtraction before going over the hole subtractor and stop if the result can only be negative + if (getStartBitIndex(b) > getStartBitIndex(a)) return {0}; + + std::vector result; + + // handle an underflow when subtracting + bool borrow = false; + + for (int i = 0; i < a.size(); i++) + { + std::int32_t subtract; + // check for the end of the subtractor + if (i >= b.size()) { + subtract = borrow; + } else { + subtract = borrow + b[i]; + } + borrow = false; + + if (a[i] >= subtract) { + // if the current number is as least as big as subtract + uint8_t number = a[i] - subtract; + result.push_back(number); + } else { + // borrow from the next number + subtract -= 256; + borrow = true; + + // here subtract can only be 0 or negative + uint8_t number = a[i] - subtract; + result.push_back(number); + } + } + + return result; +} + [[nodiscard]] std::vector convertToVector(std::uint64_t number) noexcept { std::vector result; From 1f004220871315d7ddcd2b7be0ec83660c36f884 Mon Sep 17 00:00:00 2001 From: LordofGhost <134922046+LordofGhost@users.noreply.github.com> Date: Tue, 18 Mar 2025 21:37:52 +0100 Subject: [PATCH 33/46] move into namespace operations --- src/vec/operations.h | 375 ++++++++++++++++++++++--------------------- 1 file changed, 192 insertions(+), 183 deletions(-) diff --git a/src/vec/operations.h b/src/vec/operations.h index 6a839fd..e2c3093 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -5,241 +5,250 @@ #include #include -[[nodiscard]] uint64_t getStartBitIndex (const std::vector &a) { - uint64_t index = 0; - uint64_t bitsSince1 = 0; - - for (auto number: a) { - // skip 8 bits if all zero - if (number == 0) { - bitsSince1 += 8; - continue; - } - // go over every bit in number - for (int i = 0; i < sizeof(uint8_t) * 8; i++) { - // select the current bit using a bitmask - if ((number & 0b1 << i) != 0) { - // increment the index by the bits since the last increment - index += bitsSince1 + 1; - bitsSince1 = 0; - } else { - bitsSince1++; +namespace operations { + [[nodiscard]] uint64_t getStartBitIndex (const std::vector &a) { + uint64_t index = 0; + uint64_t bitsSince1 = 0; + + for (auto number: a) { + // skip 8 bits if all zero + if (number == 0) { + bitsSince1 += 8; + continue; + } + // go over every bit in number + for (int i = 0; i < sizeof(uint8_t) * 8; i++) { + // select the current bit using a bitmask + if ((number & 0b1 << i) != 0) { + // increment the index by the bits since the last increment + index += bitsSince1 + 1; + bitsSince1 = 0; + } else { + bitsSince1++; + } } } + + // returns position of the first bit needed for the number + return index - 1; } - // returns position of the first bit needed for the number - return index - 1; -} + [[nodiscard]] bool isZero (const std::vector &a) { + for (auto number: a) { + if (number != 0) return false; + } -[[nodiscard]] bool isZero (const std::vector &a) { - for (auto number: a) { - if (number != 0) return false; + return true; } - return true; -} - -[[nodiscard]] bool isEqual ( - const std::vector &a, - const std::vector &b) noexcept -{ - const uint64_t iterations = a.size() > b.size() ? a.size() : b.size(); - // in case both numbers are the same length these variables could point ot the same vector - const std::vector shortest = a.size() < b.size() ? a : b; - const std::vector longest = a.size() > b.size() ? a : b; - - for (uint64_t i = 0; i < iterations; i++) { - if (i >= shortest.size()) { - if (longest[i] != 0) return false; - } else { - if (a[i] != b[i]) return false; + [[nodiscard]] bool isEqual ( + const std::vector &a, + const std::vector &b) noexcept + { + const uint64_t iterations = a.size() > b.size() ? a.size() : b.size(); + // in case both numbers are the same length these variables could point ot the same vector + const std::vector shortest = a.size() < b.size() ? a : b; + const std::vector longest = a.size() > b.size() ? a : b; + + for (uint64_t i = 0; i < iterations; i++) { + if (i >= shortest.size()) { + if (longest[i] != 0) return false; + } else { + if (a[i] != b[i]) return false; + } } + + return true; } - return true; -} + [[nodiscard]] bool isBigger ( + const std::vector &a, + const std::vector &b) noexcept + { + return true; + } -[[nodiscard]] bool isBigger ( - const std::vector &a, - const std::vector &b) noexcept -{ - return true; -} + [[nodiscard]] std::vector add( + const std::vector &a, + const std::vector &b) noexcept + { + // Time complexity O(iterations) + // Initialize the result vector to store the sum + std::vector result; -[[nodiscard]] std::vector add( - const std::vector &a, - const std::vector &b) noexcept -{ - // Time complexity O(iterations) - // Initialize the result vector to store the sum - std::vector result; + // Get the max iterations based on the largest vector + const int iterations = std::max(a.size(), b.size()); - // Get the max iterations based on the largest vector - const int iterations = std::max(a.size(), b.size()); + // Carry to handle overflow between bytes + std::uint16_t carry = 0; - // Carry to handle overflow between bytes - std::uint16_t carry = 0; + for (int i = 0; i < iterations; i++) + { + // Set up a holder for the sum + std::uint16_t sum = carry; - for (int i = 0; i < iterations; i++) - { - // Set up a holder for the sum - std::uint16_t sum = carry; + // Only add to sum if we actually have a value in a + if (i < a.size()) + { + sum += a[i]; + } - // Only add to sum if we actually have a value in a - if (i < a.size()) - { - sum += a[i]; + // Only add to sum if we actually have a value in b + if (i < b.size()) + { + sum += b[i]; + } + + // Calculate the carry which is the overflow beyond 255 + carry = sum >> 8; + + // Clear out everything except the lsb + // This is done by masking the sum with 255 + // For example + // 0000000101111111 (=383) + // 0000000011111111 (=255) + // ---------------- + // 0000000100000000 + sum &= 0xFF; + + // Append the least significant byte of the sum to the result + result.push_back(static_cast(sum)); } - // Only add to sum if we actually have a value in b - if (i < b.size()) + // If we got a carry we append this as well + if (carry) { - sum += b[i]; + result.push_back(static_cast(carry)); } - // Calculate the carry which is the overflow beyond 255 - carry = sum >> 8; - - // Clear out everything except the lsb - // This is done by masking the sum with 255 - // For example - // 0000000101111111 (=383) - // 0000000011111111 (=255) - // ---------------- - // 0000000100000000 - sum &= 0xFF; - - // Append the least significant byte of the sum to the result - result.push_back(static_cast(sum)); + return result; } - // If we got a carry we append this as well - if (carry) + // the return value can only be positive, if it would be negative, 0 is returned + [[nodiscard]] std::vector sub( + const std::vector &a, + const std::vector &b) noexcept { - result.push_back(static_cast(carry)); - } + // prevent from ending the subtraction before going over the hole subtractor and stop if the result can only be negative + if (getStartBitIndex(b) > getStartBitIndex(a)) return {0}; - return result; -} + std::vector result; -// the return value can only be positive, if it would be negative, 0 is returned -[[nodiscard]] std::vector sub( - const std::vector &a, - const std::vector &b) noexcept -{ - // prevent from ending the subtraction before going over the hole subtractor and stop if the result can only be negative - if (getStartBitIndex(b) > getStartBitIndex(a)) return {0}; + // handle an underflow when subtracting + bool borrow = false; - std::vector result; + for (int i = 0; i < a.size(); i++) + { + std::int32_t subtract; + // check for the end of the subtractor + if (i >= b.size()) { + subtract = borrow; + } else { + subtract = borrow + b[i]; + } + borrow = false; - // handle an underflow when subtracting - bool borrow = false; + if (a[i] >= subtract) { + // if the current number is as least as big as subtract + uint8_t number = a[i] - subtract; + result.push_back(number); + } else { + // borrow from the next number + subtract -= 256; + borrow = true; - for (int i = 0; i < a.size(); i++) - { - std::int32_t subtract; - // check for the end of the subtractor - if (i >= b.size()) { - subtract = borrow; - } else { - subtract = borrow + b[i]; - } - borrow = false; - - if (a[i] >= subtract) { - // if the current number is as least as big as subtract - uint8_t number = a[i] - subtract; - result.push_back(number); - } else { - // borrow from the next number - subtract -= 256; - borrow = true; - - // here subtract can only be 0 or negative - uint8_t number = a[i] - subtract; - result.push_back(number); + // here subtract can only be 0 or negative + uint8_t number = a[i] - subtract; + result.push_back(number); + } } + + return result; } - return result; -} + [[nodiscard]] std::vector convertToVector(std::uint64_t number) noexcept { -[[nodiscard]] std::vector convertToVector(std::uint64_t number) noexcept { + std::vector result; - std::vector result; + // Loop until the whole number is zero + while (number) + { + // We only care for the lsb + result.push_back(static_cast(number & 0xFF)); - // Loop until the whole number is zero - while (number) - { - // We only care for the lsb - result.push_back(static_cast(number & 0xFF)); + // Shift the number by 8 to the right + number >>= 8; + } - // Shift the number by 8 to the right - number >>= 8; + return result; } - return result; -} + [[nodiscard]] std::vector mul( + const std::vector &a, + const std::vector &b) noexcept + { + // Time complexity O(aSize * bSize) + const std::uint64_t aSize = a.size(); + const std::uint64_t bSize = b.size(); -[[nodiscard]] std::vector mul( - const std::vector &a, - const std::vector &b) noexcept -{ - // Time complexity O(aSize * bSize) - const std::uint64_t aSize = a.size(); - const std::uint64_t bSize = b.size(); + // Initialize the result vector with zeros, with the size of aSize + bSize + std::vector result(aSize + bSize, 0); - // Initialize the result vector with zeros, with the size of aSize + bSize - std::vector result(aSize + bSize, 0); + for (std::uint64_t i = 0; i < aSize; i++) + { + // Set up the carry value for each iteration + std::uint16_t carry = 0; - for (std::uint64_t i = 0; i < aSize; i++) - { - // Set up the carry value for each iteration - std::uint16_t carry = 0; + for (uint64_t x = 0; x < bSize; x++) + { + // Calculate the product by adding up the previous result, the carry, and the new product + std::uint16_t product = result[i + x] + carry + (a[i] * b[x]); - for (uint64_t x = 0; x < bSize; x++) - { - // Calculate the product by adding up the previous result, the carry, and the new product - std::uint16_t product = result[i + x] + carry + (a[i] * b[x]); + // Calculate the carry which is the overflow beyond 255 + carry = product >> 8; - // Calculate the carry which is the overflow beyond 255 - carry = product >> 8; + // Store the least significant byte (lsb) of the product in the result + result[i + x] = static_cast(product & 0xFF); + } - // Store the least significant byte (lsb) of the product in the result - result[i + x] = static_cast(product & 0xFF); + // If there is a carry, append it to the result + // But with the offset of bSize because of the previous inner loop + result[i + bSize] += static_cast(carry); } - // If there is a carry, append it to the result - // But with the offset of bSize because of the previous inner loop - result[i + bSize] += static_cast(carry); + return result; } - return result; -} + // a is divided by b + [[nodiscard]] std::vector div( + const std::vector &a, + const std::vector &b) noexcept + { + const std::vector dividend = a; + std::vector result; -[[nodiscard]] std::vector div( - const std::vector &a, - const std::vector &b) noexcept -{ - std::vector result; - return result; -} + while (!isZero(dividend)) { -[[nodiscard]] std::vector pow( - const std::vector &a, - const uint64_t &pow) noexcept -{ - // copy the value from a into result while keeping a constant - std::vector result; - std::copy(a.begin(), a.end(), std::back_inserter(result)); - - // start the loop at 1, because the first number is already assigned to result - for (int i = 1; i < pow; i++) { - result = mul(result, a); + } + + return result; } - return result; + [[nodiscard]] std::vector pow( + const std::vector &a, + const uint64_t &pow) noexcept + { + // copy the value from a into result while keeping a constant + std::vector result; + std::copy(a.begin(), a.end(), std::back_inserter(result)); + + // start the loop at 1, because the first number is already assigned to result + for (int i = 1; i < pow; i++) { + result = mul(result, a); + } + + return result; + } } #endif From ef7fa7690e375ec197c405fb67f1e1832994b2fc Mon Sep 17 00:00:00 2001 From: Jochen <97750753+Jochengehtab@users.noreply.github.com> Date: Tue, 18 Mar 2025 21:43:14 +0100 Subject: [PATCH 34/46] fix doc --- src/vec/operations.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/vec/operations.h b/src/vec/operations.h index e2c3093..3110ec3 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -11,16 +11,16 @@ namespace operations { uint64_t bitsSince1 = 0; for (auto number: a) { - // skip 8 bits if all zero + // Skip 8 bits if all zero if (number == 0) { bitsSince1 += 8; continue; } - // go over every bit in number + // Go over every bit in number for (int i = 0; i < sizeof(uint8_t) * 8; i++) { - // select the current bit using a bitmask + // Select the current bit using a bitmask if ((number & 0b1 << i) != 0) { - // increment the index by the bits since the last increment + // Increment the index by the bits since the last increment index += bitsSince1 + 1; bitsSince1 = 0; } else { @@ -29,7 +29,7 @@ namespace operations { } } - // returns position of the first bit needed for the number + // Returns position of the first bit needed for the number return index - 1; } @@ -46,7 +46,7 @@ namespace operations { const std::vector &b) noexcept { const uint64_t iterations = a.size() > b.size() ? a.size() : b.size(); - // in case both numbers are the same length these variables could point ot the same vector + // In case both numbers are the same length these variables could point ot the same vector const std::vector shortest = a.size() < b.size() ? a : b; const std::vector longest = a.size() > b.size() ? a : b; @@ -124,23 +124,23 @@ namespace operations { return result; } - // the return value can only be positive, if it would be negative, 0 is returned + // The return value can only be positive, if it would be negative, 0 is returned [[nodiscard]] std::vector sub( const std::vector &a, const std::vector &b) noexcept { - // prevent from ending the subtraction before going over the hole subtractor and stop if the result can only be negative + // Prevent from ending the subtraction before going over the hole subtractor and stop if the result can only be negative if (getStartBitIndex(b) > getStartBitIndex(a)) return {0}; std::vector result; - // handle an underflow when subtracting + // Handle an underflow when subtracting bool borrow = false; for (int i = 0; i < a.size(); i++) { std::int32_t subtract; - // check for the end of the subtractor + // Check for the end of the subtractor if (i >= b.size()) { subtract = borrow; } else { @@ -149,15 +149,15 @@ namespace operations { borrow = false; if (a[i] >= subtract) { - // if the current number is as least as big as subtract + // If the current number is as least as big as subtract uint8_t number = a[i] - subtract; result.push_back(number); } else { - // borrow from the next number + // Borrow from the next number subtract -= 256; borrow = true; - // here subtract can only be 0 or negative + // Here subtract can only be 0 or negative uint8_t number = a[i] - subtract; result.push_back(number); } @@ -238,11 +238,11 @@ namespace operations { const std::vector &a, const uint64_t &pow) noexcept { - // copy the value from a into result while keeping a constant + // Copy the value from a into result while keeping a constant std::vector result; std::copy(a.begin(), a.end(), std::back_inserter(result)); - // start the loop at 1, because the first number is already assigned to result + // Start the loop at 1, because the first number is already assigned to result for (int i = 1; i < pow; i++) { result = mul(result, a); } From 49be7ede29070d070ef3a3cb1cd836fecf21376d Mon Sep 17 00:00:00 2001 From: Jochen <97750753+Jochengehtab@users.noreply.github.com> Date: Sun, 23 Mar 2025 04:38:42 +0100 Subject: [PATCH 35/46] fix main example --- src/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index bd1ce00..e9467ae 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,10 +54,10 @@ int main(int argc, char* argv[]) { cli::help(); } - std::vector num1 = convertToVector(55555555); - std::vector num2 = convertToVector(45678); + std::vector num1 = operations::convertToVector(55555555); + std::vector num2 = operations::convertToVector(45678); - std::vector result = mul(num1, num2); + std::vector result = operations::mul(num1, num2); // This gives out the result as a hex number for (auto it = result.rbegin(); it != result.rend(); ++it) { From cf18da0908449cbfd3272f636714b462bb0c48d5 Mon Sep 17 00:00:00 2001 From: Jochen <97750753+Jochengehtab@users.noreply.github.com> Date: Sun, 23 Mar 2025 04:44:10 +0100 Subject: [PATCH 36/46] simplify isEqual function --- src/main.cpp | 1 + src/vec/operations.h | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e9467ae..4adb586 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -58,6 +58,7 @@ int main(int argc, char* argv[]) { std::vector num2 = operations::convertToVector(45678); std::vector result = operations::mul(num1, num2); + std::cout << operations::isEqual(num1, num2) << std::endl; // This gives out the result as a hex number for (auto it = result.rbegin(); it != result.rend(); ++it) { diff --git a/src/vec/operations.h b/src/vec/operations.h index 3110ec3..431c2b2 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -45,13 +45,16 @@ namespace operations { const std::vector &a, const std::vector &b) noexcept { - const uint64_t iterations = a.size() > b.size() ? a.size() : b.size(); + const std::uint32_t aSize = a.size(); + const std::uint32_t bSize = b.size(); + const std::uint64_t iterations = aSize > bSize ? aSize : bSize; + // In case both numbers are the same length these variables could point ot the same vector - const std::vector shortest = a.size() < b.size() ? a : b; - const std::vector longest = a.size() > b.size() ? a : b; + const std::uint32_t shortest = aSize < bSize ? aSize : bSize; + const std::vector longest = aSize > bSize ? a : b; for (uint64_t i = 0; i < iterations; i++) { - if (i >= shortest.size()) { + if (i >= shortest) { if (longest[i] != 0) return false; } else { if (a[i] != b[i]) return false; From 4db5461381ae232c0f10fc23aef310e056dd535e Mon Sep 17 00:00:00 2001 From: Jochen <97750753+Jochengehtab@users.noreply.github.com> Date: Sun, 23 Mar 2025 05:03:34 +0100 Subject: [PATCH 37/46] implement basic is bigger function without leading zero check --- src/main.cpp | 4 +++- src/vec/operations.h | 40 ++++++++++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4adb586..627fb76 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -57,8 +57,10 @@ int main(int argc, char* argv[]) { std::vector num1 = operations::convertToVector(55555555); std::vector num2 = operations::convertToVector(45678); + //std::vector num1 = {00000000, 00000000,00000000,00000000,00000000, 7}; + std::vector result = operations::mul(num1, num2); - std::cout << operations::isEqual(num1, num2) << std::endl; + std::cout << operations::isBigger(num2, num1) << std::endl; // This gives out the result as a hex number for (auto it = result.rbegin(); it != result.rend(); ++it) { diff --git a/src/vec/operations.h b/src/vec/operations.h index 431c2b2..f20b1a4 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -7,17 +7,17 @@ namespace operations { [[nodiscard]] uint64_t getStartBitIndex (const std::vector &a) { - uint64_t index = 0; - uint64_t bitsSince1 = 0; + std::uint64_t index = 0; + std::uint64_t bitsSince1 = 0; - for (auto number: a) { + for (std::uint8_t number: a) { // Skip 8 bits if all zero if (number == 0) { bitsSince1 += 8; continue; } // Go over every bit in number - for (int i = 0; i < sizeof(uint8_t) * 8; i++) { + for (std::uint64_t i = 0; i < sizeof(std::uint8_t) * 8; i++) { // Select the current bit using a bitmask if ((number & 0b1 << i) != 0) { // Increment the index by the bits since the last increment @@ -34,7 +34,7 @@ namespace operations { } [[nodiscard]] bool isZero (const std::vector &a) { - for (auto number: a) { + for (std::uint8_t number: a) { if (number != 0) return false; } @@ -53,7 +53,7 @@ namespace operations { const std::uint32_t shortest = aSize < bSize ? aSize : bSize; const std::vector longest = aSize > bSize ? a : b; - for (uint64_t i = 0; i < iterations; i++) { + for (std::uint64_t i = 0; i < iterations; i++) { if (i >= shortest) { if (longest[i] != 0) return false; } else { @@ -68,7 +68,27 @@ namespace operations { const std::vector &a, const std::vector &b) noexcept { - return true; + const std::uint32_t aSize = a.size(); + const std::uint32_t bSize = b.size(); + const std::uint64_t iterations = aSize > bSize ? aSize : bSize; + + // We loop reverse throw all the vectors to catch leading zeros + for (std::uint64_t i = iterations - 1; i > 0; i--) { + // Check for leading zeros in one of the two vectors + + const std::uint32_t index = i - 1; + + const std::uint8_t aValue = (index < aSize) ? a[index] : 0; + const std::uint8_t bValue = (index < bSize) ? b[index] : 0; + + if (aValue > bValue) + { + return true; + } + } + + + return false; } [[nodiscard]] std::vector add( @@ -153,7 +173,7 @@ namespace operations { if (a[i] >= subtract) { // If the current number is as least as big as subtract - uint8_t number = a[i] - subtract; + std::uint8_t number = a[i] - subtract; result.push_back(number); } else { // Borrow from the next number @@ -161,7 +181,7 @@ namespace operations { borrow = true; // Here subtract can only be 0 or negative - uint8_t number = a[i] - subtract; + std::uint8_t number = a[i] - subtract; result.push_back(number); } } @@ -239,7 +259,7 @@ namespace operations { [[nodiscard]] std::vector pow( const std::vector &a, - const uint64_t &pow) noexcept + const std::uint64_t &pow) noexcept { // Copy the value from a into result while keeping a constant std::vector result; From b9daffaeff05d8eb1358534c5fea3b793126b68c Mon Sep 17 00:00:00 2001 From: Jochen <97750753+Jochengehtab@users.noreply.github.com> Date: Sun, 23 Mar 2025 05:07:25 +0100 Subject: [PATCH 38/46] implement leading zero check --- src/main.cpp | 4 ++-- src/vec/operations.h | 26 ++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 627fb76..8a7c8e9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,10 +54,10 @@ int main(int argc, char* argv[]) { cli::help(); } - std::vector num1 = operations::convertToVector(55555555); + //std::vector num1 = operations::convertToVector(55555555); std::vector num2 = operations::convertToVector(45678); - //std::vector num1 = {00000000, 00000000,00000000,00000000,00000000, 7}; + std::vector num1 = {00000000, 00000000,00000000,00000000,00000000, 7}; std::vector result = operations::mul(num1, num2); std::cout << operations::isBigger(num2, num1) << std::endl; diff --git a/src/vec/operations.h b/src/vec/operations.h index f20b1a4..7fa28a0 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -72,15 +72,37 @@ namespace operations { const std::uint32_t bSize = b.size(); const std::uint64_t iterations = aSize > bSize ? aSize : bSize; + bool aFirstNumber = false; + bool bFirstNumber = false; + // We loop reverse throw all the vectors to catch leading zeros for (std::uint64_t i = iterations - 1; i > 0; i--) { - // Check for leading zeros in one of the two vectors - const std::uint32_t index = i - 1; const std::uint8_t aValue = (index < aSize) ? a[index] : 0; + if (aValue != 0) + { + aFirstNumber = true; + } + const std::uint8_t bValue = (index < bSize) ? b[index] : 0; + if (bValue != 0) + { + bFirstNumber = true; + } + + if (aFirstNumber && !bFirstNumber) + { + return true; + } + + if (!aFirstNumber && bFirstNumber) + { + return false; + } + + if (aValue > bValue) { return true; From 00590420b3d4b68148e7f498c01647303497e133 Mon Sep 17 00:00:00 2001 From: Jochen <97750753+Jochengehtab@users.noreply.github.com> Date: Sun, 23 Mar 2025 06:30:49 +0100 Subject: [PATCH 39/46] add documentation for is bigger --- src/main.cpp | 7 ++++--- src/vec/operations.h | 32 +++++++++++++++++++++----------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 8a7c8e9..5f45b93 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -55,12 +55,13 @@ int main(int argc, char* argv[]) { } //std::vector num1 = operations::convertToVector(55555555); - std::vector num2 = operations::convertToVector(45678); + //std::vector num2 = operations::convertToVector(45678); std::vector num1 = {00000000, 00000000,00000000,00000000,00000000, 7}; + std::vector num2 = {00000000, 1,00000000, 15}; - std::vector result = operations::mul(num1, num2); - std::cout << operations::isBigger(num2, num1) << std::endl; + std::vector result = operations::sub(num2, num1); + std::cout << operations::isBigger(num1, num2) << std::endl; // This gives out the result as a hex number for (auto it = result.rbegin(); it != result.rend(); ++it) { diff --git a/src/vec/operations.h b/src/vec/operations.h index 7fa28a0..ecbd35f 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -6,7 +6,7 @@ #include namespace operations { - [[nodiscard]] uint64_t getStartBitIndex (const std::vector &a) { + [[nodiscard]] std::uint64_t getStartBitIndex (const std::vector &a) { std::uint64_t index = 0; std::uint64_t bitsSince1 = 0; @@ -72,43 +72,53 @@ namespace operations { const std::uint32_t bSize = b.size(); const std::uint64_t iterations = aSize > bSize ? aSize : bSize; - bool aFirstNumber = false; - bool bFirstNumber = false; + bool aNonZero = false; + bool bNonZero = false; // We loop reverse throw all the vectors to catch leading zeros for (std::uint64_t i = iterations - 1; i > 0; i--) { const std::uint32_t index = i - 1; + // Check if the index is within the size of the a vector + // If it isn't within the size we just ste it to zero const std::uint8_t aValue = (index < aSize) ? a[index] : 0; + + // Check for leading zero if (aValue != 0) { - aFirstNumber = true; + aNonZero = true; } + // Sane as above but with the b vector const std::uint8_t bValue = (index < bSize) ? b[index] : 0; + // Check for leading zero if (bValue != 0) { - bFirstNumber = true; + bNonZero = true; } - if (aFirstNumber && !bFirstNumber) + // If we got no zeros on a but have one on b + // Then a is greater then b + if (aNonZero && !bNonZero) { return true; } - if (!aFirstNumber && bFirstNumber) + // If we got no zeros on a but have one on b + // Then a is greater then b + if (!aNonZero && bNonZero) { return false; } - + // We can just compare the two values since we loop + // reverse throw the two vectors if (aValue > bValue) { return true; } } - return false; } @@ -284,11 +294,11 @@ namespace operations { const std::uint64_t &pow) noexcept { // Copy the value from a into result while keeping a constant - std::vector result; + std::vector result; std::copy(a.begin(), a.end(), std::back_inserter(result)); // Start the loop at 1, because the first number is already assigned to result - for (int i = 1; i < pow; i++) { + for (std::uint32_t i = 1; i < pow; i++) { result = mul(result, a); } From e4eab2225d0ec11d762f4bfc2a0627fee043fbab Mon Sep 17 00:00:00 2001 From: Jochen <97750753+Jochengehtab@users.noreply.github.com> Date: Sun, 23 Mar 2025 14:41:15 +0100 Subject: [PATCH 40/46] fix mul --- src/main.cpp | 13 ++++++++----- src/vec/operations.h | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5f45b93..5aff9bf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -57,14 +57,17 @@ int main(int argc, char* argv[]) { //std::vector num1 = operations::convertToVector(55555555); //std::vector num2 = operations::convertToVector(45678); - std::vector num1 = {00000000, 00000000,00000000,00000000,00000000, 7}; - std::vector num2 = {00000000, 1,00000000, 15}; + std::vector num1 = {0, 0, 0, 0, 0, 1}; + std::vector num2 = {0, 0, 15}; + std::vector num3 = {2}; - std::vector result = operations::sub(num2, num1); + std::vector result = operations::mul(num2, num1); std::cout << operations::isBigger(num1, num2) << std::endl; - // This gives out the result as a hex number - for (auto it = result.rbegin(); it != result.rend(); ++it) { + std::vector result2 = operations::mul(result, num3); + + // This prints out the result as a hex number + for (auto it = result2.rbegin(); it != result2.rend(); ++it) { printf("%02X", *it); } std::cout << std::endl; diff --git a/src/vec/operations.h b/src/vec/operations.h index ecbd35f..71021f0 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -271,6 +271,21 @@ namespace operations { result[i + bSize] += static_cast(carry); } + // Remove any leading zeros. + auto firstNonZero = std::find_if(result.begin(), result.end(), [](std::uint8_t byte) + { + return byte != 0; + }); + + if (firstNonZero != result.end()) + { + return std::vector(firstNonZero, result.end()); + } + else + { + return {0}; + } + return result; } From b34dfe927c584c6d4556f7f69b047d82be912457 Mon Sep 17 00:00:00 2001 From: Jochen <97750753+Jochengehtab@users.noreply.github.com> Date: Sun, 23 Mar 2025 15:22:17 +0100 Subject: [PATCH 41/46] remove unecessary code --- src/main.cpp | 7 ++----- src/vec/operations.h | 15 --------------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5aff9bf..61800db 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -57,17 +57,14 @@ int main(int argc, char* argv[]) { //std::vector num1 = operations::convertToVector(55555555); //std::vector num2 = operations::convertToVector(45678); - std::vector num1 = {0, 0, 0, 0, 0, 1}; - std::vector num2 = {0, 0, 15}; - std::vector num3 = {2}; - std::vector result = operations::mul(num2, num1); + std::cout << operations::isBigger(num1, num2) << std::endl; std::vector result2 = operations::mul(result, num3); // This prints out the result as a hex number - for (auto it = result2.rbegin(); it != result2.rend(); ++it) { + for (auto it = result.rbegin(); it != result.rend(); ++it) { printf("%02X", *it); } std::cout << std::endl; diff --git a/src/vec/operations.h b/src/vec/operations.h index 71021f0..ecbd35f 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -271,21 +271,6 @@ namespace operations { result[i + bSize] += static_cast(carry); } - // Remove any leading zeros. - auto firstNonZero = std::find_if(result.begin(), result.end(), [](std::uint8_t byte) - { - return byte != 0; - }); - - if (firstNonZero != result.end()) - { - return std::vector(firstNonZero, result.end()); - } - else - { - return {0}; - } - return result; } From 14384d13e9028e271185564f4562e4a80d028dc7 Mon Sep 17 00:00:00 2001 From: Jochen <97750753+Jochengehtab@users.noreply.github.com> Date: Sun, 23 Mar 2025 15:38:09 +0100 Subject: [PATCH 42/46] fix main example --- src/main.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 61800db..5c8ed88 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,15 +54,13 @@ int main(int argc, char* argv[]) { cli::help(); } - //std::vector num1 = operations::convertToVector(55555555); - //std::vector num2 = operations::convertToVector(45678); + std::vector num1 = operations::convertToVector(55555555); + std::vector num2 = operations::convertToVector(45678); std::vector result = operations::mul(num2, num1); std::cout << operations::isBigger(num1, num2) << std::endl; - std::vector result2 = operations::mul(result, num3); - // This prints out the result as a hex number for (auto it = result.rbegin(); it != result.rend(); ++it) { printf("%02X", *it); From b62dd41e2bc8d43454a858ea5848e3ae475b84bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20B=C3=B6hm?= <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 23 Mar 2025 15:59:23 +0100 Subject: [PATCH 43/46] Feature/key#zero check (#8) Co-authored-by: Jochen <97750753+Jochengehtab@users.noreply.github.com> --- src/main.cpp | 10 +++++++--- src/vec/operations.h | 42 ++---------------------------------------- 2 files changed, 9 insertions(+), 43 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5c8ed88..f7106d8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,11 +54,15 @@ int main(int argc, char* argv[]) { cli::help(); } - std::vector num1 = operations::convertToVector(55555555); - std::vector num2 = operations::convertToVector(45678); + //std::vector num1 = operations::convertToVector(55555555); + //std::vector num2 = operations::convertToVector(45678); - std::vector result = operations::mul(num2, num1); + // 00010000 00000000 00000000 00000000 + std::vector num1 = {0b00000000, 0b00000000, 0b00000000, 0b00010000}; + // 00000000 00000100 00000000 00000000 + std::vector num2 = {0b00000000, 0b00000000, 0b00000100}; + std::vector result = operations::mul(num1, num2); std::cout << operations::isBigger(num1, num2) << std::endl; // This prints out the result as a hex number diff --git a/src/vec/operations.h b/src/vec/operations.h index ecbd35f..1775e43 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -72,55 +72,17 @@ namespace operations { const std::uint32_t bSize = b.size(); const std::uint64_t iterations = aSize > bSize ? aSize : bSize; - bool aNonZero = false; - bool bNonZero = false; - // We loop reverse throw all the vectors to catch leading zeros for (std::uint64_t i = iterations - 1; i > 0; i--) { - const std::uint32_t index = i - 1; - - // Check if the index is within the size of the a vector - // If it isn't within the size we just ste it to zero - const std::uint8_t aValue = (index < aSize) ? a[index] : 0; - - // Check for leading zero - if (aValue != 0) - { - aNonZero = true; - } - - // Sane as above but with the b vector - const std::uint8_t bValue = (index < bSize) ? b[index] : 0; - // Check for leading zero - if (bValue != 0) - { - bNonZero = true; - } + const std::uint8_t aValue = (i < aSize) ? a[i] : 0; + const std::uint8_t bValue = (i < bSize) ? b[i] : 0; - // If we got no zeros on a but have one on b - // Then a is greater then b - if (aNonZero && !bNonZero) - { - return true; - } - - // If we got no zeros on a but have one on b - // Then a is greater then b - if (!aNonZero && bNonZero) - { - return false; - } - - // We can just compare the two values since we loop - // reverse throw the two vectors if (aValue > bValue) { return true; } } - - return false; } [[nodiscard]] std::vector add( From 255200a809f1079312b83e361bf8c4872aa0d0cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20B=C3=B6hm?= <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 23 Mar 2025 18:24:36 +0100 Subject: [PATCH 44/46] fix isBigger - looping over the hole number - return false at the end --- src/vec/operations.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vec/operations.h b/src/vec/operations.h index 1775e43..36d3310 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -73,7 +73,7 @@ namespace operations { const std::uint64_t iterations = aSize > bSize ? aSize : bSize; // We loop reverse throw all the vectors to catch leading zeros - for (std::uint64_t i = iterations - 1; i > 0; i--) { + for (std::int64_t i = iterations - 1; i >= 0; i--) { const std::uint8_t aValue = (i < aSize) ? a[i] : 0; const std::uint8_t bValue = (i < bSize) ? b[i] : 0; @@ -83,6 +83,8 @@ namespace operations { return true; } } + + return false; } [[nodiscard]] std::vector add( From 0bb3745712bdb019693b929348b272aedac029ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20B=C3=B6hm?= <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 23 Mar 2025 19:26:56 +0100 Subject: [PATCH 45/46] implement divide operation - addBitFromNumber needed as utility - fractional digits are not supported - if the result is 0, an empty vector is returned --- src/vec/operations.h | 89 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 8 deletions(-) diff --git a/src/vec/operations.h b/src/vec/operations.h index 36d3310..fc68774 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -33,6 +33,33 @@ namespace operations { return index - 1; } + /* This function picks one bit from pickNumber and places it at the least significant + * position of number. */ + [[nodiscard]] std::vector addBitFromNumber (const std::vector &number, const std::vector &pickNumber, std::uint32_t index) { + std::vector result; + + // Check if the index is valid + if (index > getStartBitIndex(pickNumber)) { + return {0}; + } + + // Check if the bit at the given index is set + bool mostSignificantBit = pickNumber[index / 8] & 0b1 << index % 8; + + for (std::uint8_t currentByte : number) { + result.push_back((currentByte << 1) + mostSignificantBit); + + // Check if the most significant bit of the current byte is set + mostSignificantBit = currentByte & 0b1000000 == 0b10000000; + } + + /* In case the length of the vector and the actual number length matches, the number + * increases by one vector element with value 1 */ + if (mostSignificantBit) result.push_back(0b1); + + return result; + } + [[nodiscard]] bool isZero (const std::vector &a) { for (std::uint8_t number: a) { if (number != 0) return false; @@ -238,19 +265,65 @@ namespace operations { return result; } - // a is divided by b [[nodiscard]] std::vector div( - const std::vector &a, - const std::vector &b) noexcept - { - const std::vector dividend = a; - std::vector result; + const std::vector dividend, + const std::vector &divisor) noexcept { + std::vector quotient; + std::uint8_t quotientBuffer = 0; + std::uint16_t quotientBitIndex = 0; + + // The index of the last bit in the dividendMask inside dividend + std::int64_t dividendIndex = getStartBitIndex(dividend); + // This copy's the most significant bit of the dividend + std::vector dividendMask = addBitFromNumber({0}, dividend, dividendIndex--); + + while (dividendIndex >= -1) { + + if (quotientBitIndex > 7) { + /* The quotient is stored from the most significant byte to the least significant + * byte, in contrast to all the other vector based numbers. + * Which is later reversed, at the end of the function. */ + quotient.push_back(quotientBuffer); + quotientBuffer = 0; + quotientBitIndex = 0; + } - while (!isZero(dividend)) { + if (isEqual(dividendMask, divisor) || isBigger(dividendMask, divisor)) { + // Shift the dividend and set the new bit as high + quotientBuffer <<= 1; + quotientBuffer++; + quotientBitIndex++; + + dividendMask = sub(dividendMask, divisor); + dividendMask = addBitFromNumber(dividendMask, dividend, dividendIndex--); + } else { + /* Stop the loop if the dividend is smaller than the divisor, because fractional + * digits are not supported */ + if (dividendIndex < 0) { + quotientBuffer <<= 1; + break; + } + /* if the divisor is bigger than the dividend, we need to shift the dividend + * and set the new bit as low */ + quotientBuffer <<= 1; + quotientBitIndex++; + + /* Stop the loop if the dividend is smaller than the divisor, because fractional + * digits are not supported */ + if (dividendIndex < 0) break; + + // Because dividendMask is smaller than divisor, we add the next bit from the dividend + dividendMask = addBitFromNumber(dividendMask, dividend, dividendIndex--); + } } - return result; + if (quotientBuffer != 0) quotient.push_back(quotientBuffer); + + // Reverse the quotient + std::reverse(quotient.begin(), quotient.end()); + + return quotient; } [[nodiscard]] std::vector pow( From efe731d27dab3d784bb0c4f9aa6e952bc61ae326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20B=C3=B6hm?= <134922046+LordofGhost@users.noreply.github.com> Date: Sun, 23 Mar 2025 20:29:00 +0100 Subject: [PATCH 46/46] Implement Modulu (#10) Co-authored-by: Jochen <97750753+Jochengehtab@users.noreply.github.com> --- src/main.cpp | 17 ----------------- src/vec/operations.h | 18 +++++++++++++++++- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index f7106d8..15e2ebd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,22 +54,5 @@ int main(int argc, char* argv[]) { cli::help(); } - //std::vector num1 = operations::convertToVector(55555555); - //std::vector num2 = operations::convertToVector(45678); - - // 00010000 00000000 00000000 00000000 - std::vector num1 = {0b00000000, 0b00000000, 0b00000000, 0b00010000}; - // 00000000 00000100 00000000 00000000 - std::vector num2 = {0b00000000, 0b00000000, 0b00000100}; - - std::vector result = operations::mul(num1, num2); - std::cout << operations::isBigger(num1, num2) << std::endl; - - // This prints out the result as a hex number - for (auto it = result.rbegin(); it != result.rend(); ++it) { - printf("%02X", *it); - } - std::cout << std::endl; - return 0; } diff --git a/src/vec/operations.h b/src/vec/operations.h index fc68774..c76a995 100644 --- a/src/vec/operations.h +++ b/src/vec/operations.h @@ -267,7 +267,9 @@ namespace operations { [[nodiscard]] std::vector div( const std::vector dividend, - const std::vector &divisor) noexcept { + const std::vector &divisor, + std::vector *remaining = nullptr) noexcept +{ std::vector quotient; std::uint8_t quotientBuffer = 0; std::uint16_t quotientBitIndex = 0; @@ -289,6 +291,17 @@ namespace operations { } if (isEqual(dividendMask, divisor) || isBigger(dividendMask, divisor)) { + + /* Stop the loop if the dividend is smaller than the divisor, because fractional + * digits are not supported */ + if (dividendIndex < 0) { + quotientBuffer <<= 1; + + // If remaining pointer is passed, set the remaining value + if (remaining != nullptr) *remaining = dividendMask; + break; + } + // Shift the dividend and set the new bit as high quotientBuffer <<= 1; quotientBuffer++; @@ -301,6 +314,9 @@ namespace operations { * digits are not supported */ if (dividendIndex < 0) { quotientBuffer <<= 1; + + // If remaining pointer is passed, set the remaining value + if (remaining != nullptr) *remaining = dividendMask; break; }