Files
chaos/Chaos/Cipher/Stream/Arc4/Arc4Gen.hpp
T
hashlag 16385e93e0
Chaos Ci / test (push) Successful in 3m5s
Chaos Ci / benchmark (push) Successful in 1m25s
Arc4Gen: store the lookup table in SeArray.
2026-09-21 00:17:48 +03:00

120 lines
2.4 KiB
C++

#ifndef CHAOS_CIPHER_STREAM_ARC4_ARC4GEN_HPP
#define CHAOS_CIPHER_STREAM_ARC4_ARC4GEN_HPP
#include <cstdint>
#include <vector>
#include <utility>
#include "Service/ChaosException.hpp"
#include "Service/SeArray.hpp"
namespace Chaos::Cipher::Stream::Arc4
{
class Arc4Gen
{
public:
Arc4Gen()
: IsInitialized_(false)
{ }
template<typename InputIt>
Arc4Gen(InputIt keyBegin, InputIt keyEnd)
{
RekeyImpl(keyBegin, keyEnd);
}
template<typename InputIt>
void Rekey(InputIt keyBegin, InputIt keyEnd)
{
RekeyImpl(keyBegin, keyEnd);
}
template<typename OutputIt>
void Generate(OutputIt out, uint64_t bytesCount)
{
EnsureInitialized();
for (uint64_t cnt = 0; cnt < bytesCount; ++cnt)
{
Step(1);
*out++ = Lookup_[static_cast<uint8_t>(Lookup_[I_] + Lookup_[J_])];
}
}
void Drop(uint64_t bytesCount)
{
EnsureInitialized();
Step(bytesCount);
}
bool IsInitialized() const noexcept
{
return IsInitialized_;
}
private:
Service::SeArray<uint8_t, 256> Lookup_;
uint8_t I_;
uint8_t J_;
bool IsInitialized_;
void EnsureInitialized() const
{
if (!IsInitialized_)
{
throw Service::ChaosException("Arc4Gen: not initialized");
}
}
template<typename InputIt>
void RekeyImpl(InputIt keyBegin, InputIt keyEnd)
{
IsInitialized_ = false;
I_ = 0;
J_ = 0;
for (uint64_t idx = 0; idx < Lookup_.Size(); ++idx)
{
Lookup_[idx] = static_cast<uint8_t>(idx);
}
std::vector<uint8_t> key(keyBegin, keyEnd);
if (key.size() < 5)
{
throw Service::ChaosException("Arc4Gen: key is too small");
}
uint8_t a = 0;
uint8_t b = 0;
for (uint64_t idx = 0; idx < Lookup_.Size(); ++idx)
{
a = static_cast<uint8_t>(idx);
b = b + Lookup_[a] + key[a % key.size()];
std::swap(Lookup_[a], Lookup_[b]);
}
IsInitialized_ = true;
}
void Step(uint64_t stepsCount)
{
for (uint64_t k = 0; k < stepsCount; ++k)
{
I_ = I_ + 1;
J_ = J_ + Lookup_[I_];
std::swap(Lookup_[I_], Lookup_[J_]);
}
}
};
} // namespace Chaos::Cipher::Stream::Arc4
#endif // CHAOS_CIPHER_STREAM_ARC4_ARC4GEN_HPP