Loading src/crypto/rsa.cpp +88 −92 Original line number Diff line number Diff line Loading @@ -61,6 +61,41 @@ namespace netplus { other.capacity = 0; } // Assignment from buffer rsa(const std::vector<uint8_t>& buffer) { if (buffer.empty()) { throw std::runtime_error("Buffer is empty"); } if (!parseDERAndLoadRSA(buffer, *this)) { throw std::runtime_error("Failed to parse RSA key from DER buffer"); } } // Assignment from filepath rsa(const std::string& filepath) { std::ifstream file(filepath, std::ios::binary | std::ios::ate); if (!file.is_open()) { throw std::runtime_error("Cannot open file: " + filepath); } std::streamsize fileSize = file.tellg(); if (fileSize <= 0) { throw std::runtime_error("File is empty: " + filepath); } file.seekg(0, std::ios::beg); std::vector<uint8_t> derData(static_cast<size_t>(fileSize)); if (!file.read(reinterpret_cast<char*>(derData.data()), fileSize)) { throw std::runtime_error("Failed to read file: " + filepath); } if (!parseDERAndLoadRSA(derData, *this)) { throw std::runtime_error("Failed to parse RSA key from file: " + filepath); } } netplus::rsa::bigInt& netplus::rsa::bigInt::operator=(const bigInt& other) { if (this == &other) return *this; // Self-assignment check Loading Loading @@ -262,6 +297,59 @@ namespace netplus { return *this; } // Helper function to parse a DER length field static bool parseDERLength(const uint8_t* data, size_t maxLen, size_t& outLength, size_t& outBytesRead) { if (maxLen < 1) return false; outLength = data[0]; outBytesRead = 1; // Long form if (outLength & 0x80) { int numOctets = static_cast<int>(outLength & 0x7F); if (numOctets <= 0 || numOctets > 4) return false; if (maxLen < 1 + static_cast<size_t>(numOctets)) return false; outLength = 0; for (int i = 0; i < numOctets; ++i) { outLength = (outLength << 8) | data[1 + i]; } outBytesRead = 1 + numOctets; } return true; } // Helper function to parse a DER INTEGER static bool parseDERInteger(const uint8_t* data, size_t maxLen, std::vector<uint8_t>& outBytes, size_t& outBytesRead) { if (maxLen < 2 || data[0] != 0x02) { // 0x02 = INTEGER tag return false; } size_t length = 0; size_t lenBytesRead = 0; if (!parseDERLength(data + 1, maxLen - 1, length, lenBytesRead)) { return false; } if (1 + lenBytesRead + length > maxLen) { return false; } const uint8_t* intData = data + 1 + lenBytesRead; outBytes.clear(); // Skip leading zero byte if present (DER encoding convention for non-negative integers) if (length > 0 && intData[0] == 0x00) { outBytes.assign(intData + 1, intData + length); } else { outBytes.assign(intData, intData + length); } outBytesRead = 1 + lenBytesRead + length; return true; } // Helper function to parse DER data and load RSA key static bool parseDERAndLoadRSA(const std::vector<uint8_t>& derData, netplus::rsa& out_rsa) { if (derData.empty()) { Loading Loading @@ -358,45 +446,6 @@ namespace netplus { return false; } // Assignment from buffer rsa& rsa::operator=(const std::vector<uint8_t>& buffer) { if (buffer.empty()) { throw std::runtime_error("Buffer is empty"); } if (!parseDERAndLoadRSA(buffer, *this)) { throw std::runtime_error("Failed to parse RSA key from DER buffer"); } return *this; } // Assignment from filepath rsa& rsa::operator=(const std::string& filepath) { std::ifstream file(filepath, std::ios::binary | std::ios::ate); if (!file.is_open()) { throw std::runtime_error("Cannot open file: " + filepath); } std::streamsize fileSize = file.tellg(); if (fileSize <= 0) { throw std::runtime_error("File is empty: " + filepath); } file.seekg(0, std::ios::beg); std::vector<uint8_t> derData(static_cast<size_t>(fileSize)); if (!file.read(reinterpret_cast<char*>(derData.data()), fileSize)) { throw std::runtime_error("Failed to read file: " + filepath); } if (!parseDERAndLoadRSA(derData, *this)) { throw std::runtime_error("Failed to parse RSA key from file: " + filepath); } return *this; } // R = 2^(32*nwords), so R2 = R*R mod N rsa::bigInt rsa::calculateR2Mod(const bigInt& mod) { bigInt r(mod.used * 4 + 2); Loading Loading @@ -1055,59 +1104,6 @@ namespace netplus { return out; } // Helper function to parse a DER length field static bool parseDERLength(const uint8_t* data, size_t maxLen, size_t& outLength, size_t& outBytesRead) { if (maxLen < 1) return false; outLength = data[0]; outBytesRead = 1; // Long form if (outLength & 0x80) { int numOctets = static_cast<int>(outLength & 0x7F); if (numOctets <= 0 || numOctets > 4) return false; if (maxLen < 1 + static_cast<size_t>(numOctets)) return false; outLength = 0; for (int i = 0; i < numOctets; ++i) { outLength = (outLength << 8) | data[1 + i]; } outBytesRead = 1 + numOctets; } return true; } // Helper function to parse a DER INTEGER static bool parseDERInteger(const uint8_t* data, size_t maxLen, std::vector<uint8_t>& outBytes, size_t& outBytesRead) { if (maxLen < 2 || data[0] != 0x02) { // 0x02 = INTEGER tag return false; } size_t length = 0; size_t lenBytesRead = 0; if (!parseDERLength(data + 1, maxLen - 1, length, lenBytesRead)) { return false; } if (1 + lenBytesRead + length > maxLen) { return false; } const uint8_t* intData = data + 1 + lenBytesRead; outBytes.clear(); // Skip leading zero byte if present (DER encoding convention for non-negative integers) if (length > 0 && intData[0] == 0x00) { outBytes.assign(intData + 1, intData + length); } else { outBytes.assign(intData, intData + length); } outBytesRead = 1 + lenBytesRead + length; return true; } // Static function to load RSA key from DER-encoded data Loading src/crypto/rsa.h +5 −2 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ namespace netplus { netplus::rsa::bigInt& operator=(const bigInt& other); netplus::rsa::bigInt& operator=(bigInt&& other) noexcept; netplus::rsa::bigInt& operator=(const rsa& src); // Helper to check bit state for modPow bool isBitSet(size_t bit) const; Loading @@ -84,10 +85,12 @@ namespace netplus { rsa(); rsa(const rsa& src); rsa(rsa&& src) noexcept; rsa (const std::string& filepath); rsa(const std::vector<uint8_t>& buffer); rsa& operator=(const rsa& src); rsa& operator=(rsa&& src) noexcept; rsa& operator=(const std::string& filepath); rsa& operator=(const std::vector<uint8_t>& buffer); explicit operator bool() const { return !(n.isZero() || d.isZero()); Loading test/https_test.cpp +4 −14 Original line number Diff line number Diff line Loading @@ -111,14 +111,9 @@ int main() { netplus::ssl::CertificateBundle bundle1; bundle1.cert = cert; bundle1.privateKeyDer = std::vector<uint8_t>(test_key_der.begin(), test_key_der.end()); // Pre-load RSA key into bundle using temporary file // Pre-load RSA key into bundle using vector-based constructor try { std::string temp_key1 = "/tmp/test_key1.der"; std::ofstream temp_file1(temp_key1, std::ios::binary); temp_file1.write(reinterpret_cast<const char*>(bundle1.privateKeyDer.data()), bundle1.privateKeyDer.size()); temp_file1.close(); bundle1.rsa_key = temp_key1; std::remove(temp_key1.c_str()); bundle1.rsa_key = netplus::rsa(bundle1.privateKeyDer); } catch (const std::exception& e) { std::cerr << "Failed to load RSA key 1: " << e.what() << std::endl; std::cerr.flush(); Loading @@ -131,14 +126,9 @@ int main() { netplus::ssl::CertificateBundle bundle2; bundle2.cert = cert2; bundle2.privateKeyDer = std::vector<uint8_t>(test2_key_der.begin(), test2_key_der.end()); // Pre-load RSA key into bundle using temporary file // Pre-load RSA key into bundle using vector-based constructor try { std::string temp_key2 = "/tmp/test_key2.der"; std::ofstream temp_file2(temp_key2, std::ios::binary); temp_file2.write(reinterpret_cast<const char*>(bundle2.privateKeyDer.data()), bundle2.privateKeyDer.size()); temp_file2.close(); bundle2.rsa_key = temp_key2; std::remove(temp_key2.c_str()); bundle2.rsa_key = netplus::rsa(bundle2.privateKeyDer); } catch (const std::exception& e) { std::cerr << "Failed to load RSA key 2: " << e.what() << std::endl; std::cerr.flush(); Loading Loading
src/crypto/rsa.cpp +88 −92 Original line number Diff line number Diff line Loading @@ -61,6 +61,41 @@ namespace netplus { other.capacity = 0; } // Assignment from buffer rsa(const std::vector<uint8_t>& buffer) { if (buffer.empty()) { throw std::runtime_error("Buffer is empty"); } if (!parseDERAndLoadRSA(buffer, *this)) { throw std::runtime_error("Failed to parse RSA key from DER buffer"); } } // Assignment from filepath rsa(const std::string& filepath) { std::ifstream file(filepath, std::ios::binary | std::ios::ate); if (!file.is_open()) { throw std::runtime_error("Cannot open file: " + filepath); } std::streamsize fileSize = file.tellg(); if (fileSize <= 0) { throw std::runtime_error("File is empty: " + filepath); } file.seekg(0, std::ios::beg); std::vector<uint8_t> derData(static_cast<size_t>(fileSize)); if (!file.read(reinterpret_cast<char*>(derData.data()), fileSize)) { throw std::runtime_error("Failed to read file: " + filepath); } if (!parseDERAndLoadRSA(derData, *this)) { throw std::runtime_error("Failed to parse RSA key from file: " + filepath); } } netplus::rsa::bigInt& netplus::rsa::bigInt::operator=(const bigInt& other) { if (this == &other) return *this; // Self-assignment check Loading Loading @@ -262,6 +297,59 @@ namespace netplus { return *this; } // Helper function to parse a DER length field static bool parseDERLength(const uint8_t* data, size_t maxLen, size_t& outLength, size_t& outBytesRead) { if (maxLen < 1) return false; outLength = data[0]; outBytesRead = 1; // Long form if (outLength & 0x80) { int numOctets = static_cast<int>(outLength & 0x7F); if (numOctets <= 0 || numOctets > 4) return false; if (maxLen < 1 + static_cast<size_t>(numOctets)) return false; outLength = 0; for (int i = 0; i < numOctets; ++i) { outLength = (outLength << 8) | data[1 + i]; } outBytesRead = 1 + numOctets; } return true; } // Helper function to parse a DER INTEGER static bool parseDERInteger(const uint8_t* data, size_t maxLen, std::vector<uint8_t>& outBytes, size_t& outBytesRead) { if (maxLen < 2 || data[0] != 0x02) { // 0x02 = INTEGER tag return false; } size_t length = 0; size_t lenBytesRead = 0; if (!parseDERLength(data + 1, maxLen - 1, length, lenBytesRead)) { return false; } if (1 + lenBytesRead + length > maxLen) { return false; } const uint8_t* intData = data + 1 + lenBytesRead; outBytes.clear(); // Skip leading zero byte if present (DER encoding convention for non-negative integers) if (length > 0 && intData[0] == 0x00) { outBytes.assign(intData + 1, intData + length); } else { outBytes.assign(intData, intData + length); } outBytesRead = 1 + lenBytesRead + length; return true; } // Helper function to parse DER data and load RSA key static bool parseDERAndLoadRSA(const std::vector<uint8_t>& derData, netplus::rsa& out_rsa) { if (derData.empty()) { Loading Loading @@ -358,45 +446,6 @@ namespace netplus { return false; } // Assignment from buffer rsa& rsa::operator=(const std::vector<uint8_t>& buffer) { if (buffer.empty()) { throw std::runtime_error("Buffer is empty"); } if (!parseDERAndLoadRSA(buffer, *this)) { throw std::runtime_error("Failed to parse RSA key from DER buffer"); } return *this; } // Assignment from filepath rsa& rsa::operator=(const std::string& filepath) { std::ifstream file(filepath, std::ios::binary | std::ios::ate); if (!file.is_open()) { throw std::runtime_error("Cannot open file: " + filepath); } std::streamsize fileSize = file.tellg(); if (fileSize <= 0) { throw std::runtime_error("File is empty: " + filepath); } file.seekg(0, std::ios::beg); std::vector<uint8_t> derData(static_cast<size_t>(fileSize)); if (!file.read(reinterpret_cast<char*>(derData.data()), fileSize)) { throw std::runtime_error("Failed to read file: " + filepath); } if (!parseDERAndLoadRSA(derData, *this)) { throw std::runtime_error("Failed to parse RSA key from file: " + filepath); } return *this; } // R = 2^(32*nwords), so R2 = R*R mod N rsa::bigInt rsa::calculateR2Mod(const bigInt& mod) { bigInt r(mod.used * 4 + 2); Loading Loading @@ -1055,59 +1104,6 @@ namespace netplus { return out; } // Helper function to parse a DER length field static bool parseDERLength(const uint8_t* data, size_t maxLen, size_t& outLength, size_t& outBytesRead) { if (maxLen < 1) return false; outLength = data[0]; outBytesRead = 1; // Long form if (outLength & 0x80) { int numOctets = static_cast<int>(outLength & 0x7F); if (numOctets <= 0 || numOctets > 4) return false; if (maxLen < 1 + static_cast<size_t>(numOctets)) return false; outLength = 0; for (int i = 0; i < numOctets; ++i) { outLength = (outLength << 8) | data[1 + i]; } outBytesRead = 1 + numOctets; } return true; } // Helper function to parse a DER INTEGER static bool parseDERInteger(const uint8_t* data, size_t maxLen, std::vector<uint8_t>& outBytes, size_t& outBytesRead) { if (maxLen < 2 || data[0] != 0x02) { // 0x02 = INTEGER tag return false; } size_t length = 0; size_t lenBytesRead = 0; if (!parseDERLength(data + 1, maxLen - 1, length, lenBytesRead)) { return false; } if (1 + lenBytesRead + length > maxLen) { return false; } const uint8_t* intData = data + 1 + lenBytesRead; outBytes.clear(); // Skip leading zero byte if present (DER encoding convention for non-negative integers) if (length > 0 && intData[0] == 0x00) { outBytes.assign(intData + 1, intData + length); } else { outBytes.assign(intData, intData + length); } outBytesRead = 1 + lenBytesRead + length; return true; } // Static function to load RSA key from DER-encoded data Loading
src/crypto/rsa.h +5 −2 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ namespace netplus { netplus::rsa::bigInt& operator=(const bigInt& other); netplus::rsa::bigInt& operator=(bigInt&& other) noexcept; netplus::rsa::bigInt& operator=(const rsa& src); // Helper to check bit state for modPow bool isBitSet(size_t bit) const; Loading @@ -84,10 +85,12 @@ namespace netplus { rsa(); rsa(const rsa& src); rsa(rsa&& src) noexcept; rsa (const std::string& filepath); rsa(const std::vector<uint8_t>& buffer); rsa& operator=(const rsa& src); rsa& operator=(rsa&& src) noexcept; rsa& operator=(const std::string& filepath); rsa& operator=(const std::vector<uint8_t>& buffer); explicit operator bool() const { return !(n.isZero() || d.isZero()); Loading
test/https_test.cpp +4 −14 Original line number Diff line number Diff line Loading @@ -111,14 +111,9 @@ int main() { netplus::ssl::CertificateBundle bundle1; bundle1.cert = cert; bundle1.privateKeyDer = std::vector<uint8_t>(test_key_der.begin(), test_key_der.end()); // Pre-load RSA key into bundle using temporary file // Pre-load RSA key into bundle using vector-based constructor try { std::string temp_key1 = "/tmp/test_key1.der"; std::ofstream temp_file1(temp_key1, std::ios::binary); temp_file1.write(reinterpret_cast<const char*>(bundle1.privateKeyDer.data()), bundle1.privateKeyDer.size()); temp_file1.close(); bundle1.rsa_key = temp_key1; std::remove(temp_key1.c_str()); bundle1.rsa_key = netplus::rsa(bundle1.privateKeyDer); } catch (const std::exception& e) { std::cerr << "Failed to load RSA key 1: " << e.what() << std::endl; std::cerr.flush(); Loading @@ -131,14 +126,9 @@ int main() { netplus::ssl::CertificateBundle bundle2; bundle2.cert = cert2; bundle2.privateKeyDer = std::vector<uint8_t>(test2_key_der.begin(), test2_key_der.end()); // Pre-load RSA key into bundle using temporary file // Pre-load RSA key into bundle using vector-based constructor try { std::string temp_key2 = "/tmp/test_key2.der"; std::ofstream temp_file2(temp_key2, std::ios::binary); temp_file2.write(reinterpret_cast<const char*>(bundle2.privateKeyDer.data()), bundle2.privateKeyDer.size()); temp_file2.close(); bundle2.rsa_key = temp_key2; std::remove(temp_key2.c_str()); bundle2.rsa_key = netplus::rsa(bundle2.privateKeyDer); } catch (const std::exception& e) { std::cerr << "Failed to load RSA key 2: " << e.what() << std::endl; std::cerr.flush(); Loading