Move Arc4 to the new Cipher/Stream subdirectory.
Chaos Ci / test (push) Successful in 3m8s
Chaos Ci / benchmark (push) Successful in 1m27s

This commit is contained in:
hashlag committed 2026-09-13 17:38:51 +03:00
1 parent c51a22646f
commit d0b8cbe2ef
5 files changed
+16 -16

No files matched your search

+88
View File
@@ -0,0 +1,88 @@
#ifndef CHAOS_CIPHER_STREAM_ARC4_ARC4CRYPT_HPP
#define CHAOS_CIPHER_STREAM_ARC4_ARC4CRYPT_HPP
#include <cstdint>
#include <algorithm>
#include "Arc4Gen.hpp"
#include "Service/SeArray.hpp"
#include "Service/ChaosException.hpp"
namespace Chaos::Cipher::Stream::Arc4
{
class Arc4Crypt
{
public:
Arc4Crypt()
: IsInitialized_(false)
{ }
template<typename InputIt>
Arc4Crypt(InputIt keyBegin, InputIt keyEnd)
{
RekeyImpl(keyBegin, keyEnd);
}
template<typename InputIt>
void Rekey(InputIt keyBegin, InputIt keyEnd)
{
RekeyImpl(keyBegin, keyEnd);
}
template<typename OutputIt, typename InputIt>
void Encrypt(OutputIt out, InputIt in, uint64_t count)
{
EnsureInitialized();
EncryptDecryptImpl(out, in, count);
}
template<typename OutputIt, typename InputIt>
void Decrypt(OutputIt out, InputIt in, uint64_t count)
{
EnsureInitialized();
EncryptDecryptImpl(out, in, count);
}
private:
Arc4Gen Gen_;
bool IsInitialized_;
void EnsureInitialized() const
{
if (!IsInitialized_)
{
throw Service::ChaosException("Arc4Crypt: not initialized");
}
}
template<typename InputIt>
void RekeyImpl(InputIt keyBegin, InputIt keyEnd)
{
Gen_.Rekey(keyBegin, keyEnd);
IsInitialized_ = true;
}
template<typename OutputIt, typename InputIt>
void EncryptDecryptImpl(OutputIt out, InputIt in, uint64_t count)
{
Service::SeArray<uint8_t, 512> keyBuf;
while (count > 0)
{
uint64_t keyMaterialBytes = std::min<uint64_t>(keyBuf.Size(), count);
Gen_.Generate(keyBuf.Begin(), keyMaterialBytes);
for (auto keyBufIt = keyBuf.Begin();
keyMaterialBytes > 0 && count > 0;
++keyBufIt, --keyMaterialBytes, --count)
{
*out++ = *in++ ^ *keyBufIt;
}
}
}
};
} // namespace Chaos::Cipher::Stream::Arc4
#endif // CHAOS_CIPHER_STREAM_ARC4_ARC4CRYPT_HPP
+112
View File
@@ -0,0 +1,112 @@
#ifndef CHAOS_CIPHER_STREAM_ARC4_ARC4GEN_HPP
#define CHAOS_CIPHER_STREAM_ARC4_ARC4GEN_HPP
#include <array>
#include <cstdint>
#include <vector>
#include <utility>
#include "Service/ChaosException.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);
}
private:
std::array<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)
{
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