// Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net) - GPL v3 License #pragma once #include #include #include // RC4 stream cipher implementation for cryptographic operations class RC4 { public: // Initialize RC4 cipher with 64-bit key value RC4(std::int64_t key) { if (!init_state_initialized) { for (std::int16_t i = 0; i < 256; i++) init_state[i] = static_cast(i); init_state_initialized = true; } Init(key); } // Destructor - cleanup cipher state ~RC4() = default; // Initialize or reinitialize cipher with new key void Init(std::int64_t key) { // Copy initial state array to working state std::memcpy(state.data(), init_state.data(), 256); x = 0; y = 0; // Key scheduling algorithm (KSA) std::uint32_t key_index = 0; std::uint32_t state_index = 0; auto* key_bytes = reinterpret_cast(&key); for (std::int16_t i = 0; i < 256; i++) { std::uint32_t temp = state[i]; state_index += key_bytes[key_index] + temp; state_index &= 0xFF; state[i] = state[state_index]; state[state_index] = static_cast(temp); key_index++; key_index &= 7; // Wrap around 8-byte key } } // Encrypt/decrypt data buffer using RC4 stream cipher // RC4 is symmetric - same operation for encrypt and decrypt void Cypher(std::uint8_t* buffer, std::int32_t length) { std::int32_t offset = 0; std::uint8_t key1 = x; std::uint8_t key2 = y; if (length > 0) { do { // Pseudo-random generation algorithm (PRGA) key1++; std::uint8_t key_val1 = state[key1]; key2 += key_val1; std::uint8_t key_val2 = state[key2]; // Swap state values state[key1] = key_val2; state[key2] = key_val1; // XOR buffer byte with keystream byte buffer[offset++] ^= state[(key_val1 + key_val2) & 0xFF]; } while (offset < length); } // Update cipher state x = key1; y = key2; } private: std::array state; // RC4 internal state array std::uint8_t x; // First state index std::uint8_t y; // Second state index // Static initialization state shared across all instances static inline bool init_state_initialized = false; static inline std::array init_state; };