Commit a3e2a85c authored by jan.koester's avatar jan.koester
Browse files

start ptimizing

parent 3293b0db
Loading
Loading
Loading
Loading
+299 −542

File changed.

Preview size limit exceeded, changes collapsed.

+37 −54
Original line number Diff line number Diff line
@@ -26,86 +26,69 @@
 *******************************************************************************/

#pragma once

#include <vector>
#include <stdexcept>
#include <cstdint>
#include <stdexcept>

namespace netplus {

// Type aliases for clarity (AES operates on 128-bit blocks/keys)
// Keep your existing aliases
using block128 = std::vector<uint8_t>;
using key128   = std::vector<uint8_t>;

// --- Global AES Tables (Defined in the header for easy access) ---
// Note: You must fill these arrays with the correct 256-byte values.
// Global tables (provided in aes.cpp)
extern const uint8_t S_BOX[256];
extern const uint8_t INV_S_BOX[256];
extern const uint8_t RCON[10]; // Rcon values for key expansion (only 10 needed for AES-128)
extern const uint8_t RCON[10];

class aes {
private:
    // Stores the expanded round keys (11 keys * 16 bytes = 176 bytes for AES-128)
    std::vector<block128> m_roundKeys;

    // --- Core AES Functions ---

    // Key Expansion and related helpers
    // ----------------------------------------------------------------
    // OPTIMIZED ROUND KEY STORAGE:
    // 11 round keys * 16 bytes = 176 bytes (AES-128)
    // Avoids 11 heap allocations that vector<block128> causes.
    // ----------------------------------------------------------------
    std::vector<uint8_t> m_roundKeyBytes; // size = 176

    // access helper: returns pointer to 16-byte round key
    inline const uint8_t* rk(int round) const {
        return &m_roundKeyBytes[size_t(round) * 16];
    }

    // --- Key Expansion + helpers ---
    void keyExpansion(const key128& key);
    static uint32_t subWord(uint32_t word);
    static uint32_t rotWord(uint32_t word);

    // Round operations
    void subBytes(block128& state);
    void shiftRows(block128& state);
    void mixColumns(block128& state);
    void addRoundKey(block128& state, const block128& roundKey);
    // --- Round ops ---
    static void subBytes(uint8_t* state);
    static void shiftRows(uint8_t* state);
    static void mixColumns(uint8_t* state);
    static void addRoundKey(uint8_t* state, const uint8_t* roundKey);

    // Inverse Round operations
    void invSubBytes(block128& state);
    void invShiftRows(block128& state);
    void invMixColumns(block128& state);
    // --- Inverse ops ---
    static void invSubBytes(uint8_t* state);
    static void invShiftRows(uint8_t* state);
    static void invMixColumns(uint8_t* state);

    // Helper function for Galois Field multiplication in mixColumns
    // GF multiplication
    static uint8_t gmul(uint8_t a, uint8_t b);

    friend void aes_self_check();

public:
    /**
     * @brief Constructor for the aes class (AES-128). Performs key expansion.
     * @param key The 128-bit master key (16 bytes).
     */
    explicit aes(const key128& key);

    /**
     * @brief Encrypts a 128-bit block of plaintext.
     * @param plaintext The 16-byte input block.
     * @return The 16-byte ciphertext block.
     */
    // NOTE: Keeping your vector-based API, but avoids realloc/extra copies.
    block128 encrypt(const block128& plaintext);

    /**
     * @brief Decrypts a 128-bit block of ciphertext.
     * @param ciphertext The 16-byte input block.
     * @return The 16-byte plaintext block.
     */
    block128 decrypt(const block128& ciphertext);

        /**
     * encryptCBC
     * @param plaintext: The raw data to encrypt
     * @param iv: 16-byte Initialization Vector
     * @return: Encrypted ciphertext (length will be multiple of 16)
     */
    std::vector<uint8_t> encryptCBC(const std::vector<uint8_t>& plaintext, const std::vector<uint8_t>& iv);

    /**
     * decryptCBC
     * @param ciphertext: The encrypted data
     * @param iv: 16-byte Initialization Vector
     * @return: Decrypted and unpadded plaintext
     */
    std::vector<uint8_t> decryptCBC(const std::vector<uint8_t>& ciphertext, const std::vector<uint8_t>& iv);
    // TLS CBC helpers
    std::vector<uint8_t> encryptCBC(const std::vector<uint8_t>& plaintext,
                                    const std::vector<uint8_t>& iv);

    std::vector<uint8_t> decryptCBC(const std::vector<uint8_t>& ciphertext,
                                    const std::vector<uint8_t>& iv);
};

} // namespace netplus
+93 −23
Original line number Diff line number Diff line
@@ -27,9 +27,9 @@
#include <iomanip>
#include <algorithm>
#include <stdexcept>
#include <random>
#include <sstream>

