Commit 422eddce authored by jan.koester's avatar jan.koester
Browse files

test

parent a66e3cae
Loading
Loading
Loading
Loading
+88 −92
Original line number Diff line number Diff line
@@ -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

@@ -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()) {
@@ -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);
@@ -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


+5 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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());
+4 −14
Original line number Diff line number Diff line
@@ -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();
@@ -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();