2025-09-06 18:48:40 -05:00

65 lines
1.2 KiB
C++

// Copyright (C) 2007-2025 EQ2EMulator
// Licensed under GPL v3
#include "rc4.h"
#include <algorithm>
#include <cstring>
#include <numeric>
static constexpr std::array<uchar, 256> get_init_state() noexcept
{
std::array<uchar, 256> state{};
std::iota(state.begin(), state.end(), 0);
return state;
}
static const auto g_init_state = get_init_state();
RC4::RC4(int64 key) noexcept
{
Init(key);
}
void RC4::Init(int64 key) noexcept
{
m_state = g_init_state;
m_x = 0;
m_y = 0;
ulong key_index = 0;
ulong state_index = 0;
const auto* key_ptr = reinterpret_cast<const uchar*>(&key);
for (int16 i = 0; i < 256; ++i) {
const ulong temp = m_state[i];
state_index += key_ptr[key_index] + temp;
state_index &= 0xFF;
m_state[i] = m_state[state_index];
m_state[state_index] = static_cast<uchar>(temp);
key_index++;
key_index &= 7;
}
}
void RC4::Cypher(uchar* data, int32 length) noexcept
{
uchar key1 = m_x;
uchar key2 = m_y;
for (int32 i = 0; i < length; ++i) {
++key1;
const uchar key_val1 = m_state[key1];
key2 += key_val1;
const uchar key_val2 = m_state[key2];
m_state[key1] = key_val2;
m_state[key2] = key_val1;
data[i] ^= m_state[(key_val1 + key_val2) & 0xFF];
}
m_x = key1;
m_y = key2;
}