#include "random.h"
#include "rsa.h"

namespace netplus {
@@ -432,19 +432,26 @@ namespace netplus {
    }

    void netplus::rsa::generateSecureRandom(bigInt& n, size_t bits) {

        size_t words = (bits + 31) / 32;
        n.reserve(words);

        std::random_device rd;
        for (size_t i = 0; i < words; ++i) {
            n.data[i] = rd();
        }
        n.reserve(words);
        n.used = words;
        // Ensure the top bit is set for the requested bit-length

        fillRandomBytes(reinterpret_cast<uint8_t*>(n.data.get()),
                        words * sizeof(uint32_t));

        n.data[words - 1] |= (1U << ((bits - 1) % 32));

        uint32_t excess = (uint32_t)(words * 32 - bits);
        if (excess > 0) {
            uint32_t mask = 0xFFFFFFFFu >> excess;
            n.data[words - 1] &= mask;
            n.data[words - 1] |= (1U << ((bits - 1) % 32));
        // Ensure it's odd for primality testing
        n.data[0] |= 1;
        }
        n.data[0] |= 1U;
    }


    rsa::bigInt rsa::gcd(bigInt a, bigInt b) {
        while (!b.isZero()) {
@@ -507,17 +514,79 @@ namespace netplus {
    }

    bool rsa::isProbablyPrime(const bigInt& n, int k) {
        // Correctly initialize constants using the (value, capacity) constructor
        bigInt one(1U, 1);
        bigInt two(2U, 1);
        bigInt one(1U, n.capacity);
        bigInt two(2U, n.capacity);
        bigInt three(3U, n.capacity);

        // nm1 = n - 1
        bigInt nm1(n.capacity);
        subtract(n, one, nm1);

        // Initial checks
        // trivial checks
        if (compare(n, one) <= 0) return false;
        if (n.isEven()) return compare(n, two) == 0;

        // Find d and s such that n - 1 = 2^s * d
        // ------------------------------------------------------------
        // Lambda: randomBigIntBits(out,bits)
        // ------------------------------------------------------------
        auto randomBigIntBits = [&](bigInt& out, size_t bits) {
            size_t words = (bits + 31) / 32;
            out.reserve(words);
            out.used = words;

            // fill random words
            for (size_t i = 0; i < words; ++i) {
                fillRandomBytes(reinterpret_cast<uint8_t*>(&out.data[i]),
                                sizeof(uint32_t));
            }

            // mask unused high bits
            size_t extra = words * 32 - bits;
            if (extra > 0) {
                uint32_t mask = 0xFFFFFFFFu >> extra;
                out.data[words - 1] &= mask;
            }

            // optional normalize if you have it:
            // out.normalize();
        };

        // ------------------------------------------------------------
        // Lambda: randomBelow(limit)   -> uniform r in [0..limit-1]
        // ------------------------------------------------------------
        auto randomBelow = [&](const bigInt& limit) -> bigInt {
            size_t bits = limit.bitLength();
            bigInt r(limit.capacity);

            for (;;) {
                randomBigIntBits(r, bits);

                if (compare(r, limit) < 0)
                    return r;
            }
        };

        // ------------------------------------------------------------
        // Lambda: randomWitnessA(n) -> uniform a in [2..n-2]
        // ------------------------------------------------------------
        auto randomWitnessA = [&]() -> bigInt {

            // nMinusThree = n - 3
            bigInt nMinusThree(n.capacity);
            subtract(n, three, nMinusThree);   // n-3

            // r ∈ [0..n-4]
            bigInt r = randomBelow(nMinusThree);

            // a = r + 2  => [2..n-2]
            bigInt a(n.capacity);
            add(r, two, a);
            return a;
        };

        // ------------------------------------------------------------
        // factor n-1 = 2^s * d
        // ------------------------------------------------------------
        bigInt d = nm1;
        size_t s = 0;
        while (d.isEven()) {
@@ -525,32 +594,33 @@ namespace netplus {
            s++;
        }

        // ------------------------------------------------------------
        // Miller-Rabin rounds
        std::random_device rd;
        std::mt19937 gen(rd());

        // ------------------------------------------------------------
        for (int i = 0; i < k; i++) {
            // Simplified witness: for production RSA, 'a' should be a random
            // value in range [2, n-2]. For now, using small primes as witnesses:
            uint32_t witness_val = (i == 0) ? 2 : (i == 1 ? 3 : 5 + (i * 2));
            bigInt a(witness_val, n.capacity);

            bigInt a = randomWitnessA();

            bigInt x = modPow(a, d, n);

            // if x == 1 or x == n - 1
            // x == 1 or x == n-1
            if ((x.used == 1 && x.data[0] == 1) || compare(x, nm1) == 0)
                continue;

            bool composite = true;

            for (size_t r = 1; r < s; r++) {
                x = modPow(x, two, n); // Square: x = x^2 % n
                x = modPow(x, two, n);

                if (compare(x, nm1) == 0) {
                    composite = false;
                    break;
                }
            }

            if (composite) return false;
        }

        return true;
    }

+49 −46
Original line number Diff line number Diff line
@@ -265,67 +265,72 @@ namespace netplus {
            if (!c->csock) return;

            try {
                // ----------------------------
                // 1) TLS handshake stage
                // ----------------------------
                if (!c->csock->getHandshakeDone()) {
                // Peer already closed?
                if (events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR)) {
                    rearm.disarm();
                    CloseEventHandler(fd, tid, args);
                    return;
                }

                // -------------------------------------------------
                // 1) TLS handshake
                // -------------------------------------------------
                if (!c->csock->getHandshakeDone()) {
                    c->csock->handshake_after_accept();

                    // try flush once if something queued
                    if (c->csock->hasPendingWrite()) {
                        try {
                            c->csock->flush_out();
                        } catch (NetException& e) {
                            if (e.getErrorType() != NetException::Note)
                                throw;
                            if (e.getErrorType() == NetException::Note)
                                return; // wait EPOLLOUT
                            throw;
                        }
                    }

                    // if still not done, stop here
                    // still not done -> wait for next IO event
                    if (!c->csock->getHandshakeDone())
                        return;
                }

                // ----------------------------
                // 2) EPOLLIN: receive application data
                // ----------------------------
                // -------------------------------------------------
                // 2) EPOLLIN: receive one chunk
                // -------------------------------------------------
                if (events & EPOLLIN) {
                    bool got = false;

                    for (;;) {
                    buffer buf(BLOCKSIZE);
                    size_t rcv = 0;

                    try {
                        rcv = c->csock->recvData(buf, 0);
                    } catch (NetException& e) {
                            if (e.getErrorType() == NetException::Note)
                                break;
                        if (e.getErrorType() == NetException::Note) {
                            // nothing to read right now
                            rcv = 0;
                        } else {
                            throw;
                        }
                    }

                    if (rcv == 0) {
                        // If peer closed => recvData must return 0.
                        // Note case already handled.
                        // In TLS, alert/EOF => close.
                        rearm.disarm();
                        CloseEventHandler(fd, tid, args);
                        return;
                    }

                    c->RecvData.append(buf.data.buf, rcv);
                        got = true;
                    }

                    if (got && !c->RecvData.empty()) {
                    evconnection->RequestEvent(*c, tid, args);
                }
                }

                // ----------------------------
                // 3) EPOLLOUT: flush + send queued responses
                // ----------------------------
                // -------------------------------------------------
                // 3) EPOLLOUT: flush + send one chunk
                // -------------------------------------------------
                if (events & EPOLLOUT) {

                    // always flush TLS pending first
                    // flush pending TLS output
                    if (c->csock->hasPendingWrite()) {
                        try {
                            c->csock->flush_out();
@@ -336,8 +341,8 @@ namespace netplus {
                        }
                    }

                    // now send queued app data
                    while (!c->SendData.empty()) {
                    // send exactly one chunk from SendData
                    if (!c->SendData.empty()) {
                        size_t sendlen = std::min((size_t)BLOCKSIZE, c->SendData.size());
                        buffer out(c->SendData.data(), sendlen);

@@ -351,25 +356,23 @@ namespace netplus {

                        } catch (NetException& e) {
                            if (e.getErrorType() == NetException::Note)
                                break;
                                return;
                            throw;
                        }

                        if (consumed == 0)
                            break;

                        c->SendData.erase(c->SendData.begin(),
                                        c->SendData.begin() + consumed);
                        if (consumed > 0) {
                            c->SendData.erase(c->SendData.begin(), c->SendData.begin() + consumed);
                        }
                    }

                    // if nothing pending, signal response done
                    if (c->SendData.empty() && !c->csock->hasPendingWrite()) {
                        evconnection->ResponseEvent(*c, tid, args);
                    }
                }

            } catch (NetException& e) {
                if (e.getErrorType() == NetException::Note) return;
                if (e.getErrorType() == NetException::Note)
                    return;

                rearm.disarm();
                CloseEventHandler(fd, tid, args);
+1 −2
Original line number Diff line number Diff line
@@ -10,6 +10,5 @@ namespace netplus {
    inline void fillRandom(std::vector<uint8_t>& v) {
        if (!v.empty()) fillRandomBytes(v.data(), v.size());
    }

}
};