65 lines
1.2 KiB
C++
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;
|
|
}
|