]> gitweb.hamatoma.de Git - reqt/commitdiff
ReRandomizer works and is tested
authorhama <hama@siduction.net>
Sun, 11 Oct 2015 23:30:44 +0000 (01:30 +0200)
committerhama <hama@siduction.net>
Sun, 11 Oct 2015 23:30:44 +0000 (01:30 +0200)
base/ReRandomizer.cpp
base/ReRandomizer.hpp
cunit/allTests.cpp
cunit/cuReFileSystem.cpp
cunit/cuReRandomizer.cpp
os/ReFileSystem.cpp
os/ReFileSystem.hpp

index a2afb578663d14d215028da698158a5b5ca9b500..ab67d853b0d13bdeb57e79d8b4a73a79d4120612 100644 (file)
@@ -44,6 +44,59 @@ inline int abs(int x) {
 }
 #endif
 
+/**
+ * Builds a number from a text by hasing.
+ *
+ * Conditions:
+ * <ul><li>It should be difficult to restore the text from the hash.</li>
+ * <li>Same text must return the same hash value.</li>
+ * <li>All bits should be set from any text (except the empty text)</li>
+ * </ul>
+ *
+ * @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_t *>(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:
- * <ul><li>It should be difficult to restore the text from the hash.</li>
- * <li>Same text must return the same hash value.</li>
- * <li>All bits should be set from any text (except the empty text)</li>
- * </ul>
- *
- * @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<const seed_t*>(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_t*>(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<char*>(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 <code>setSeed()</code>.
  *
@@ -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<seed_t*>(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 <code>saveSeed()</code>.
+ *
+ * @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 <code>restoreSeed()</code>
+ *
+ * @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);
index fdb4e21e5bd66673764cec71392511c27c80ecbc..b0d1286286d9d508142f9235005fd117aa5f32c0 100644 (file)
@@ -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;
index 4bf3cf045b219fa2615a0381cb4c3040ecd5148e..13f4fa2ed95610cc5220ea59e5de61be909c4571 100644 (file)
@@ -92,8 +92,8 @@ static void testOs() {
        testReFileSystem();
 }
 void allTests() {
-       testBase();
        testOs();
+       testBase();
        testGui();
        if (s_allTest) {
                testBase();
index 39abdcbd553f7552fd17b7a5dba406ca04bdf45c..29072938e97c417eddc7e03ab63bd44c91638ee9 100644 (file)
@@ -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();
index 988acf4bc03d7ac260cfae41355b783ad7d503c7..93d7e1b9b1390bf88a9d3d9bbedfbf3b8c1fc153 100644 (file)
@@ -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() {
index 49a4233d36fd3671a46ea779c6dae627b479d70a..9df7bcb8c33592996a1eed59b874eb474fa25fd0 100644 (file)
@@ -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<br>
+ *                                     Can be identical to <code>source</code> (in place replacement)
+ */
 void ReCryptFileSystem::decodeContent(const QByteArray& source,
     QByteArray& target) {
 
 }
 
+/**
+ * Encode a filename.
+ *
+ * Method:
+ * <ul><li>Invert the name without extension (first char becomes the last),
+ * add the extension</li>
+ * <li>Replace the "unconvertable" chars (> 127) into "%xx" ('%' with 2 hexdigits)</li>
+ * <li>exchange the char with a value generated by the pseudo random generator</li>
+ * </ul>
+ * @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<int64_t*>(target.data());
+       int64_t last = m_trueRandom.nextInt64();
+       for (int ix = 0; ix < count; ix++) {
+               last = *target ^= m_contentRandom.nextInt64() ^ last;
+       }
 
 }
 
index b3daa0f57d64cf3053cc0eeabf4e116108382323..6f207c001c4bdf7f3ec595656b88e0cea72cfb21 100644 (file)
@@ -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;