Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ add_subdirectory(src)
include(CTest)
add_subdirectory(tests)

target_link_libraries(RSA PUBLIC Base256)
target_include_directories(RSA PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(RSA PUBLIC BigInt)
target_include_directories(RSA PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
2 changes: 1 addition & 1 deletion docs/algorithms/div.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ When the loop finishes processing the final bit (`dividendIndex < 0`), whatever
*(Note: Because of this architecture, evaluating `A % B` requires the exact same computational effort as `A / B`. Therefore, if both the quotient and remainder are needed, they are extracted simultaneously to halve CPU cycles).*

### 5. Final Normalization
Even though pre-allocation is tightly bound to the `initialDividendIndex`, the final quotient might have leading zeros depending on the magnitude of the divisor. The `div` function concludes by stripping any trailing zero-bytes from the little-endian vector to maintain strict `Base256` normalization guarantees.
Even though pre-allocation is tightly bound to the `initialDividendIndex`, the final quotient might have leading zeros depending on the magnitude of the divisor. The `div` function concludes by stripping any trailing zero-bytes from the little-endian vector to maintain strict `BigInt` normalization guarantees.

---

Expand Down
6 changes: 3 additions & 3 deletions src/decrypt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ std::string decrypt(keyPair& keyPair, const std::vector<uint8_t>& ciphertext) {
std::vector<uint8_t> chunk(ciphertext.begin() + i, ciphertext.begin() + i + blockSize);

// 2. Construct representation from the extracted block chunk (using 64-bit limbs)
const operations::Base256 c_num(bytesToByteArray(chunk));
const operations::BigInt c_num(bytesToByteArray(chunk));

// 3. Perform RSA mathematical operation: M = C^d mod n
operations::Base256 m_num =
operations::BigInt m_num =
modPow(c_num, keyPair.getPrivateKey().d, keyPair.getPrivateKey().n);

// 4. Retrieve the decrypted byte value and convert it back to a character
Expand All @@ -42,4 +42,4 @@ std::string decrypt(keyPair& keyPair, const std::vector<uint8_t>& ciphertext) {

return plaintext;
}
} // namespace core::decryptor
} // namespace core::decryptor
6 changes: 3 additions & 3 deletions src/encrypt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ std::vector<uint8_t> encrypt(keyPair& keyPair, const std::string& plaintext) {

for (const char c : plaintext) {
// 1. Convert the character byte to the internal 64-bit limb representation
const operations::Base256 m(static_cast<uint8_t>(c));
const operations::BigInt m(static_cast<uint8_t>(c));

// 2. Perform RSA mathematical operation: C = M^e mod n
operations::Base256 c_num = modPow(m, keyPair.getPublicKey().e, keyPair.getPublicKey().n);
operations::BigInt c_num = modPow(m, keyPair.getPublicKey().e, keyPair.getPublicKey().n);

// 3. Extract raw bytes from the computed ciphertext number (padded to target block size)
std::vector<uint8_t> c_bytes = byteArrayToBytes(c_num.getBytes(), blockSize);
Expand All @@ -30,4 +30,4 @@ std::vector<uint8_t> encrypt(keyPair& keyPair, const std::string& plaintext) {

return ciphertext;
}
} // namespace core::encryptor
} // namespace core::encryptor
4 changes: 2 additions & 2 deletions src/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <string>
#include <vector>

#include "base256.h"
#include "bigint.h"
#include "key_fwd.h"

// Converts a little-endian byte array to a 64-bit word array
Expand Down Expand Up @@ -52,4 +52,4 @@
}
}
return bytes;
}
}
42 changes: 21 additions & 21 deletions src/keyPair.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,43 +65,43 @@ std::vector<uint8_t> generateCandidateBytes() {
}

// Generates a cryptographically secure 2048-bit prime number
operations::Base256 generateSecurePrime() {
operations::BigInt generateSecurePrime() {
std::vector<uint8_t> candidateBytes = generateCandidateBytes();
// Convert 256 byte vector to Base256 representation using 64-bit limbs
operations::Base256 candidate(bytesToByteArray(candidateBytes));
// Convert 256 byte vector to BigInt representation using 64-bit limbs
operations::BigInt candidate(bytesToByteArray(candidateBytes));

// Search sequentially for the next prime using the math_utils library
while (!operations::math::isPrime(candidate)) {
candidate += operations::Base256(2);
candidate += operations::BigInt(2);
}
return candidate;
}
} // namespace

