5#ifndef BITCOIN_UTIL_OBFUSCATION_H
6#define BITCOIN_UTIL_OBFUSCATION_H
26 explicit Obfuscation(std::span<const std::byte, KEY_SIZE> key_bytes)
33 void operator()(std::span<std::byte> target,
size_t key_offset = 0)
const
40 if (
const auto misalign{
reinterpret_cast<uintptr_t
>(target.data()) %
KEY_SIZE}) {
41 const size_t alignment{
KEY_SIZE - misalign};
42 XorWord(target.first(alignment), rot_key);
44 target = {std::assume_aligned<KEY_SIZE>(target.data() + alignment), target.size() - alignment};
48 for (
constexpr auto unroll{8}; target.size() >=
KEY_SIZE * unroll; target = target.subspan(
KEY_SIZE * unroll)) {
49 for (
size_t i{0}; i < unroll; ++i) {
61 template <
typename Stream>
65 std::vector<std::byte> bytes{
KEY_SIZE};
70 template <
typename Stream>
73 std::vector<std::byte> bytes{
KEY_SIZE};
75 if (bytes.size() !=
KEY_SIZE)
throw std::ios_base::failure(
strprintf(
"Obfuscation key size should be exactly %s bytes long",
KEY_SIZE));
90 for (
size_t i{0}; i <
KEY_SIZE; ++i) {
91 int key_rotation_bits{int(CHAR_BIT * i)};
92 if constexpr (std::endian::native == std::endian::big) key_rotation_bits *= -1;
97 static KeyType ToKey(std::span<const std::byte, KEY_SIZE> key_span)
100 std::memcpy(&key, key_span.data(),
KEY_SIZE);
107 if (target.empty())
return;
109 std::memcpy(&raw, target.data(), target.size());
111 std::memcpy(target.data(), &raw, target.size());
std::array< KeyType, KEY_SIZE > m_rotations
Obfuscation(std::span< const std::byte, KEY_SIZE > key_bytes)
void Unserialize(Stream &s)
std::string HexKey() const
void SetRotations(KeyType key)
static KeyType ToKey(std::span< const std::byte, KEY_SIZE > key_span)
static void XorWord(std::span< std::byte > target, KeyType key)
void operator()(std::span< std::byte > target, size_t key_offset=0) const
static constexpr size_t KEY_SIZE
void Serialize(Stream &s) const
std::string HexStr(const std::span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.