From e1cfe423aee918c07bb45fafca1da9276f1f977d Mon Sep 17 00:00:00 2001 From: hama Date: Sun, 18 Oct 2015 12:18:24 +0200 Subject: [PATCH] ReByteScrambler works --- base/ReFileUtils.cpp | 42 ++-- base/ReRandomizer.cpp | 459 ++++++++++++++++++++++++++++++++------- base/ReRandomizer.hpp | 69 +++++- base/ReStringUtils.cpp | 20 +- base/ReStringUtils.hpp | 10 +- base/retrace.hpp | 28 +++ cunit/allTests.cpp | 2 +- cunit/cuReFileSystem.cpp | 57 ----- cunit/cuReRandomizer.cpp | 116 +++++++++- os/ReFileSystem.cpp | 202 +++++++---------- os/ReFileSystem.hpp | 29 +-- remodules.hpp | 1 + 12 files changed, 713 insertions(+), 322 deletions(-) create mode 100644 base/retrace.hpp diff --git a/base/ReFileUtils.cpp b/base/ReFileUtils.cpp index 1f86781..73d776f 100644 --- a/base/ReFileUtils.cpp +++ b/base/ReFileUtils.cpp @@ -24,9 +24,9 @@ QDateTime ReFileUtils::m_undefinedTime; * Constructor. */ ReTreeStatistic::ReTreeStatistic() : - m_files(0), - m_directories(0), - m_fileSizes(0L) { + m_files(0), + m_directories(0), + m_fileSizes(0L) { } /** @@ -83,15 +83,15 @@ QByteArray ReFileUtils::pathAppend(const char* base, const char* path) { */ bool ReFileUtils::deleteTree(const QString& path, bool withBase, - ReLogger* logger) { + ReLogger* logger) { bool rc = true; QDir dir(path); if (dir.exists(path)) { QFileInfo info; QStringList names = dir.entryList( - QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs - | QDir::Files); + QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs + | QDir::Files); QStringList::const_iterator it; for (it = names.constBegin(); it != names.constEnd(); ++it) { QString full(path); @@ -104,16 +104,16 @@ bool ReFileUtils::deleteTree(const QString& path, bool withBase, rc = false; if (logger != NULL) logger->logv(LOG_ERROR, LOC_DELETE_TREE_1, - "cannot delete directory (%d): %s", errno, - full.toUtf8().constData()); + "cannot delete directory (%d): %s", errno, + full.toUtf8().constData()); } } else { if (!QFile::remove(full)) { rc = false; if (logger != NULL) logger->logv(LOG_ERROR, LOC_DELETE_TREE_2, - "cannot delete file (%d): %s", errno, - full.toUtf8().constData()); + "cannot delete file (%d): %s", errno, + full.toUtf8().constData()); } } } @@ -121,7 +121,7 @@ bool ReFileUtils::deleteTree(const QString& path, bool withBase, if (withBase && (rmdir(path.toUtf8())) != 0) { rc = false; logger->logv(LOG_ERROR, LOC_DELETE_TREE_3, - "cannot delete directory (%d): %s", errno, path.toUtf8()); + "cannot delete directory (%d): %s", errno, path.toUtf8()); } return rc; } @@ -199,7 +199,7 @@ bool ReFileUtils::isAbsolutPath(const QString& path) { rc = path.startsWith(OS_SEPARATOR); #else rc = path.length() > 3 && path.at(1) == ':' && path.at(2) == OS_SEPARATOR - || path.startsWith("\\\\"); + || path.startsWith("\\\\"); #endif return rc; } @@ -217,7 +217,7 @@ bool ReFileUtils::isAbsolutPath(const char* path) { rc = path[0] == OS_SEPARATOR; #else rc = isalpha(path[0]) && path[1] == ':' && path[2] == OS_SEPARATOR - || path[0] == OS_SEPARATOR && path[1] == OS_SEPARATOR; + || path[0] == OS_SEPARATOR && path[1] == OS_SEPARATOR; #endif return rc; } @@ -302,7 +302,7 @@ QByteArray ReFileUtils::cleanPath(const char* path) { // ignore ".": do nothing } else if (length == 2 && path[0] == '.' && path[1] == '.') { // remove the last slash and node - if (rc.size() > minLength) { + if (rc.length() > minLength) { rc.resize(rc.size() - 1); int ix = rc.lastIndexOf(OS_SEPARATOR); if (ix > minLength) @@ -321,7 +321,7 @@ QByteArray ReFileUtils::cleanPath(const char* path) { if (path[0] == '.' && path[1] == '\0') { if (rc.size() == 0) rc.append('.'); - } else if (path[0] == '.' && path[1] == '.' && path[3] == '\0') { + } else if (path[0] == '.' && path[1] == '.' && path[2] == '\0' && rc.length() > 0) { // remove the last slash and node if (rc.size() > minLength) { rc.resize(rc.size() - 1); @@ -345,7 +345,7 @@ QByteArray ReFileUtils::cleanPath(const char* path) { * @return buffer (for chaining) */ QByteArray& ReFileUtils::readFromFile(const char* filename, - QByteArray& buffer) { + QByteArray& buffer) { FILE* fp = fopen(filename, "r"); if (fp != NULL) { struct stat info; @@ -408,7 +408,7 @@ QByteArray ReFileUtils::replaceExtension(const char* path, const char* ext) { * @return true: success */ bool ReFileUtils::setTimes(const char* filename, const QDateTime& modified, - const QDateTime& accessed, ReLogger* logger) { + const QDateTime& accessed, ReLogger* logger) { bool rc = true; #if defined __linux__ struct timeval vals[2]; @@ -478,7 +478,7 @@ int64_t ReFileUtils::tell(FILE* file) { * @return the name of an existing directory */ QByteArray ReFileUtils::tempDir(const char* node, const char* parent, - bool withSeparator) { + bool withSeparator) { #if defined __linux__ QByteArray temp("/tmp"); static const char* firstVar = "TMP"; @@ -526,7 +526,7 @@ QByteArray ReFileUtils::tempDir(const char* node, const char* parent, * @return the name of an existing directory */ QByteArray ReFileUtils::tempDirEmpty(const char* node, const char* parent, - bool withSeparator) { + bool withSeparator) { QByteArray rc = tempDir(node, parent, withSeparator); deleteTree(rc, false, NULL); return rc; @@ -541,7 +541,7 @@ QByteArray ReFileUtils::tempDirEmpty(const char* node, const char* parent, * @return the full name of a temporary file */ QByteArray ReFileUtils::tempFile(const char* node, const char* parent, - bool deleteIfExists) { + bool deleteIfExists) { QByteArray rc(tempDir(parent)); if (!rc.endsWith('/')) rc += '/'; @@ -562,7 +562,7 @@ QByteArray ReFileUtils::tempFile(const char* node, const char* parent, * @param mode file write mode: "w" (write) or "a" (append) */ void ReFileUtils::writeToFile(const char* filename, const char* content, - size_t contentLength, const char* mode) { + size_t contentLength, const char* mode) { FILE* fp = fopen(filename, mode); if (fp != NULL) { if (contentLength == (size_t) - 1) diff --git a/base/ReRandomizer.cpp b/base/ReRandomizer.cpp index 1736b2a..25e51cb 100644 --- a/base/ReRandomizer.cpp +++ b/base/ReRandomizer.cpp @@ -10,19 +10,44 @@ */ #include "base/rebase.hpp" +//#define WITH_TRACE +#include "retrace.hpp" +enum { + LOC_READ_1 = LOC_FIRST_OF(LOC_RANDOMIZER), // 12201 + LOC_DECODE_CONTENT_1, // 12202 + LOC_DECODE_CONTENT_2, // 12203 +}; + +const char ReNameScrambler::ESC = '%'; -static bool s_trace = false; const int ReRandomizer::m_primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, - 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, - 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, - 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, - 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, - 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, - 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, - 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, - 659, 661, 673, 677, 683, 691 }; + 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, + 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, + 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, + 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, + 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, + 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, + 659, 661, 673, 677, 683, 691 }; const int ReRandomizer::m_countPrimes = sizeof ReRandomizer::m_primes - / sizeof(int); + / sizeof(int); +const int ReNameScrambler::m_indexOfNodeChar[] = { -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 0, 1, -1, 2, 3, 4, 5, 6, 7, 8, -1, 9, 10, 11, 12, + -1, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, -1, -1, -1, 23, -1, -1, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, -1, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, }; +const char ReNameScrambler::m_nodeChars[] = { ' ', '!', '#', '$', '%', '&', + '\'', '(', ')', '+', ',', '-', '.', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '=', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', + 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + '[', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', + 'z', '{', '|', '}', '~', '\x7f', }; +const int ReNameScrambler::m_countNodeChars = + sizeof ReNameScrambler::m_nodeChars; /** * @brief Constructor. @@ -30,7 +55,8 @@ const int ReRandomizer::m_countPrimes = sizeof ReRandomizer::m_primes * @param name the name of the generator */ ReRandomizer::ReRandomizer(const char* name) : - m_name(name) { + m_name(name), + m_counter(0){ } /** * @brief Destructor. @@ -42,6 +68,10 @@ ReRandomizer::~ReRandomizer() { inline int abs(int x) { return x < 0 ? -x : x; } +inline int64_t abs(int64_t x){ + return x < 0 ? -x : x; +} + #endif /** @@ -80,17 +110,17 @@ void ReRandomizer::hash(const QByteArray& text, QByteArray& seed) { int textLength = text.length(); for (int ix = maxTrg; ix >= 0; ix--) { last = trg[ix] = last * text.at(ix % textLength) - + m_primes[ix % m_countPrimes] * text.at((ix + 1) % textLength); + + m_primes[ix % m_countPrimes] * text.at((ix + 1) % textLength); } // length password > length seed: for (int ix = maxTrg; ix < textLength; ix++) { last = trg[ix % maxTrg] ^= last * text.at(ix) - + m_primes[ix % m_countPrimes]; + + m_primes[ix % m_countPrimes]; } // length password < length seed: for (int ix = textLength; ix <= maxTrg; ix++) { last = trg[ix] = last * text.at(ix % textLength) - + m_primes[ix % m_countPrimes]; + + m_primes[ix % m_countPrimes]; } // mix of all seed entries: for (int ix = 0; ix <= maxTrg; ix++) @@ -125,7 +155,7 @@ ReRandomizer::seed_t ReRandomizer::nearTrueRandom() { void* dummy2 = malloc(1); free(dummy2); rc = (((seed_t) random) << 31) + ((seed_t) &dummy << 9) - + ((-random ^ 0x20111958) ^ (seed_t(dummy2))); + + ((-random ^ 0x20111958) ^ (seed_t(dummy2))); #endif return rc; } @@ -138,7 +168,7 @@ ReRandomizer::seed_t ReRandomizer::nearTrueRandom() { * @return The next random character. */ char ReRandomizer::nextChar() { - char rc = nextInt(' ', ' ' + CHARRANGE - 1); + char rc = nextInt(' ' + CHARRANGE - 1, ' '); return rc; } @@ -158,7 +188,7 @@ int ReRandomizer::nextInt(int maxValue, int minValue) { minValue = maxValue; maxValue = rc; } - seed_t seed = nextSeed(); + seed_t seed = nextSeed64(); if (minValue == maxValue) rc = minValue; else { @@ -167,10 +197,6 @@ int ReRandomizer::nextInt(int maxValue, int minValue) { int64_t offset = seed % range; rc = (int) (minValue + offset); } - if (s_trace) { - static int count = 0; - printf("%c %8x ", count++ % 4 == 0 ? '\n' : ' ', rc); - } return rc; } @@ -190,7 +216,7 @@ int64_t ReRandomizer::nextInt64(int64_t maxValue, int64_t minValue) { minValue = maxValue; maxValue = rc; } - seed_t seed = nextSeed(); + seed_t seed = nextSeed64(); if (minValue == maxValue) rc = minValue; else if (minValue == 0 && maxValue == LLONG_MAX) @@ -201,13 +227,9 @@ int64_t ReRandomizer::nextInt64(int64_t maxValue, int64_t minValue) { else { // int64 overflow: we need a higher precision: double rc2 = (double) minValue - + fmod((double) seed, (double) (maxValue - minValue)); + + fmod((double) seed, (double) (maxValue - minValue)); rc = (int) rc2; } - if (s_trace) { - static int count = 0; - printf("%c %16llx ", count++ % 4 == 0 ? '\n' : ' ', (long long) rc); - } return rc; } @@ -223,7 +245,7 @@ int64_t ReRandomizer::nextInt64(int64_t maxValue, int64_t minValue) { * @result The buffer. */ const char* ReRandomizer::nextString(int minLength, int maxLength, - QByteArray &buffer) { + QByteArray &buffer) { int len = nextInt(maxLength, minLength); buffer.resize(len); char* ptr = buffer.data(); @@ -297,9 +319,9 @@ void ReRandomizer::shuffle(void* array, size_t length, size_t elemSize) { * @param name the name of the generator */ ReSingleSeedRandomizer::ReSingleSeedRandomizer(const char* name) : - ReRandomizer(name), - m_seed(0x1120120419198991ull), - m_lastSetSeed(0x1120120419198991ull) { + ReRandomizer(name), + m_seed(0x1120120419198991ull), + m_lastSetSeed(0x1120120419198991ull) { } /** @@ -316,6 +338,7 @@ void ReSingleSeedRandomizer::modifySeed(int64_t seed) { */ void ReSingleSeedRandomizer::reset() { m_seed = m_lastSetSeed; + m_counter = 0; } /** @@ -360,8 +383,7 @@ ReRandomizer::seed_t ReSingleSeedRandomizer::seed() const { */ void ReSingleSeedRandomizer::setSeed(seed_t seed) { m_seed = m_lastSetSeed = seed; - if (s_trace) - printf(" Seed: %llx ", (long long) seed); + TRACE1("setSeed: %llx\n", (long long) seed); } /** @@ -377,8 +399,8 @@ void ReSingleSeedRandomizer::textToSeed(const QByteArray& text) { * @brief Constructor. */ ReCongruentialGeneratorBase::ReCongruentialGeneratorBase() : - m_factor(214013), - m_increment(2531011) { + m_factor(214013), + m_increment(2531011) { } /** @@ -404,8 +426,9 @@ ReRandomizer::seed_t ReCongruentialGeneratorBase::increment() const { * * @return The next seed. */ -ReRandomizer::seed_t ReCongruentialGenerator::nextSeed() { +ReRandomizer::seed_t ReCongruentialGenerator::nextSeed64() { m_seed = m_seed * m_factor + m_increment; + ++m_counter; return m_seed; } @@ -431,23 +454,23 @@ void ReCongruentialGeneratorBase::setIncrement(ReRandomizer::seed_t increment) { * @brief Constructor. */ ReCongruentialGenerator::ReCongruentialGenerator() : - ReSingleSeedRandomizer("LCG"), - ReCongruentialGeneratorBase() { + ReSingleSeedRandomizer("LCG"), + ReCongruentialGeneratorBase() { } /** * @brief Constructor. */ ReCongruentialGenerator::ReCongruentialGenerator(const char* name) : - ReSingleSeedRandomizer(name), - ReCongruentialGeneratorBase() { + ReSingleSeedRandomizer(name), + ReCongruentialGeneratorBase() { } /** * Constructor. */ ReRotateRandomizer::ReRotateRandomizer() : - ReCongruentialGenerator("Rotating LCG") { + ReCongruentialGenerator("Rotating LCG") { } @@ -460,9 +483,10 @@ ReRotateRandomizer::ReRotateRandomizer() : * @return a pseudo random number */ -ReRandomizer::seed_t ReRotateRandomizer::nextSeed() { - seed_t rc = ReCongruentialGenerator::nextSeed(); +ReRandomizer::seed_t ReRotateRandomizer::nextSeed64() { + seed_t rc = ReCongruentialGenerator::nextSeed64(); rc = ((rc & 0x7fffffff) << 33) | ((rc >> 31) & 0x1ffffffffll); + ++m_counter; return rc; } @@ -471,17 +495,17 @@ ReRandomizer::seed_t ReRotateRandomizer::nextSeed() { */ ReMultiSeedRandomizer::ReMultiSeedRandomizer(int countSeeds, const char* name) : - ReRandomizer(name), - m_countSeeds(min(256, max(countSeeds, 2))), - m_seedBuffer(), - m_startSeed(), - m_seeds() { + ReRandomizer(name), + m_countSeeds(min(256, max(countSeeds, 2))), + m_seedBuffer(), + m_startSeed(), + m_seeds() { m_seedBuffer.resize(m_countSeeds * sizeof m_seeds[0]); m_seeds = reinterpret_cast(m_seedBuffer.data()); for (int ix = 0; ix < m_countSeeds; ix++) { int ixPrimes = ix % m_countPrimes; m_seeds[ix] = m_primes[ixPrimes] * (2 * ix + 1) - + (seed_t(m_primes[m_countPrimes - 1 - ixPrimes]) << 32); + + (seed_t(m_primes[m_countPrimes - 1 - ixPrimes]) << 32); } // assignment does not work: copy on write m_startSeed.resize(m_seedBuffer.length()); @@ -492,11 +516,12 @@ ReMultiSeedRandomizer::ReMultiSeedRandomizer(int countSeeds, const char* name) : * * @return a pseudo random number */ -ReRandomizer::seed_t ReMultiCongruentialGenerator::nextSeed() { +ReRandomizer::seed_t ReMultiCongruentialGenerator::nextSeed64() { m_currentSeed = (m_currentSeed + 1) % m_countSeeds; seed_t rc = m_seeds[m_currentSeed] * m_factor + m_increment; m_seeds[m_currentSeed] = rc; rc = ((rc & 0x7fffffff) << 33) | ((rc >> 31) & 0x1ffffffffLL); + ++m_counter; return rc; } @@ -517,6 +542,7 @@ void ReMultiSeedRandomizer::modifySeed(int64_t seed) { void ReMultiSeedRandomizer::reset() { // assignment does not work: copy on write memcpy(m_seedBuffer.data(), m_startSeed.constData(), m_seedBuffer.length()); + m_counter = 0; } /** @@ -559,9 +585,9 @@ void ReMultiSeedRandomizer::textToSeed(const QByteArray& text) { * @param countSeeds number of seeds */ ReMultiCongruentialGenerator::ReMultiCongruentialGenerator(int countSeeds) : - ReMultiSeedRandomizer(countSeeds, "Multi LCG"), - ReCongruentialGeneratorBase(), - m_currentSeed(-1) { + ReMultiSeedRandomizer(countSeeds, "Multi LCG"), + ReCongruentialGeneratorBase(), + m_currentSeed(-1) { } /** @@ -570,6 +596,7 @@ ReMultiCongruentialGenerator::ReMultiCongruentialGenerator(int countSeeds) : void ReMultiCongruentialGenerator::reset() { ReMultiSeedRandomizer::reset(); m_currentSeed = -1; + m_counter = 0; } /** @@ -578,7 +605,7 @@ void ReMultiCongruentialGenerator::reset() { * @return */ ReXorShift64Randomizer::ReXorShift64Randomizer() : - ReSingleSeedRandomizer("ShiftXor64") { + ReSingleSeedRandomizer("ShiftXor64") { } /** @@ -586,10 +613,11 @@ ReXorShift64Randomizer::ReXorShift64Randomizer() : * * @return the next pseudo random value */ -ReRandomizer::seed_t ReXorShift64Randomizer::nextSeed() { +ReRandomizer::seed_t ReXorShift64Randomizer::nextSeed64() { m_seed ^= m_seed << 13; m_seed ^= m_seed >> 7; m_seed ^= m_seed << 17; + ++m_counter; return m_seed; } @@ -597,13 +625,13 @@ ReRandomizer::seed_t ReXorShift64Randomizer::nextSeed() { * Constructor. */ ReKISSRandomizer::ReKISSRandomizer() : - ReRandomizer("KISS"), - m_params(), - m_startParams() { - m_params.m_x = 1234567890987654321ULL; - m_params.m_y = 362436362436362436ULL; - m_params.m_z = 1066149217761810ULL; - m_params.m_c = 123456123456123456ULL; + ReRandomizer("KISS"), + m_params(), + m_startParams() { + m_params.m_x = 0x1234567887654321ULL; + m_params.m_y = 0x3624363624363636ULL; + m_params.m_z = 0x2011195811081965ULL; + m_params.m_c = 0x2004199111121989ULL; m_startParams = m_params; } @@ -611,22 +639,23 @@ ReKISSRandomizer::ReKISSRandomizer() : * Dumps the state of the generator. */ void ReKISSRandomizer::dump() { + printf("%2d: f: %016llx i: %016llx: c: %016llx x: %016llx y: %016llx z: %016llx\n", + m_counter, + (long long) m_factor, (long long) m_increment, + (long long) m_params.m_c, (long long) m_params.m_x, + (long long) m_params.m_y, (long long) m_params.m_z); printf( - "f: %016llx i: %016llx: c: %016llx x: %016llx y: %016llx z: %016llx\n", - m_factor, m_increment, m_params.m_x, m_params.m_x, m_params.m_y, - m_params.m_z); - printf( - "f: %016llx i: %016llx: c: %016llx x: %016llx y: %016llx z: %016llx\n", - m_factor, m_increment, m_startParams.m_x, m_startParams.m_x, - m_startParams.m_y, m_startParams.m_z); + " f: %016llx i: %016llx: c: %016llx x: %016llx y: %016llx z: %016llx\n", + (long long) m_factor, (long long) m_increment, + (long long) m_startParams.m_c, (long long) m_startParams.m_x, + (long long) m_startParams.m_y, (long long) m_startParams.m_z); } /** * Calculates the next pseudo random value. * @return */ -ReRandomizer::seed_t ReKISSRandomizer::nextSeed() { - +ReRandomizer::seed_t ReKISSRandomizer::nextSeed64() { seed_t t; // Linear congruence generator m_params.m_z = m_factor * m_params.m_z + m_increment; @@ -640,10 +669,11 @@ ReRandomizer::seed_t ReKISSRandomizer::nextSeed() { m_params.m_c = (m_params.m_x >> 6); m_params.m_x += t; m_params.m_c += (m_params.m_x < t); - - return m_params.m_x + m_params.m_y + m_params.m_z; + ++m_counter; + seed_t rc = m_params.m_x + m_params.m_y + m_params.m_z; + TRACE2("%3d: %llx\n", m_counter, (long long) rc); + return rc; } - /** * Modifies the current seed with a 64-bit value. * @@ -657,6 +687,7 @@ void ReKISSRandomizer::modifySeed(int64_t seed) { */ void ReKISSRandomizer::reset() { m_params = m_startParams; + m_counter = 0; } /** @@ -691,3 +722,283 @@ void ReKISSRandomizer::textToSeed(const QByteArray& text) { restore(seeds, m_params); m_startParams = m_params; } + +/** + * Constructor. + * + * @param contentRandom a pseudo random generator + * @param logger the logger + */ +ReByteScrambler::ReByteScrambler(ReRandomizer& contentRandom, + int reservedLength, int markerLength, ReLogger* logger) : + m_contentRandom(contentRandom), + m_realRandom(), + m_contentSeed(), + m_buffer(), + m_header(), + m_reservedLength(reservedLength), + m_markerLength(max(0, min(sizeof(int64_t), markerLength))), + m_headerLength(0), + m_logger(logger) +{ + m_contentRandom.saveSeed(m_contentSeed); + m_buffer.reserve(256); + m_realRandom.nearTrueRandom(); + m_headerLength = sizeof (int64_t) + markerLength + m_reservedLength; + m_header.resize(m_headerLength); +} + +/** + * Constructor. + * + * @param nameRandom a pseudo random generator + * @param logger the logger + */ +ReNameScrambler::ReNameScrambler(ReRandomizer& nameRandom, ReLogger* logger) : + m_nameRandom(nameRandom), + m_nameSeed(), + m_logger(logger) +{ + nameRandom.saveSeed(m_nameSeed); +} + +/** + * Makes the clear text name from an encoded name. + * + * @param name the encoded name + * @return the clear text name + */ +QByteArray& ReNameScrambler::decodeName(const QByteArray& name) +{ + //@ToDo + m_buffer = name; + return m_buffer; +} + +/** + * Makes a clear text filename. + * + * @param name encrypted filename + * @return the clear text filename + */ +QString ReNameScrambler::decodeName(const QString& name) { + QString rc = name; + return rc; +} + +/** + * Encodes a block of file content. + * + * @param first true: this is the first block of the file + * @param source the source block + * @param target OUT: the target block
+ * Can be identical to source (in place replacement) + * @return true: successful
+ * false: otherwise + */ +bool ReByteScrambler::decodeContent(const QByteArray& source, + QByteArray& target) { + bool rc = true; + int offset = 0; + target.resize(0); + if (rc){ + target.resize(source.length() - offset); + int64_t* trg = reinterpret_cast(target.data()); + int count = (source.length() - offset) / sizeof(int64_t); + const int64_t* src = reinterpret_cast(source.constData() + offset); + int64_t last = ReRandomizer::m_primes[0]; + for (int ix = 0; ix < count; ix++) { + int64_t last2 = last; + last = *src++; + int64_t rand = m_contentRandom.nextSeed64(); + *trg++ = last ^ rand ^ last2; + TRACE_IT(("ix: %d last: %016lx rand %016lx src: %016lx trg: %016lx\n", + ix, last2, rand, src[-1], trg[-1])); + } + int countTail = (source.length() - offset) % sizeof(int64_t); + if (countTail != 0){ + char* trgTail = reinterpret_cast(trg); + char lastTail = (char) last; + const char* srcTail = reinterpret_cast(src); + for (int ix = 0; ix < countTail; ix++){ + char last2 = lastTail; + lastTail = *srcTail++; + char rand = m_contentRandom.nextChar(); + *trgTail++ = lastTail ^ rand ^ last2; + TRACE_IT(("ix: %d last: %02x rand %2x src: %02x trg: %02x\n", + ix, (uint8_t) last2, (uint8_t) rand, + (uint8_t) srcTail[-1], (uint8_t) trgTail[-1])); + } + } + } + return rc; +} + +/** + * Encodes a buffer of file content. + * + * @param source the source buffer + * @param target OUT: the target buffer. + * May be identical to source (in place processing) + */ +void ReByteScrambler::encodeContent(const QByteArray& source, + QByteArray& target) { + target.resize(source.length()); + int64_t* trg = reinterpret_cast(target.data()); + int count = source.length() / sizeof(int64_t); + const int64_t* src = reinterpret_cast(source.constData()); + int64_t last = ReRandomizer::m_primes[0]; + + for (int ix = 0; ix < count; ix++) { + int64_t rand = m_contentRandom.nextSeed64(); + IF_TRACE(int64_t last2 = last); + last = *trg++ = *src++ ^ rand ^ last; + TRACE_IT(("ix: %d last: %016lx rand %016lx src: %016lx trg: %016lx\n", + ix, last2, rand, src[-1], trg[-1])); + } + int countTail = source.length() % sizeof(int64_t); + if (countTail != 0){ + char* trgTail = reinterpret_cast(trg); + char lastTail = (char) last; + const char* srcTail = reinterpret_cast(src); + for (int ix = 0; ix < countTail; ix++){ + char rand = m_contentRandom.nextChar(); + IF_TRACE(char last2 = lastTail); + lastTail = *trgTail++ = *srcTail++ ^ rand ^ lastTail; + TRACE_IT(("ix: %d last: %02x rand %2x src: %02x trg: %02x\n", + ix, (uint8_t) last2, (uint8_t) rand, + (uint8_t) srcTail[-1], (uint8_t) trgTail[-1])); + } + } +} + +/** + * Initializes the scrambler from a header. + * + * @param header the header with the initializing info. If NULL the internal + * header will be used + * @param info OUT: the reserved area in the header + * @return true: success + */ +bool ReByteScrambler::initFromHeader(const QByteArray* header, QByteArray& info) +{ + TRACE("initFromHeader():\n"); + bool rc = true; + if (header == NULL) + header = &m_header; + if (header->length() < m_headerLength ){ + m_logger->logv(LOG_ERROR, LOC_DECODE_CONTENT_1, "header length too small: %d/%d", + header->length(), m_headerLength); + rc = false; + } else { + int64_t random = * reinterpret_cast(header->constData()); + m_contentRandom.reset(); + m_contentRandom.modifySeed(random); + QByteArray marker; + marker.append(reinterpret_cast(header->constData()+ sizeof(int64_t)), + m_markerLength); + QByteArray marker2; + m_contentRandom.nextString(m_markerLength, m_markerLength, marker2); + if (marker != marker2){ + m_logger->logv(LOG_ERROR, LOC_DECODE_CONTENT_2, "invalid marker: %s / %s", + ReStringUtils::hexDump(marker, m_markerLength, m_markerLength).constData(), + ReStringUtils::hexDump(marker2, m_markerLength, m_markerLength).constData()); + rc = false; + } + char last = 0x47; + const char* src = reinterpret_cast(header->data() + sizeof (int64_t) + m_markerLength); + int length = *src++; + TRACE1("info: Length: %d\n", length); + info.resize(0); + for (int ix = 0; ix < length; ix++){ + char last2 = last; + last = *src++; + char rand = m_contentRandom.nextChar(); + info.append(last ^ rand ^ last2); + } + } + IF_TRACE(m_contentRandom.dump()); + return rc; +} + +/** + * Initializes the scrambler header. + * + * Format of the header: + *
random (8 byte)
+ * marker (m_markerLength byte)
+ * reserved (m_reservedLength byte)
+ * 
+ * + * @param info the content of the "reserved area" + */ +void ReByteScrambler::initHeader(const QByteArray& info) +{ + TRACE("initHeader():\n"); + int64_t random = m_realRandom.nextSeed64(); + m_contentRandom.reset(); + m_contentRandom.modifySeed(random); + m_header.fill(' ', m_headerLength); + * reinterpret_cast(m_header.data()) = random; + if (m_markerLength > 0){ + m_buffer.resize(0); + m_contentRandom.nextString(m_markerLength, m_markerLength, m_buffer); + memcpy(m_header.data() + sizeof(int64_t), m_buffer, m_markerLength); + } + char last = 0x47; + char* trg = reinterpret_cast(m_header.data() + sizeof (int64_t) + m_markerLength); + int infoLength = min(info.length(), m_reservedLength - 1); + TRACE2("info: length: %d reserved: %d\n", infoLength, m_reservedLength); + *trg++ = infoLength; + for (int ix = 0; ix < infoLength && ix < m_reservedLength; ix++){ + last = *trg++ = m_contentRandom.nextChar() ^ info.at(ix) ^ last; + } + TRACE_IT(("random: %016lx marker: %s\n", random, + m_buffer.constData())); + IF_TRACE(m_contentRandom.dump()); +} +/** + * Encode a filename. + * + * Method: + *
  • Invert the name without extension (first char becomes the last), + * add the extension
  • + *
  • Replace the "unconvertable" chars (> 127) into "%xx" ('%' with 2 hexdigits)
  • + *
  • exchange the char with a value generated by the pseudo random generator
  • + *
+ * @param name clear text filename + * @return the encrypted filename + */ +QByteArray& ReNameScrambler::encodeName(const QByteArray& node) { + QByteArray rc; + int length = node.length(); + int nameLength = rc.lastIndexOf('.'); + if (nameLength < 0) + nameLength = node.length(); + const char* src = node.constData(); + unsigned char cc; + int ix2 = nameLength - 1; + for (int ix = 0; ix < length; ix++) { + cc = (unsigned char) src[ix >= nameLength ? ix : ix2--]; + if (cc != ESC && cc < 128) { + m_buffer.append(cc); + } else { + m_buffer.append(ESC); + char hex[3]; + snprintf(hex, sizeof hex, "%02x", cc); + m_buffer.append(hex, 2); + } + } + m_nameRandom.reset(); + char* trg = m_buffer.data(); + int pred = 0; + for (int ix = 0; ix < length; ix++) { + int ix2 = (m_indexOfNodeChar[(int) *trg] + pred + + m_nameRandom.nextInt(m_countNodeChars - 1)) % m_countNodeChars; + *trg = m_nodeChars[ix2]; + pred = ix2; + } + return m_buffer; +} + + diff --git a/base/ReRandomizer.hpp b/base/ReRandomizer.hpp index bae5487..4fb334e 100644 --- a/base/ReRandomizer.hpp +++ b/base/ReRandomizer.hpp @@ -40,6 +40,10 @@ public: * @param seed the value to modify the current seed */ virtual void modifySeed(int64_t seed) = 0; + /** @brief Returns the next pseudo random number. + * @return the next pseudo random number + * */ + virtual seed_t nextSeed64() = 0; /** @brief Sets the instance to a defined start state. */ virtual void reset() = 0; @@ -66,13 +70,9 @@ public: static seed_t hash(const QByteArray& text); static void hash(const QByteArray& text, QByteArray& seed); -protected: - /** @brief Returns the next pseudo random number. - * @return the next pseudo random number - * */ - virtual seed_t nextSeed() = 0; protected: QByteArray m_name; + int m_counter; public: // the first 125 prime numbers static const int m_primes[]; @@ -118,14 +118,14 @@ protected: * In this implementation modulus is 2**64. */ class ReCongruentialGenerator: public ReSingleSeedRandomizer, - public ReCongruentialGeneratorBase { + public ReCongruentialGeneratorBase { public: ReCongruentialGenerator(); protected: ReCongruentialGenerator(const char* name); protected: friend class ReShiftRandom; - virtual seed_t nextSeed(); + virtual seed_t nextSeed64(); }; /** @@ -139,7 +139,7 @@ class ReRotateRandomizer: public ReCongruentialGenerator { public: ReRotateRandomizer(); protected: - virtual seed_t nextSeed(); + virtual seed_t nextSeed64(); }; /** @@ -167,12 +167,12 @@ protected: * Difference: An array of seeds is used (round robin). */ class ReMultiCongruentialGenerator: public ReMultiSeedRandomizer, - public ReCongruentialGeneratorBase { + public ReCongruentialGeneratorBase { public: ReMultiCongruentialGenerator(int countSeeds); public: virtual void reset(); - virtual seed_t nextSeed(); + virtual seed_t nextSeed64(); protected: int m_currentSeed; }; @@ -181,7 +181,7 @@ class ReXorShift64Randomizer: public ReSingleSeedRandomizer { public: ReXorShift64Randomizer(); public: - virtual seed_t nextSeed(); + virtual seed_t nextSeed64(); }; /** @@ -202,7 +202,7 @@ public: ReKISSRandomizer(); public: virtual void dump(); - virtual seed_t nextSeed(); + virtual seed_t nextSeed64(); public: virtual void modifySeed(int64_t seed); virtual void reset(); @@ -232,4 +232,49 @@ private: params_t m_startParams; }; +/** + * A processing unit for encoding/decoding of binary data. + */ +class ReByteScrambler{ +public: + ReByteScrambler(ReRandomizer& contentRandom, + int reservedLength, int markerLength, ReLogger* logger); +public: + bool decodeContent(const QByteArray& source, QByteArray& target); + void encodeContent(const QByteArray& source, QByteArray& target); + void initHeader(const QByteArray& info = ReStringUtils::m_empty); + bool initFromHeader(const QByteArray* header, QByteArray& info); +protected: + ReRandomizer& m_contentRandom; + ReKISSRandomizer m_realRandom; + QByteArray m_contentSeed; + QByteArray m_buffer; + QByteArray m_header; + int m_reservedLength; + int m_markerLength; + int m_headerLength; + ReLogger* m_logger; +}; + +class ReNameScrambler{ +public: + ReNameScrambler(ReRandomizer& nameRandom, ReLogger* logger); +public: + QByteArray& decodeName(const QByteArray& name); + QString decodeName(const QString& name); + QByteArray& encodeName(const QByteArray& name); + QString encodeName(const QString& name); +protected: + ReRandomizer& m_nameRandom; + QByteArray m_nameSeed; + QByteArray m_buffer; + ReLogger* m_logger; +public: + static const char ESC; +public: + static const int m_indexOfNodeChar[]; + static const char m_nodeChars[]; + static const int m_countNodeChars; +}; + #endif /* RANDOMIZER_H_ */ diff --git a/base/ReStringUtils.cpp b/base/ReStringUtils.cpp index 0faf845..03e57e7 100644 --- a/base/ReStringUtils.cpp +++ b/base/ReStringUtils.cpp @@ -24,6 +24,8 @@ * This is a class with static members only. */ +const QByteArray ReStringUtils::m_empty; + /** * @brief Counts the occurrences of a given char in a string. * @@ -76,9 +78,9 @@ int ReStringUtils::count(const char* source, const char* item) { * the prefix of source with the given length */ const QByteArray& ReStringUtils::cutString(const QByteArray& source, - int maxLength, QByteArray& buffer, const char* appendix) { + int maxLength, QByteArray& buffer, const char* appendix) { QByteArray& rc = - source.length() <= maxLength ? (QByteArray&) source : buffer; + source.length() <= maxLength ? (QByteArray&) source : buffer; if (source.length() > maxLength) { buffer = source.left(maxLength); if (appendix != NULL && appendix[0] != '\0') @@ -105,8 +107,8 @@ char ReStringUtils::fileSeparatorChar() { const char* path = getenv("PATH"); if (path != NULL) { s_fileSeparator = - strchr(path, ';') != NULL || strchr(path, '\\') != NULL ? - '\\' : '/'; + strchr(path, ';') != NULL || strchr(path, '\\') != NULL ? + '\\' : '/'; } else { if (getenv("windows") != NULL) s_fileSeparator = '\\'; @@ -219,7 +221,7 @@ QByteArray ReStringUtils::replaceNode(const char* source, const char* newNode) { * @return an array with the splitted source */ QList ReStringUtils::toArray(const char* source, - const char* separator) { + const char* separator) { const char* end = source; QList < QByteArray > rc; rc.reserve(count(source, separator) + 1); @@ -270,7 +272,7 @@ QByteArray ReStringUtils::toCString(const char* source, int maxLength) { default: { char buffer[5]; qsnprintf(buffer, sizeof buffer, "\\x%02x", - ((unsigned int) cc) % 0xff); + ((unsigned int) cc) % 0xff); rc += buffer; break; } @@ -302,7 +304,7 @@ QByteArray ReStringUtils::toNumber(int value, const char* format) { * false: error occurred */ bool ReStringUtils::write(const char* file, const char* content, - const char* mode) { + const char* mode) { FILE* fp = fopen(file, mode); if (fp != NULL) { fputs(content, fp); @@ -368,7 +370,7 @@ int ReStringUtils::lengthOfNumber(const char* text, bool skipTrailingSpaces) { * @param countBlanks IN/OUT: number of ' ' */ static void addSeparators(const char* line, int& commas, int& semicolons, - int& pipes, int& blanks) { + int& pipes, int& blanks) { commas += ReStringUtils::countChar(line, ','); semicolons += ReStringUtils::countChar(line, ';'); pipes += ReStringUtils::countChar(line, '|'); @@ -464,7 +466,7 @@ int ReStringUtils::lengthOfUInt64(const char* text, int radix, quint64* pValue) } } else { throw ReException("ReStringUtil::lengthOfInt(): wrong radix: %d", - radix); + radix); } if (pValue != NULL) *pValue = value; diff --git a/base/ReStringUtils.hpp b/base/ReStringUtils.hpp index a896bce..dfcf76c 100644 --- a/base/ReStringUtils.hpp +++ b/base/ReStringUtils.hpp @@ -16,26 +16,28 @@ public: static int countChar(const char* line, char cc); static int count(const char* source, const char* item); static const QByteArray& cutString(const QByteArray& source, int maxLength, - QByteArray& buffer, const char* appendix = "..."); + QByteArray& buffer, const char* appendix = "..."); static const char* fileSeparator(); static char fileSeparatorChar(); static QByteArray hexDump(uint8_t* data, int length, int bytesPerLine = 16); static QByteArray hexDump(const void* data, int length, int bytesPerLine = - 16) { + 16) { return hexDump((uint8_t*) data, length, bytesPerLine); } static QByteArray read(const char* file, bool removeLastNewline = true); static QByteArray replaceNode(const char* source, const char* newNode); static bool write(const char* file, const char* content = NULL, - const char* mode = "w"); + const char* mode = "w"); static QList toArray(const char* source, const char* separator); static QByteArray toCString(const char* source, int maxLength = -1); static QByteArray toNumber(int value, const char* format = "%d"); static int lengthOfNumber(const char* text, - bool skipTrailingSpaces = false); + bool skipTrailingSpaces = false); static char findCsvSeparator(FILE* fp, char* buffer, size_t bufferSize); static int lengthOfUInt64(const char* text, int radix, quint64* pValue); static int lengthOfReal(const char* text, qreal* pValue); +public: + static const QByteArray m_empty; }; #endif // RPLSTRING_HPP diff --git a/base/retrace.hpp b/base/retrace.hpp new file mode 100644 index 0000000..31e5fd9 --- /dev/null +++ b/base/retrace.hpp @@ -0,0 +1,28 @@ +/* + * Licence: + * You can use and modify this file without any restriction. + * There is no warranty. + * You also can use the licence from http://www.wtfpl.net/. + * The original sources can be found on https://github.com/republib. +*/ + + +#ifndef RETRACEACTIVE_HPP +#define RETRACEACTIVE_HPP + +#ifdef WITH_TRACE +#define TRACE(format) printf(format); +#define TRACE1(format, a1) printf(format, a1) +#define TRACE2(format, a1, a2) printf(format, a1, a2) +#define TRACE_IT(args) printf args +#define IF_TRACE(statem) statem +#else +#define TRACE(m) +#define TRACE1(format, a1) +#define TRACE2(format, a1, a2) +#define TRACE_IT(args) +#define IF_TRACE(statem) +#endif + +#endif // RETRACEACTIVE_HPP + diff --git a/cunit/allTests.cpp b/cunit/allTests.cpp index 13f4fa2..dfef20a 100644 --- a/cunit/allTests.cpp +++ b/cunit/allTests.cpp @@ -41,11 +41,11 @@ static void testBase() { void testReFile(); void testReFileUtils(); void testReMatcher(); + testReFileUtils(); testReRandomizer(); testReMatcher(); testReQStringUtil(); testReFile(); - testReFileUtils(); if (s_allTest) { testReRandomizer(); testReByteStorage(); diff --git a/cunit/cuReFileSystem.cpp b/cunit/cuReFileSystem.cpp index b9c1884..4945b1b 100644 --- a/cunit/cuReFileSystem.cpp +++ b/cunit/cuReFileSystem.cpp @@ -14,7 +14,6 @@ /** @file * @brief Unit test of the basic exceptions. */ - class TestReFileSystem: public ReTest { public: TestReFileSystem() : @@ -153,65 +152,9 @@ protected: struct stat info; checkEqu(0, stat(path.toUtf8().constData(), &info)); } - void testCharTables() { - for (int ix = 0; ix < ReCryptFileSystem::m_countNodeChars; ix++) { - char cc = ReCryptFileSystem::m_nodeChars[ix]; - int index = ReCryptFileSystem::m_indexOfNodeChar[(int) cc]; - checkEqu(ix, index); - } - for (unsigned char cc = 0; cc < 128; cc++) { - int index = ReCryptFileSystem::m_indexOfNodeChar[cc]; - if (index >= 0) { - unsigned char cc2 = ReCryptFileSystem::m_nodeChars[index]; - checkEqu(cc, cc2); - } - } - log("ready"); - } - void checkName(const char* name, ReCryptFileSystem& fs){ - QByteArray src(name); - QByteArray trg; - QByteArray trg2; - trg = src; - fs.encodeName(trg); - trg2 = trg; - fs.decodeName(trg2); - checkEqu(src, trg2); - } - - void testNamesEncoding(){ - QByteArray dir = ReFileUtils::tempDir("fs"); - ReLocalFileSystem base(dir, &m_logger); - ReKISSRandomizer nameRandom; - ReKISSRandomizer dataRandom; - ReCryptFileSystem fs(base, nameRandom, dataRandom, &m_logger); - checkName("a.b", fs); - checkName("Ä.txt", fs); - checkName("Ää", fs); - checkName(".git", fs); - } - void checkContent(const char* content, ReCryptFileSystem& fs){ - QByteArray src(content); - QByteArray trg; - QByteArray trg2; - - fs.encodeContent(true, src, trg); - fs.decodeContent(true, src, trg); - } - void testContentEncoding(){ - QByteArray dir = ReFileUtils::tempDir("fs"); - ReLocalFileSystem base(dir, &m_logger); - ReKISSRandomizer nameRandom; - ReKISSRandomizer dataRandom; - ReCryptFileSystem fs(base, nameRandom, dataRandom, &m_logger); - - } virtual void run() { init(); - testContentEncoding(); - testNamesEncoding(); - testCharTables(); testReListInfos(); testSetProperties(); testSetPropertiesOwner(); diff --git a/cunit/cuReRandomizer.cpp b/cunit/cuReRandomizer.cpp index 93d7e1b..f840b66 100644 --- a/cunit/cuReRandomizer.cpp +++ b/cunit/cuReRandomizer.cpp @@ -17,7 +17,7 @@ class TestReRandomizer: public ReTest { public: TestReRandomizer() : - ReTest("ReRandomizer") { + ReTest("ReRandomizer") { doIt(); } @@ -121,8 +121,34 @@ public: fclose(fp); } } + void checkModifySeed(ReRandomizer& rand){ + rand.reset(); + QByteArray s1; + rand.nextString(10, 10, s1); + rand.reset(); + rand.modifySeed(22); + QByteArray s2; + rand.nextString(10, 10, s2); + checkF(s1 == s2); + rand.reset(); + rand.modifySeed(22); + QByteArray s3; + rand.nextString(10, 10, s3); + checkEqu(s2, s3); + } - void special() { + void testModifySeed(){ + ReCongruentialGenerator rand; + checkModifySeed(rand); + ReXorShift64Randomizer rand2; + checkModifySeed(rand2); + ReMultiCongruentialGenerator rand3(2); + checkModifySeed(rand3); + ReKISSRandomizer rand4; + checkModifySeed(rand4); + } + + void testWrite1m() { ReCongruentialGenerator rand; write1m(rand); ReXorShift64Randomizer rand2; @@ -131,14 +157,98 @@ public: write1m(rand3); ReKISSRandomizer rand4; write1m(rand4); + } + + void testCharTables() { + for (int ix = 0; ix < ReNameScrambler::m_countNodeChars; ix++) { + char cc = ReNameScrambler::m_nodeChars[ix]; + int index = ReNameScrambler::m_indexOfNodeChar[(int) cc]; + checkEqu(ix, index); + } + for (unsigned char cc = 0; cc < 128; cc++) { + int index = ReNameScrambler::m_indexOfNodeChar[cc]; + if (index >= 0) { + unsigned char cc2 = ReNameScrambler::m_nodeChars[index]; + checkEqu(cc, cc2); + } + } + log("ready"); + } + void checkName(const char* name, ReNameScrambler& scrambler){ + QByteArray src(name); + QByteArray trg; + QByteArray trg2; + trg = src; + scrambler.encodeName(trg); + trg2 = trg; + scrambler.decodeName(trg2); + checkEqu(src, trg2); + } + + void testNamesEncoding(){ + QByteArray dir = ReFileUtils::tempDir("fs"); + ReKISSRandomizer nameRandom; + ReNameScrambler scrambler(nameRandom, &m_logger); + checkName("a.b", scrambler); + checkName("Ä.txt", scrambler); + checkName("Ää", scrambler); + checkName(".git", scrambler); + } + void checkContent(const char* content, ReByteScrambler& scrambler){ + QByteArray src(content); + QByteArray trg; + QByteArray trg2; + ReKISSRandomizer rand; + rand.nearTrueRandom(); + QByteArray info; + rand.nextString(10, 20, info); + scrambler.initHeader(info); + scrambler.encodeContent(src, trg); + QByteArray info2; + scrambler.initFromHeader(NULL, info2); + scrambler.decodeContent(trg, trg2); + checkEqu(src, trg2); + checkT(info.startsWith(info2)); + } + void testContentEncoding(){ + ReKISSRandomizer dataRandom; + ReByteScrambler scrambler(dataRandom, 8, 4, &m_logger); + checkContent("12345678abc", scrambler); + checkContent("8765432112345678ab", scrambler); + checkContent("8765432112345678", scrambler); + checkContent("", scrambler); + ReXorShift64Randomizer rand; + QByteArray src; + for (int ix = 0; ix < 1000; ix++){ + rand.nextString(10, 50, src); + checkContent(src, scrambler); + } + for (int ix = 0; ix < 1000; ix++){ + src.resize(0); + for (int ix2 = 0; ix2 < 50; ix2++){ + int64_t nRand = rand.nextInt64(); + src.append((const char*) &nRand, sizeof nRand); + } + checkContent(src, scrambler); + } + } + void special(){ + ReKISSRandomizer rand; + rand.dump(); + rand.nextSeed64(); + rand.dump(); log("ready"); } virtual void run(void) { special(); + testContentEncoding(); + testNamesEncoding(); + testCharTables(); + testModifySeed(); testTextToSeed(); + testWrite1m(); testBasics(); - int ix = 1; } }; void testReRandomizer() { diff --git a/os/ReFileSystem.cpp b/os/ReFileSystem.cpp index c06fc2b..7ff1ebe 100644 --- a/os/ReFileSystem.cpp +++ b/os/ReFileSystem.cpp @@ -32,25 +32,17 @@ enum { LOC_SET_PROPERTIES_5, // 12017 }; -const char ReCryptFileSystem::ESC = '%'; -const int ReCryptFileSystem::NODE_LENGHT = 24; -const int ReCryptFileSystem::m_indexOfNodeChar[] = { -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 0, 1, -1, 2, 3, 4, 5, 6, 7, 8, -1, 9, 10, 11, 12, - -1, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, -1, -1, -1, 23, -1, -1, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, -1, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, }; -const char ReCryptFileSystem::m_nodeChars[] = { ' ', '!', '#', '$', '%', '&', - '\'', '(', ')', '+', ',', '-', '.', '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '=', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', - 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - '[', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', - 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', - 'z', '{', '|', '}', '~', '\x7f', }; -const int ReCryptFileSystem::m_countNodeChars = - sizeof ReCryptFileSystem::m_nodeChars; +const int ReCryptFileSystem::NODE_LENGHT = 44; +const int ReCryptFileSystem::MARKER_LENGHT = 4; +const int ReCryptFileSystem::CHECKSUM_LENGHT = 16; +const int ReCryptFileSystem::HEADER_LENGTH = sizeof(int64_t) + + ReCryptFileSystem::NODE_LENGHT + + ReCryptFileSystem::MARKER_LENGHT; + +#ifdef WITH_TRACE +static bool s_trace = true; +#endif + /** * Constructor. * @@ -614,17 +606,8 @@ ReFileMetaData&ReFileMetaData::operator =(const ReFileMetaData& source) { ReCryptFileSystem::ReCryptFileSystem(ReFileSystem& hostFileSystem, ReRandomizer& nameRandom, ReRandomizer& contentRandom, ReLogger* logger) : ReFileSystem("cryptfs", logger), - m_host(hostFileSystem), - m_contentRandom(contentRandom), - m_nameRandom(nameRandom), - m_realRandom(), - m_contentSeed(), - m_nameSeed(), - m_buffer() { - m_contentRandom.saveSeed(m_contentSeed); - m_nameRandom.saveSeed(m_nameSeed); - m_buffer.reserve(256); - m_realRandom.nearTrueRandom(); + ReByteScrambler(contentRandom, NODE_LENGHT, sizeof(int32_t), logger), + m_host(hostFileSystem) { } /** @@ -633,121 +616,94 @@ ReCryptFileSystem::ReCryptFileSystem(ReFileSystem& hostFileSystem, ReCryptFileSystem::~ReCryptFileSystem() { } -/** - * Makes a clear text filename. - * - * @param name encrypted filename - * @return the clear text filename +/** Frees resources like open files. */ -QString ReCryptFileSystem::decodeName(const QString& name) { - QString rc = name; - return rc; +void ReCryptFileSystem::close() +{ } /** - * Encodes a block of file content. + * Fills a list with the items of the current directory. * - * @param first true: this is the first block of the file - * @param source the source block - * @param target OUT: the target block
- * Can be identical to source (in place replacement) + * @param matcher the matching processor + * @return the count of the found entries (list.size()) */ -void ReCryptFileSystem::decodeContent(bool first, const QByteArray& source, - QByteArray& target) { +int ReCryptFileSystem::listInfos(const ReIncludeExcludeMatcher& matcher, + ReFileMetaDataList& list) { + return 0; } /** - * Encode a filename. + * Creates a directory. * - * Method: - *
  • Invert the name without extension (first char becomes the last), - * add the extension
  • - *
  • Replace the "unconvertable" chars (> 127) into "%xx" ('%' with 2 hexdigits)
  • - *
  • exchange the char with a value generated by the pseudo random generator
  • - *
- * @param name clear text filename - * @return the encrypted filename - */ -QByteArray& ReCryptFileSystem::encodeName(const QByteArray& node) { - QByteArray rc; - int length = node.length(); - int nameLength = rc.lastIndexOf('.'); - if (nameLength < 0) - nameLength = node.length(); - const char* src = node.constData(); - unsigned char cc; - int ix2 = nameLength - 1; - for (int ix = 0; ix < length; ix++) { - cc = (unsigned char) src[ix >= nameLength ? ix : ix2--]; - if (cc != ESC && cc < 128) { - m_buffer.append(cc); - } else { - m_buffer.append(ESC); - char hex[3]; - snprintf(hex, sizeof hex, "%02x", cc); - m_buffer.append(hex, 2); - } - } - m_nameRandom.reset(); - char* trg = m_buffer.data(); - int pred = 0; - for (int ix = 0; ix < length; ix++) { - int ix2 = (m_indexOfNodeChar[*trg] + pred - + m_nameRandom.nextInt(m_countNodeChars - 1)) % m_countNodeChars; - *trg = m_nodeChars[ix2]; - pred = ix2; - } - return m_buffer; + * @param node the name without path (in the current directory) + * @return EC_SUCCESS or error code + */ +ReFileSystem::ErrorCode ReCryptFileSystem::makeDir(const QString& node) { + return EC_SUCCESS; } /** - * Encodes a buffer of file content. + * Reads a part of a file into a buffer. * - * @param first true: this is the first block of the file - * @param source the source buffer - * @param target OUT: the target buffer - */ -void ReCryptFileSystem::encodeContent(bool first, const QByteArray& source, - QByteArray& target) { - target.resize(0); - if (first) { - int64_t random = m_realRandom.nextInt64(); - // first block contains the random value and the node name of the file: - target.reserve(source.length() + sizeof(random) + 24); - target.fill(' ', sizeof(random) + 24); - memcpy(target.data(), &random, sizeof random); - } - int64_t* trg = reinterpret_cast(target.data() + target.length()); - target.resize(target.length() + source.length()); - int count = source.length() / sizeof(int64_t); - const int64_t* src = reinterpret_cast(target.constData()); - int64_t last = 0; - - for (int ix = 0; ix < count; ix++) { - last = *trg++ = *src++ ^ m_contentRandom.nextInt64() ^ last; - } - int ixMax = source.length() % sizeof(int64_t); - if (ixMax != 0){ - char* trg2 = reinterpret_cast(trg); - char last2 = (char) last; - const char* src2 = reinterpret_cast(src); - for (int ix = 0; ix <= ixMax; ix++){ - last2 = *trg2++ = *src2++ ^ m_contentRandom.nextChar() ^ last2; - } - } + * @param source the file to read (inside the current directory) + * @param offset first position to read + * @param size number of bytes to read + * @param buffer OUT: content of the file + * @return EC_SUCCESS or error code + */ +ReFileSystem::ErrorCode ReCryptFileSystem::read(const ReFileMetaData& source, + int64_t offset, int size, QByteArray& buffer) { + return EC_SUCCESS; } -int ReCryptFileSystem::listInfos(const ReIncludeExcludeMatcher& matcher, - ReFileMetaDataList& list) { +/** Removes a file or directory. + * @param node the properties ot the node (in the current directory) + * @return EC_SUCCESS or error code + */ +ReFileSystem::ErrorCode ReCryptFileSystem::remove(const ReFileMetaData& node) +{ + return EC_SUCCESS; } -ReFileSystem::ErrorCode ReCryptFileSystem::makeDir(const QString& node) { +/** + * Sets the current directory. + * + * @param path relative or absolute path. If absolute it must be part of the + * base path + * @return EC_SUCCESS or error code + */ +ReFileSystem::ErrorCode ReCryptFileSystem::setDirectory(const QString& path) +{ + return EC_SUCCESS; } -ReFileSystem::ErrorCode ReCryptFileSystem::read(const ReFileMetaData& source, - int64_t offset, int size, QByteArray& buffer) { +/** + * Sets the properties of a file in the current directory. + * + * @param source the properties to copy + * @param target the properties of the file to change + * @param force true: try to change rights to enable + * other changes
+ * false: current rights will be respected + * @return EC_SUCCESS or error code + */ +ReFileSystem::ErrorCode ReCryptFileSystem::setProperties(const ReFileMetaData& source, + ReFileMetaData& target, bool force) +{ + return EC_SUCCESS; } +/** + * Writes a buffer to a file. + * + * @param node the file to write (without path, inside the current directory) + * @param offset first position to write + * @param buffer content to write + * @return EC_SUCCESS or error code + */ ReFileSystem::ErrorCode ReCryptFileSystem::write(const QString& target, int64_t offset, const QByteArray& buffer) { + return EC_SUCCESS; } + diff --git a/os/ReFileSystem.hpp b/os/ReFileSystem.hpp index 0988bfa..90d67f2 100644 --- a/os/ReFileSystem.hpp +++ b/os/ReFileSystem.hpp @@ -55,6 +55,8 @@ public: EC_ALREADY_EXISTS, EC_NOT_EXISTS, EC_RENAME, + EC_HEADER_LENGTH, + EC_MARKER, }; public: @@ -193,40 +195,31 @@ protected: * If a file content is copied / moved to the base filesystem the content * will be encrypted. In the other direction the file content will be decrypted. */ -class ReCryptFileSystem: ReFileSystem { +class ReCryptFileSystem: public ReFileSystem, protected ReByteScrambler { public: - static const char ESC; static const int NODE_LENGHT; + static const int HEADER_LENGTH; + static const int CHECKSUM_LENGHT; + static const int MARKER_LENGHT; public: ReCryptFileSystem(ReFileSystem& hostFileSystem, ReRandomizer& nameRandom, ReRandomizer& contentRandom, ReLogger* logger); ~ReCryptFileSystem(); public: - QString decodeName(const QString& name); - void decodeContent(bool first, const QByteArray& source, QByteArray& target); - QString encodeName(const QString& name); - QByteArray& encodeName(const QByteArray& name); - void encodeContent(bool first, const QByteArray& source, QByteArray& target); +public: + virtual void close(); virtual int listInfos(const ReIncludeExcludeMatcher& matcher, ReFileMetaDataList& list); virtual ErrorCode makeDir(const QString& node); virtual ErrorCode read(const ReFileMetaData& source, int64_t offset, int size, QByteArray& buffer); + virtual ErrorCode remove(const ReFileMetaData& node); + virtual ErrorCode setDirectory(const QString& path); + virtual ErrorCode setProperties(const ReFileMetaData& source, ReFileMetaData& target, bool force); virtual ErrorCode write(const QString& target, int64_t offset, const QByteArray& buffer); - protected: ReFileSystem& m_host; - ReRandomizer& m_contentRandom; - ReRandomizer& m_nameRandom; - ReKISSRandomizer m_realRandom; - QByteArray m_contentSeed; - QByteArray m_nameSeed; - QByteArray m_buffer; -public: - static const int m_indexOfNodeChar[]; - static const char m_nodeChars[]; - static const int m_countNodeChars; }; #endif /* OS_REFILESYSTEM_HPP_ */ diff --git a/remodules.hpp b/remodules.hpp index 3f5aff9..35a8073 100644 --- a/remodules.hpp +++ b/remodules.hpp @@ -33,6 +33,7 @@ enum { LOC_FILETREE, LOC_STATESTORAGE, // 120 LOC_FILESYSTEM, + LOC_RANDOMIZER, }; #define LOC_FIRST_OF(moduleNo) (moduleNo*100+1) class RplModules { -- 2.39.5