// Default Constructor: Generates a new secure 4096-bit RSA keypair
keyPair::keyPair() {
const operations::Base256 p = generateSecurePrime();
operations::Base256 q = generateSecurePrime();
const operations::BigInt p = generateSecurePrime();
operations::BigInt q = generateSecurePrime();

// Ensure p and q are not identical
while (p == q) {
q = generateSecurePrime();
}

operations::Base256 phi = (p - operations::Base256(1)) * (q - operations::Base256(1));
const operations::Base256 e(65537);
operations::BigInt phi = (p - operations::BigInt(1)) * (q - operations::BigInt(1));
const operations::BigInt e(65537);

// Ensure e and phi are coprime
while (operations::math::gcd(e, phi) != operations::Base256(1)) {
while (operations::math::gcd(e, phi) != operations::BigInt(1)) {
q = generateSecurePrime();
while (p == q) {
q = generateSecurePrime();
}
phi = (p - operations::Base256(1)) * (q - operations::Base256(1));
phi = (p - operations::BigInt(1)) * (q - operations::BigInt(1));
}

const operations::Base256 n = p * q;
const operations::Base256 d = operations::math::modInverse(e, phi);
const operations::BigInt n = p * q;
const operations::BigInt d = operations::math::modInverse(e, phi);

public_key.n = n;
public_key.e = e;
Expand All @@ -127,9 +127,9 @@ std::vector<uint8_t> PublicKey::serialize() const { return keyPair::s_serialize(

std::vector<uint8_t> PrivateKey::serialize() const { return keyPair::s_serialize(n, d); }

// Serializes two Base256 fields with Big-endian size headers
std::vector<uint8_t> keyPair::s_serialize(const operations::Base256 &first,
const operations::Base256 &second) {
// Serializes two BigInt fields with Big-endian size headers
std::vector<uint8_t> keyPair::s_serialize(const operations::BigInt &first,
const operations::BigInt &second) {
std::vector<uint8_t> serialized;

// Safely extract the raw byte stream from the 64-bit limb vectors
Expand All @@ -156,9 +156,9 @@ std::vector<uint8_t> keyPair::s_serialize(const operations::Base256 &first,
return serialized;
}

// Deserializes two Base256 fields with Big-endian size headers
bool keyPair::s_deserialize(const std::vector<uint8_t> &data, operations::Base256 &outFirst,
operations::Base256 &outSecond) {
// Deserializes two BigInt fields with Big-endian size headers
bool keyPair::s_deserialize(const std::vector<uint8_t> &data, operations::BigInt &outFirst,
operations::BigInt &outSecond) {
if (data.size() < 8) return false;

size_t index = 0;
Expand Down Expand Up @@ -189,8 +189,8 @@ bool keyPair::s_deserialize(const std::vector<uint8_t> &data, operations::Base25
std::vector<uint8_t> secondBytes(secondBegin, secondEnd);

// Convert deserialized byte streams back into 64-bit limb vectors
outFirst = operations::Base256(bytesToByteArray(firstBytes));
outSecond = operations::Base256(bytesToByteArray(secondBytes));
outFirst = operations::BigInt(bytesToByteArray(firstBytes));
outSecond = operations::BigInt(bytesToByteArray(secondBytes));

return true;
}
Expand Down Expand Up @@ -274,4 +274,4 @@ uint8_t keyPair::getBase64Index(char letter) {
}
}
return 0;
}
}
20 changes: 10 additions & 10 deletions src/keyPair.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@
#include <string>
#include <vector>

#include "base256.h"
#include "bigint.h"
#include "key_fwd.h"

#define KEY_FOLDER "rsa-keys"

enum { NONE, PUBLIC, PRIVATE, BOTH };

struct PublicKey {
operations::Base256 n;
operations::Base256 e;
operations::BigInt n;
operations::BigInt e;

[[nodiscard]] std::vector<uint8_t> serialize() const;
};

struct PrivateKey {
operations::Base256 n;
operations::Base256 d;
operations::BigInt n;
operations::BigInt d;

[[nodiscard]] std::vector<uint8_t> serialize() const;
};
Expand Down Expand Up @@ -51,15 +51,15 @@ class keyPair {
static keyPair create(const std::vector<uint8_t> &pubData,
const std::vector<uint8_t> &privData);

static std::vector<uint8_t> s_serialize(const operations::Base256 &first,
const operations::Base256 &second);
static bool s_deserialize(const std::vector<uint8_t> &data, operations::Base256 &outFirst,
operations::Base256 &outSecond);
static std::vector<uint8_t> s_serialize(const operations::BigInt &first,
const operations::BigInt &second);
static bool s_deserialize(const std::vector<uint8_t> &data, operations::BigInt &outFirst,
operations::BigInt &outSecond);

// Base64 helper functions
static std::string base64Encode(const std::vector<uint8_t> &data);
static std::vector<uint8_t> base64Decode(std::string data);
static uint8_t getBase64Index(char letter);
};

#endif
#endif
Loading