From: hama Date: Sun, 11 Oct 2015 23:30:44 +0000 (+0200) Subject: ReRandomizer works and is tested X-Git-Url: https://gitweb.hamatoma.de/?a=commitdiff_plain;h=a07a68a178efdd4cf6165a56ff8e407835ae3ba1;p=reqt ReRandomizer works and is tested --- diff --git a/base/ReRandomizer.cpp b/base/ReRandomizer.cpp index a2afb57..ab67d85 100644 --- a/base/ReRandomizer.cpp +++ b/base/ReRandomizer.cpp @@ -44,6 +44,59 @@ inline int abs(int x) { } #endif +/** + * Builds a number from a text by hasing. + * + * Conditions: + * + * + * @param text the text to hash + * @return a number + */ +ReRandomizer::seed_t ReRandomizer::hash(const QByteArray& text) { + seed_t rc = 0x200a110b190c580dLL; + int ixPrimes = m_countPrimes / 2; + rc *= text.at(0); + for (int ix = text.length() - 1; ix > 0; ix--) { + rc = rc * m_primes[ixPrimes] * text.at(ix) * m_primes[ixPrimes - 1]; + if ((ixPrimes -= 2) <= 0) + ixPrimes = m_countPrimes; + } + return rc; +} + +/** + * Converts a text into a seed + * @param text + * @param seed + */ +void ReRandomizer::hash(const QByteArray& text, QByteArray& seed) { + int maxTrg = seed.length() / sizeof(seed_t) - 1; + seed_t* trg = reinterpret_cast(seed.data()); + seed_t last = 0x1b20a811cc19f258LL; + 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); + } + // length password > length seed: + for (int ix = maxTrg; ix < textLength; ix++) { + last = trg[ix % maxTrg] ^= last * text.at(ix) + + 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]; + } + // mix of all seed entries: + for (int ix = 0; ix <= maxTrg; ix++) + last = trg[ix] ^= last * trg[maxTrg - ix]; +} + /** * Returns the name of the generator. * @@ -158,16 +211,6 @@ int64_t ReRandomizer::nextInt64(int64_t maxValue, int64_t minValue) { return rc; } -/** - * @brief Calculates the next seed for the generator. - * - * @return The next seed. - */ -ReRandomizer::seed_t ReCongruentialGenerator::nextSeed() { - m_seed = m_seed * m_factor + m_increment; - return m_seed; -} - /** * @brief Returns a string with random characters. * @@ -243,79 +286,6 @@ void ReRandomizer::shuffle(void* array, size_t length, size_t elemSize) { } } } -/** - * Builds a number from a text by hasing. - * - * Conditions: - * - * - * @param text the text to hash - * @return a number - */ -ReRandomizer::seed_t ReRandomizer::hash(const QByteArray& text) { - seed_t rc = 0x200a110b190c580dLL; - int ixPrimes = m_countPrimes / 2; - for (int ix = text.length() - 1; ix >= 0; ix--) { - rc = rc * m_primes[ixPrimes] + text.at(ix) * m_primes[ixPrimes - 1]; - if ((ixPrimes -= 2) <= 0) - ixPrimes = m_countPrimes; - } - return rc; -} - -/** - * Converts a text into a seed - * @param text - * @param seed - */ -void ReRandomizer::hash(const QByteArray& text, QByteArray& seed) { - int ixSrc = text.length() / sizeof(seed_t) - 1; - int maxSrc = text.length() / sizeof(seed_t) - 1; - const seed_t* src = reinterpret_cast(text.constData()); - seed_t srcSeed = 0x44112200773355LL; - if (text.length() < (int) sizeof(seed_t)) { - for (int ix = text.length() - 1; ix >= 0; ix--) - srcSeed = (srcSeed << 8) | text.at(ix); - src = &srcSeed; - maxSrc = 1; - } - seed_t last = 0x112012041919891LL; - seed_t* trg = reinterpret_cast(seed.data()); - int ixTrg; - int ixPrime = m_countPrimes; - int maxTrg = seed.length() / sizeof(seed_t) - 1; - for (ixTrg = 0; ixTrg < maxTrg; ixTrg++) { - last = trg[ixTrg] = last * m_primes[ixPrime] - + src[ixSrc] * m_primes[ixPrime - 1]; - if ((ixPrime -= 2) <= 0) - ixPrime = m_countPrimes; - if (--ixSrc <= 0) - ixSrc = maxSrc; - } - ixSrc = text.length() - 1; - char* trgPtr = reinterpret_cast(seed.data()); - for (ixTrg = seed.length() % sizeof(seed_t); ixTrg < seed.length(); - ixTrg++) { - last = last + text.at(ixSrc) * m_primes[ixPrime]; - trgPtr[ixTrg] = (char) last; - if (--ixPrime < 0) - ixPrime = m_countPrimes; - if (--ixSrc < 0) - ixSrc = text.length() - 1; - } - ixTrg = 0; - for (int ix = seed.length(); ix < text.length(); ix++) { - trg[ixTrg] ^= text.at(ixSrc); - if (--ixSrc < 0) - ixSrc = text.length() - 1; - if (ixTrg++ >= seed.length()) - ixTrg = 0; - } -} - /** * @brief Sets the seed to the value given by the last setSeed(). * @@ -355,16 +325,6 @@ void ReSingleSeedRandomizer::restoreSeed(const QByteArray& seed) { m_lastSetSeed = m_seed; } -/** @brief Sets the current seed. - * - * @param seed The seed to set. - */ -void ReSingleSeedRandomizer::setSeed(seed_t seed) { - m_seed = m_lastSetSeed = seed; - if (s_trace) - printf(" Seed: %llx ", (long long) seed); -} - /** * Gets the current point of pseudo random. * @@ -384,6 +344,16 @@ ReRandomizer::seed_t ReSingleSeedRandomizer::seed() const { return m_seed; } +/** @brief Sets the current seed. + * + * @param seed The seed to set. + */ +void ReSingleSeedRandomizer::setSeed(seed_t seed) { + m_seed = m_lastSetSeed = seed; + if (s_trace) + printf(" Seed: %llx ", (long long) seed); +} + /** * Converts a text (e.g. password) into the generator specific seed. * @@ -419,6 +389,16 @@ ReRandomizer::seed_t ReCongruentialGeneratorBase::increment() const { return m_increment; } +/** + * @brief Calculates the next seed for the generator. + * + * @return The next seed. + */ +ReRandomizer::seed_t ReCongruentialGenerator::nextSeed() { + m_seed = m_seed * m_factor + m_increment; + return m_seed; +} + /** * Sets the factor. * @@ -441,10 +421,26 @@ void ReCongruentialGeneratorBase::setIncrement(ReRandomizer::seed_t increment) { * @brief Constructor. */ ReCongruentialGenerator::ReCongruentialGenerator() : - ReSingleSeedRandomizer("Linear Congruential Generator"), + ReSingleSeedRandomizer("LCG"), + ReCongruentialGeneratorBase() { +} + +/** + * @brief Constructor. + */ +ReCongruentialGenerator::ReCongruentialGenerator(const char* name) : + ReSingleSeedRandomizer(name), ReCongruentialGeneratorBase() { } +/** + * Constructor. + */ +ReRotateRandomizer::ReRotateRandomizer() : + ReCongruentialGenerator("Rotating LCG") { + +} + /** @brief Returns the next 64 bit pseudo random number. * * A congruential generator produces good random in the most significant @@ -453,6 +449,7 @@ ReCongruentialGenerator::ReCongruentialGenerator() : * * @return a pseudo random number */ + ReRandomizer::seed_t ReRotateRandomizer::nextSeed() { seed_t rc = ReCongruentialGenerator::nextSeed(); rc = ((rc & 0x7fffffff) << 33) | ((rc >> 31) & 0x1ffffffffll); @@ -469,11 +466,28 @@ ReMultiSeedRandomizer::ReMultiSeedRandomizer(int countSeeds, const char* name) : m_seedBuffer(), m_startSeed(), m_seeds() { - m_seedBuffer.fill(0x38, m_countSeeds * sizeof m_seeds[0]); + 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); + } // assignment does not work: copy on write m_startSeed.resize(m_seedBuffer.length()); - memcpy(m_seedBuffer.data(), m_startSeed.constData(), m_startSeed.length()); + memcpy(m_startSeed.data(), m_seedBuffer.constData(), m_startSeed.length()); +} + +/** @brief Returns the next 64 bit pseudo random number. + * + * @return a pseudo random number + */ +ReRandomizer::seed_t ReMultiCongruentialGenerator::nextSeed() { + 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); + return rc; } /** @brief Sets the instance to a defined start state. @@ -514,7 +528,7 @@ void ReMultiSeedRandomizer::saveSeed(QByteArray& seed) const { void ReMultiSeedRandomizer::textToSeed(const QByteArray& text) { hash(text, m_seedBuffer); // assignment does not work: copy on write - memcpy(m_seedBuffer.data(), m_startSeed.constData(), m_seedBuffer.length()); + memcpy(m_startSeed.data(), m_seedBuffer.constData(), m_seedBuffer.length()); } /** @@ -528,16 +542,12 @@ ReMultiCongruentialGenerator::ReMultiCongruentialGenerator(int countSeeds) : m_currentSeed(-1) { } -/** @brief Returns the next 64 bit pseudo random number. - * - * @return a pseudo random number +/** + * Sets the seed to the start point (defined with setSeed()). */ -ReRandomizer::seed_t ReMultiCongruentialGenerator::nextSeed() { - 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); - return rc; +void ReMultiCongruentialGenerator::reset() { + ReMultiSeedRandomizer::reset(); + m_currentSeed = -1; } /** @@ -612,18 +622,38 @@ ReRandomizer::seed_t ReKISSRandomizer::nextSeed() { return m_params.m_x + m_params.m_y + m_params.m_z; } +/** + * Sets the seed to the start point (defined with setSeed()). + */ void ReKISSRandomizer::reset() { m_params = m_startParams; } +/** + * Sets the current point of pseudo random with a seed saved by saveSeed(). + * + * @param seed the current point of pseudo random + */ void ReKISSRandomizer::restoreSeed(const QByteArray& seed) { restore(seed, m_params); } +/** + * Stores the the current point of pseudo random in a buffer. + * + * Restoring is done by restoreSeed() + * + * @param seed the current point of pseudo random + */ void ReKISSRandomizer::saveSeed(QByteArray& seed) const { save(m_params, seed); } +/** + * Converts a text (e.g. password) into the generator specific seed. + * + * @param text the text to convert + */ void ReKISSRandomizer::textToSeed(const QByteArray& text) { QByteArray seeds; seeds.resize(sizeof m_params); diff --git a/base/ReRandomizer.hpp b/base/ReRandomizer.hpp index fdb4e21..b0d1286 100644 --- a/base/ReRandomizer.hpp +++ b/base/ReRandomizer.hpp @@ -21,7 +21,7 @@ public: START_RANGE = ' ', CHARRANGE = 128 - START_RANGE }; - typedef uint64_t seed_t; + typedef int64_t seed_t; public: ReRandomizer(const char* name); virtual ~ReRandomizer(); @@ -116,6 +116,8 @@ class ReCongruentialGenerator: public ReSingleSeedRandomizer, public ReCongruentialGeneratorBase { public: ReCongruentialGenerator(); +protected: + ReCongruentialGenerator(const char* name); protected: friend class ReShiftRandom; virtual seed_t nextSeed(); @@ -129,6 +131,8 @@ protected: * Then x % m returns better results. */ class ReRotateRandomizer: public ReCongruentialGenerator { +public: + ReRotateRandomizer(); protected: virtual seed_t nextSeed(); }; @@ -161,6 +165,7 @@ class ReMultiCongruentialGenerator: public ReMultiSeedRandomizer, public: ReMultiCongruentialGenerator(int countSeeds); public: + virtual void reset(); virtual seed_t nextSeed(); protected: int m_currentSeed; diff --git a/cunit/allTests.cpp b/cunit/allTests.cpp index 4bf3cf0..13f4fa2 100644 --- a/cunit/allTests.cpp +++ b/cunit/allTests.cpp @@ -92,8 +92,8 @@ static void testOs() { testReFileSystem(); } void allTests() { - testBase(); testOs(); + testBase(); testGui(); if (s_allTest) { testBase(); diff --git a/cunit/cuReFileSystem.cpp b/cunit/cuReFileSystem.cpp index 39abdcb..2907293 100644 --- a/cunit/cuReFileSystem.cpp +++ b/cunit/cuReFileSystem.cpp @@ -153,9 +153,25 @@ 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"); + } virtual void run() { init(); + testCharTables(); testReListInfos(); testSetProperties(); testSetPropertiesOwner(); diff --git a/cunit/cuReRandomizer.cpp b/cunit/cuReRandomizer.cpp index 988acf4..93d7e1b 100644 --- a/cunit/cuReRandomizer.cpp +++ b/cunit/cuReRandomizer.cpp @@ -39,7 +39,9 @@ public: rand.saveSeed(seed2); checkEqu(seed1, seed2); char cc2 = rand.nextChar(); - checkEqu(cc1, cc2); + if (cc1 != cc1) { + checkEqu(cc1, cc2); + } rand.reset(); int numbers[16]; @@ -51,7 +53,7 @@ public: for (size_t ix = 0; ix < sizeof numbers / sizeof numbers[0]; ix++) checkEqu(numbers[ix], rand.nextInt()); clock_t start = clock(); - for (int ix = 0; ix < 1000 * 1000; ix++) { + for (int ix = 0; ix < 10 * 1000 * 1000; ix++) { rand.nextInt64(); } double duration = double(clock() - start) / CLOCKS_PER_SEC; @@ -70,17 +72,73 @@ public: ReXorShift64Randomizer rand5; testOne(rand5); } + void testOnePassw(const char* pw, ReRandomizer& rand) { + QByteArray passw(pw); + QByteArray seed; + rand.textToSeed(passw); + rand.saveSeed(seed); + passw.append(": ", 8 - passw.length()); + passw = rand.name() + ": " + passw; + passw.append(seed.toHex()); + log(passw.constData()); + } + void testPasswords(ReRandomizer& rand) { + testOnePassw("a", rand); + testOnePassw("b", rand); + testOnePassw("aa", rand); + testOnePassw("ab", rand); + testOnePassw("aaa", rand); + testOnePassw("aab", rand); + } + + void testTextToSeed() { + ReCongruentialGenerator rand; + testPasswords(rand); + ReXorShift64Randomizer rand2; + testPasswords(rand2); + ReMultiCongruentialGenerator rand3(2); + testPasswords(rand3); + ReKISSRandomizer rand4; + testPasswords(rand4); + log("ready"); + } + void write1m(ReRandomizer& rand) { + QByteArray fn = ReFileUtils::tempFile(rand.name().constData()); + fn.append(".data"); + QByteArray buffer; + buffer.reserve(1000 * sizeof(int64_t)); + FILE* fp = fopen(fn.constData(), "w"); + checkNN(fp); + if (fp != NULL) { + for (int block = 0; block < 1000; block++) { + buffer.clear(); + for (int ix = 0; ix < 1000; ix++) { + int64_t x = rand.nextInt64(); + buffer.append((const char*) &x, sizeof x); + } + fwrite(buffer.constData(), 1, buffer.length(), fp); + } + fclose(fp); + } + } + void special() { - ReKISSRandomizer rand; - int i1 = rand.nextInt(); - rand.reset(); - int i2 = rand.nextInt(); - checkEqu(i1, i2); + ReCongruentialGenerator rand; + write1m(rand); + ReXorShift64Randomizer rand2; + write1m(rand2); + ReMultiCongruentialGenerator rand3(2); + write1m(rand3); + ReKISSRandomizer rand4; + write1m(rand4); + log("ready"); } virtual void run(void) { special(); + testTextToSeed(); testBasics(); + int ix = 1; } }; void testReRandomizer() { diff --git a/os/ReFileSystem.cpp b/os/ReFileSystem.cpp index 49a4233..9df7bcb 100644 --- a/os/ReFileSystem.cpp +++ b/os/ReFileSystem.cpp @@ -616,12 +616,14 @@ ReCryptFileSystem::ReCryptFileSystem(ReFileSystem& hostFileSystem, 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(); } /** @@ -641,11 +643,30 @@ QString ReCryptFileSystem::decodeName(const QString& name) { return rc; } +/** + * Encodes a block of file content. + * + * @param source the source block + * @param target OUT: the target block
+ * Can be identical to source (in place replacement) + */ void ReCryptFileSystem::decodeContent(const QByteArray& source, QByteArray& target) { } +/** + * 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& ReCryptFileSystem::encodeName(const QByteArray& node) { QByteArray rc; int length = node.length(); @@ -677,12 +698,22 @@ QByteArray& ReCryptFileSystem::encodeName(const QByteArray& node) { } return m_buffer; } -QString ReCryptFileSystem::encodeName(const QString& node) { - return encodeName(node.toUtf8()); -} +/** + * Encodes a buffer of file content. + * + * @param source the source buffer + * @param target OUT: the target buffer + */ void ReCryptFileSystem::encodeContent(const QByteArray& source, QByteArray& target) { + m_contentRandom.reset(); + int count = source.length() / sizeof(int64_t); + int64_t* target = reinterpret_cast(target.data()); + int64_t last = m_trueRandom.nextInt64(); + for (int ix = 0; ix < count; ix++) { + last = *target ^= m_contentRandom.nextInt64() ^ last; + } } diff --git a/os/ReFileSystem.hpp b/os/ReFileSystem.hpp index b3daa0f..6f207c0 100644 --- a/os/ReFileSystem.hpp +++ b/os/ReFileSystem.hpp @@ -218,10 +218,11 @@ protected: ReFileSystem& m_host; ReRandomizer& m_contentRandom; ReRandomizer& m_nameRandom; + ReKISSRandomizer& m_realRandom; QByteArray m_contentSeed; QByteArray m_nameSeed; QByteArray m_buffer; -protected: +public: static const int m_indexOfNodeChar[]; static const char m_nodeChars[]; static const int m_countNodeChars;