refactor: move util::Xor to Obfuscation().Xor
This is meant to focus the usages to narrow the scope of the obfuscation optimization. `Obfuscation::Xor` is mostly a move. Co-authored-by: maflcko <6399679+maflcko@users.noreply.github.com>
This commit is contained in:
1 parent
fa5d296e3b
commit
377aab8e5a
5 files changed
+26
-28
No files matched your search
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include <bench/bench.h>
|
#include <bench/bench.h>
|
||||||
#include <random.h>
|
#include <random.h>
|
||||||
#include <streams.h>
|
|
||||||
#include <util/obfuscation.h>
|
#include <util/obfuscation.h>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@@ -18,7 +17,7 @@ static void ObfuscationBench(benchmark::Bench& bench)
|
|||||||
|
|
||||||
size_t offset{0};
|
size_t offset{0};
|
||||||
bench.batch(data.size()).unit("byte").run([&] {
|
bench.batch(data.size()).unit("byte").run([&] {
|
||||||
util::Xor(data, key, offset++); // mutated differently each time
|
Obfuscation().Xor(data, key, offset++); // mutated differently each time
|
||||||
ankerl::nanobench::doNotOptimizeAway(data);
|
ankerl::nanobench::doNotOptimizeAway(data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -6,6 +6,7 @@
|
|||||||
#include <span.h>
|
#include <span.h>
|
||||||
#include <streams.h>
|
#include <streams.h>
|
||||||
#include <util/fs_helpers.h>
|
#include <util/fs_helpers.h>
|
||||||
|
#include <util/obfuscation.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ std::size_t AutoFile::detail_fread(std::span<std::byte> dst)
|
|||||||
size_t ret = std::fread(dst.data(), 1, dst.size(), m_file);
|
size_t ret = std::fread(dst.data(), 1, dst.size(), m_file);
|
||||||
if (!m_obfuscation.empty()) {
|
if (!m_obfuscation.empty()) {
|
||||||
if (!m_position.has_value()) throw std::ios_base::failure("AutoFile::read: position unknown");
|
if (!m_position.has_value()) throw std::ios_base::failure("AutoFile::read: position unknown");
|
||||||
util::Xor(dst.subspan(0, ret), m_obfuscation, *m_position);
|
Obfuscation().Xor(dst.subspan(0, ret), m_obfuscation, *m_position);
|
||||||
}
|
}
|
||||||
if (m_position.has_value()) *m_position += ret;
|
if (m_position.has_value()) *m_position += ret;
|
||||||
return ret;
|
return ret;
|
||||||
@@ -103,7 +104,7 @@ void AutoFile::write_buffer(std::span<std::byte> src)
|
|||||||
if (!m_file) throw std::ios_base::failure("AutoFile::write_buffer: file handle is nullptr");
|
if (!m_file) throw std::ios_base::failure("AutoFile::write_buffer: file handle is nullptr");
|
||||||
if (m_obfuscation.size()) {
|
if (m_obfuscation.size()) {
|
||||||
if (!m_position) throw std::ios_base::failure("AutoFile::write_buffer: obfuscation position unknown");
|
if (!m_position) throw std::ios_base::failure("AutoFile::write_buffer: obfuscation position unknown");
|
||||||
util::Xor(src, m_obfuscation, *m_position); // obfuscate in-place
|
Obfuscation().Xor(src, m_obfuscation, *m_position); // obfuscate in-place
|
||||||
}
|
}
|
||||||
if (std::fwrite(src.data(), 1, src.size(), m_file) != src.size()) {
|
if (std::fwrite(src.data(), 1, src.size(), m_file) != src.size()) {
|
||||||
throw std::ios_base::failure("AutoFile::write_buffer: write failed");
|
throw std::ios_base::failure("AutoFile::write_buffer: write failed");
|
||||||
|
|||||||
+2
-22
@@ -11,6 +11,7 @@
|
|||||||
#include <span.h>
|
#include <span.h>
|
||||||
#include <support/allocators/zeroafterfree.h>
|
#include <support/allocators/zeroafterfree.h>
|
||||||
#include <util/check.h>
|
#include <util/check.h>
|
||||||
|
#include <util/obfuscation.h>
|
||||||
#include <util/overflow.h>
|
#include <util/overflow.h>
|
||||||
#include <util/syserror.h>
|
#include <util/syserror.h>
|
||||||
|
|
||||||
@@ -27,27 +28,6 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace util {
|
|
||||||
inline void Xor(std::span<std::byte> write, std::span<const std::byte> key, size_t key_offset = 0)
|
|
||||||
{
|
|
||||||
if (key.size() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
key_offset %= key.size();
|
|
||||||
|
|
||||||
for (size_t i = 0, j = key_offset; i != write.size(); i++) {
|
|
||||||
write[i] ^= key[j++];
|
|
||||||
|
|
||||||
// This potentially acts on very many bytes of data, so it's
|
|
||||||
// important that we calculate `j`, i.e. the `key` index in this
|
|
||||||
// way instead of doing a %, which would effectively be a division
|
|
||||||
// for each byte Xor'd -- much slower than need be.
|
|
||||||
if (j == key.size())
|
|
||||||
j = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace util
|
|
||||||
|
|
||||||
/* Minimal stream for overwriting and/or appending to an existing byte vector
|
/* Minimal stream for overwriting and/or appending to an existing byte vector
|
||||||
*
|
*
|
||||||
* The referenced vector will grow as necessary
|
* The referenced vector will grow as necessary
|
||||||
@@ -279,7 +259,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
void Xor(const std::vector<unsigned char>& key)
|
void Xor(const std::vector<unsigned char>& key)
|
||||||
{
|
{
|
||||||
util::Xor(MakeWritableByteSpan(*this), MakeByteSpan(key));
|
Obfuscation().Xor(MakeWritableByteSpan(*this), MakeByteSpan(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compute total memory usage of this object (own memory + any dynamic memory). */
|
/** Compute total memory usage of this object (own memory + any dynamic memory). */
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ BOOST_AUTO_TEST_CASE(xor_roundtrip_random_chunks)
|
|||||||
auto apply_random_xor_chunks{[&](std::span<std::byte> target, std::span<const std::byte, Obfuscation::KEY_SIZE> obfuscation) {
|
auto apply_random_xor_chunks{[&](std::span<std::byte> target, std::span<const std::byte, Obfuscation::KEY_SIZE> obfuscation) {
|
||||||
for (size_t offset{0}; offset < target.size();) {
|
for (size_t offset{0}; offset < target.size();) {
|
||||||
const size_t chunk_size{1 + m_rng.randrange(target.size() - offset)};
|
const size_t chunk_size{1 + m_rng.randrange(target.size() - offset)};
|
||||||
util::Xor(target.subspan(offset, chunk_size), obfuscation, offset);
|
Obfuscation().Xor(target.subspan(offset, chunk_size), obfuscation, offset);
|
||||||
offset += chunk_size;
|
offset += chunk_size;
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
@@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(xor_bytes_reference)
|
|||||||
std::vector actual{expected};
|
std::vector actual{expected};
|
||||||
|
|
||||||
expected_xor(std::span{expected}.subspan(write_offset), key_bytes, key_offset);
|
expected_xor(std::span{expected}.subspan(write_offset), key_bytes, key_offset);
|
||||||
util::Xor(std::span{actual}.subspan(write_offset), key_bytes, key_offset);
|
Obfuscation().Xor(std::span{actual}.subspan(write_offset), key_bytes, key_offset);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), actual.begin(), actual.end());
|
BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), actual.begin(), actual.end());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,29 @@
|
|||||||
#define BITCOIN_UTIL_OBFUSCATION_H
|
#define BITCOIN_UTIL_OBFUSCATION_H
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <span.h>
|
||||||
|
|
||||||
class Obfuscation
|
class Obfuscation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr size_t KEY_SIZE{sizeof(uint64_t)};
|
static constexpr size_t KEY_SIZE{sizeof(uint64_t)};
|
||||||
|
|
||||||
|
void Xor(std::span<std::byte> write, std::span<const std::byte> key, size_t key_offset = 0)
|
||||||
|
{
|
||||||
|
assert(key.size() == KEY_SIZE);
|
||||||
|
key_offset %= KEY_SIZE;
|
||||||
|
|
||||||
|
for (size_t i = 0, j = key_offset; i != write.size(); i++) {
|
||||||
|
write[i] ^= key[j++];
|
||||||
|
|
||||||
|
// This potentially acts on very many bytes of data, so it's
|
||||||
|
// important that we calculate `j`, i.e. the `key` index in this
|
||||||
|
// way instead of doing a %, which would effectively be a division
|
||||||
|
// for each byte Xor'd -- much slower than need be.
|
||||||
|
if (j == KEY_SIZE)
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BITCOIN_UTIL_OBFUSCATION_H
|
#endif // BITCOIN_UTIL_OBFUSCATION_H
|
||||||
Reference in new issue
Block a user