From b657f6887940667d4ecd52af8a5091bdb404ab03 Mon Sep 17 00:00:00 2001 From: hama Date: Wed, 21 Oct 2015 00:07:41 +0200 Subject: [PATCH] ReRandomizer::shuffle corrected, project reprime --- appl/reprime/.gitignore | 73 +++++++ appl/reprime/Prime.cpp | 151 +++++++++++++ appl/reprime/Prime.hpp | 34 +++ appl/reprime/main.cpp | 19 ++ appl/reprime/reprime.pro | 20 ++ base/ReRandomizer.cpp | 255 +++++++++++++++++----- base/ReRandomizer.hpp | 17 +- cunit/cuReRandomizer.cpp | 8 +- cunit/cunit.pro | 6 +- os/ReCryptFileSystem.cpp | 456 +++++++++++++++++++++++++++++++++++++++ os/ReCryptFileSystem.hpp | 112 ++++++++++ os/ReFileSystem.cpp | 147 ++----------- os/ReFileSystem.hpp | 41 +--- os/reos.hpp | 1 + remodules.hpp | 1 + 15 files changed, 1106 insertions(+), 235 deletions(-) create mode 100644 appl/reprime/.gitignore create mode 100644 appl/reprime/Prime.cpp create mode 100644 appl/reprime/Prime.hpp create mode 100644 appl/reprime/main.cpp create mode 100644 appl/reprime/reprime.pro create mode 100644 os/ReCryptFileSystem.cpp create mode 100644 os/ReCryptFileSystem.hpp diff --git a/appl/reprime/.gitignore b/appl/reprime/.gitignore new file mode 100644 index 0000000..5439c79 --- /dev/null +++ b/appl/reprime/.gitignore @@ -0,0 +1,73 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + + diff --git a/appl/reprime/Prime.cpp b/appl/reprime/Prime.cpp new file mode 100644 index 0000000..6d46371 --- /dev/null +++ b/appl/reprime/Prime.cpp @@ -0,0 +1,151 @@ +/* + * Prime.cpp + * + * Created on: Oct 8, 2015 + * Author: kawi + */ +#include "math.h" +#include "stdlib.h" +#include "math.h" +#include "stdio.h" +#include "unistd.h" +#include "time.h" +#include "assert.h" +#include "base/rebase.hpp" +#include "Prime.hpp" + +Prime::Prime(int64_t from, int count) : + m_from(from), + m_count(count), + m_primes(NULL), + m_sizePrimes(0), + m_countPrimes(0), + m_maxStoredPrimes(0){ + m_maxStoredPrimes = int (sqrt((double) m_from / 3 / log(sqrt(m_from)))) + 100; + m_sizePrimes = m_maxStoredPrimes + 10; + fprintf(stderr, "Storing %d primes\n", m_sizePrimes); + m_primes = new int64_t[m_sizePrimes]; + m_primes[0] = 2; + m_countPrimes = 1; +} + +Prime::~Prime() { +} +void toFile(const char* prefix, int64_t* primes, int count){ + QByteArray fn = QByteArray(prefix) + "." + + QDateTime::currentDateTime().toLocalTime() + .toString("yyyy.MM.dd_hh_mm_ss").toUtf8() + ".txt"; + FILE* fp = fopen(fn.constData(), "w"); + if (fp != NULL){ + fprintf(stderr, "Result in %s\n", fn.constData()); + for (int ix = 0; ix < count; ix++){ + fprintf(fp, "%lldL, // %llx\n", + (long long) primes[ix], (long long) primes[ix]); + } + fclose(fp); + } + +} + +void Prime::calculate() { + int64_t x = lastPrime() * lastPrime(); + int64_t* primes = new int64_t[m_count]; + + assert(x % 2 == 1); + int nPrinted = 0; + while (nPrinted < m_count){ + while (x > 0){ + x -= 2; + bool isPrime = true; + for (int ix = 0; ix < m_countPrimes; ix++){ + int64_t fac = m_primes[ix]; + if (x % fac == 0){ + isPrime = false; + break; + } + } + if (isPrime){ + printf("%lld, // %llx\n", (long long) x, (long long) x); + fflush(stdout); + primes[nPrinted++] = x; + x -= m_from / m_count / 5; + if (x % 2 == 0) + x--; + break; + } + } + } + toFile("primes.sorted", primes, m_count); + ReKISSRandomizer random; + random.nearTrueRandom(); + random.shuffle(primes, m_count, sizeof primes[0]); + toFile("primes.shuffled", primes, m_count); +} + +void Prime::storePrimes() { + clock_t start = clock(); + int counter2 = 0; + for (int64_t x = 3; true; x += 2){ + if (x % (10*1000*1000) == 1){ + fprintf(stderr, "%ld Mio: %8.3f\n", x / (1000*1000), + (clock() - start) / double(CLOCKS_PER_SEC)); + if (counter2++ % 5 == 0) + dump(); + fflush(stderr); + } + bool isPrime = true; + for (int ix = 0; ix < m_countPrimes; ix++){ + int64_t fac = m_primes[ix]; + if (x % fac == 0){ + isPrime = false; + break; + } else if (fac * fac > x) + break; + } + if (isPrime) { + m_primes[m_countPrimes++] = x; + if (m_countPrimes >= m_maxStoredPrimes || x * x > m_from) + break; + } + } + dump(); +} + +void Prime::dump() { + int64_t last = lastPrime(); + fprintf(stderr, "count primes: %d size primes: %d last prime: %ld lp*lp: %ld\n", + m_countPrimes, m_sizePrimes, last, last * last); +} + +void Prime::run(int argc, char* argv[]){ + int64_t from = 0x82L * 0x10000 * 0x10000 * 10000; //* 0x10000; + int count = 150; + if (argc > 1){ + int64_t lValue; + if (sscanf(argv[1], "0x%lx", &lValue) == 1){ + } else if (sscanf(argv[1], "%ld", &lValue) != 1) + printf("wrong argument 1: %s", argv[1]); + else + from = lValue; + + if (argc > 2){ + int nValue; + if (sscanf(argv[2], "%d", &nValue) != 1) + printf("wrong argument 2: %s", argv[2]); + else + count = nValue; + } + } + + fprintf(stderr, "from: %ld/%lx count: %d\n", from, from, count); + clock_t start = clock(); + Prime prime(from, count); + prime.storePrimes(); + fprintf (stderr, "storePrime: %f sec\n", + double (clock() - start) / CLOCKS_PER_SEC); + prime.dump(); + prime.calculate(); + double duration = double (clock() - start) / CLOCKS_PER_SEC; + fprintf (stderr, "duration: %f sec\n", duration); +} + diff --git a/appl/reprime/Prime.hpp b/appl/reprime/Prime.hpp new file mode 100644 index 0000000..3c4b4f1 --- /dev/null +++ b/appl/reprime/Prime.hpp @@ -0,0 +1,34 @@ +/* + * Prime.hpp + * + * Created on: Oct 8, 2015 + * Author: kawi + */ + +#ifndef PRIME_HPP_ +#define PRIME_HPP_ + +//typedef long long int int64_t; +class Prime { +public: + Prime(int64_t from, int count); + virtual ~Prime(); +public: + void storePrimes(); + void calculate(); + void dump(); + int64_t lastPrime() const { + return m_primes[m_countPrimes - 1]; + } +public: + static void run(int argc, char* argv[]); +private: + int64_t m_from; + int m_count; + int64_t* m_primes; + int m_sizePrimes; + int m_countPrimes; + int m_maxStoredPrimes; +}; + +#endif /* PRIME_HPP_ */ diff --git a/appl/reprime/main.cpp b/appl/reprime/main.cpp new file mode 100644 index 0000000..32f2bfd --- /dev/null +++ b/appl/reprime/main.cpp @@ -0,0 +1,19 @@ +/* + * 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. +*/ + + +#include +#include "Prime.hpp" +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + Prime::run(argc, argv); + exit(0); + return a.exec(); +} + diff --git a/appl/reprime/reprime.pro b/appl/reprime/reprime.pro new file mode 100644 index 0000000..3e275a8 --- /dev/null +++ b/appl/reprime/reprime.pro @@ -0,0 +1,20 @@ +QT += core network gui +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = reprime + +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + +INCLUDEPATH = ../.. + +SOURCES += main.cpp \ + ../../base/ReLogger.cpp \ + ../../base/ReRandomizer.cpp \ + ../../base/ReStringUtils.cpp \ + ../../base/ReException.cpp \ + Prime.cpp + + diff --git a/base/ReRandomizer.cpp b/base/ReRandomizer.cpp index 25e51cb..cda4079 100644 --- a/base/ReRandomizer.cpp +++ b/base/ReRandomizer.cpp @@ -20,15 +20,133 @@ enum { const char ReNameScrambler::ESC = '%'; -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 }; +const int64_t ReRandomizer::m_primes[] = { + 4794328877860651L, // 11086aadb3872b + 4958110297415603L, // 119d600308dfb3 + 4623102848326049L, // 106cb00308d9a1 + 4891108807597633L, // 1160700308de41 + 4578435188447437L, // 1044100308d8cd + 5546234485817489L, // 13b445585e4091 + 5389897676242243L, // 132615585e3d43 + 4786884267880873L, // 1101a5585e31a9 + 5241005476646707L, // 129eaaadb38f33 + 4734771998022511L, // 10d2400308db6f + 5278228526545621L, // 12c085585e3ad5 + 4652881288245079L, // 1087c5585e2f57 + 5181448596808493L, // 1268800308e32d + 4920887247516739L, // 117b85585e3443 + 5360119236323197L, // 130b000308e77d + 5471788386019861L, // 1370900308ea15 + 4645436678265319L, // 1081000308d9e7 + 4481655258710579L, // fec0aadb38233 + 5523900655878179L, // 139ff5585e4023 + 5203782426747811L, // 127cd00308e3a3 + 5375008456282711L, // 13188aadb39257 + 5226116256687127L, // 1291200308e417 + 5419676116161323L, // 13412aadb3932b + 5218671646707367L, // 128a5aadb38ea7 + 5136780936929903L, // 123fe00308e26f + 4556101358508169L, // 102fc00308d889 + 5263339306586077L, // 12b2faadb38fdd + 4518878308609331L, // 100de5585e2d33 + 4533767528568833L, // 101b700308d801 + 4764550437941633L, // 10ed55585e3181 + 5509011435918673L, // 13926aadb39551 + 5166559376848937L, // 125af5585e3829 + 4489099868690317L, // ff2d00308d78d + 4727327388042733L, // 10cb7aadb385ed + 5330340796404157L, // 12efeaadb391bd + 4801773487840397L, // 110f300308dc8d + 5397342286222069L, // 132cdaadb392f5 + 5308006966464857L, // 12db9aadb39159 + 5084668667071573L, // 12107aadb38c55 + 4816662707799941L, // 111cbaadb38785 + 4704993558103493L, // 10b72aadb385c5 + 5114447106990601L, // 122b900308e209 + 4712438168083259L, // 10bdf00308db3b + 5479232995999613L, // 137755585e3f7d + 4660325898224963L, // 108e8aadb38543 + 5040001007192867L, // 11e7daadb38b23 + 4972999517375089L, // 11aaeaadb38a71 + 4853885757698843L, // 113e95585e331b + 5315451576444613L, // 12e2600308e6c5 + 5412231506181583L, // 133a65585e3dcf + 5144225546909639L, // 1246a5585e37c7 + 4548656748528367L, // 1028faadb382ef + 4615658238346273L, // 1065eaadb38421 + 5583457535716339L, // 13d6200308ebf3 + 4474210648730791L, // fe545585e2ca7 + 4838996537739323L, // 11310aadb3883b + 4600769018386699L, // 1058600308d90b + 4742216608002253L, // 10d905585e30cd + 4570990578467701L, // 103d4aadb38375 + 5032556397213109L, // 11e115585e35b5 + 5025111787233371L, // 11da500308e05b + 5568568315756819L, // 13c895585e4113 + 5174003986828717L, // 1261baadb38dad + 4675215118184491L, // 109c15585e302b + 5494122215959133L, // 1384e00308ea5d + 4980444127354847L, // 11b1b00308dfdf + 4697548948123739L, // 10b065585e305b + 4779439657901123L, // 10fae00308dc43 + 5129336326950151L, // 12391aadb38d07 + 5464343776040087L, // 1369caadb39497 + 5248450086626447L, // 12a5700308e48f + 4905998027557141L, // 116dfaadb38915 + 5047445617172633L, // 11eea00308e099 + 5345230016363663L, // 12fd75585e3c8f + 5442009946100803L, // 13557aadb39443 + 4630547458305841L, // 107375585e2f31 + 5501566825938893L, // 138ba5585e3fcd + 5077224057091819L, // 1209b5585e36eb + 4913442637536913L, // 1174c00308de91 + 4935776467476299L, // 1189100308df4b + 4541212138548581L, // 102235585e2d65 + 5404786896201841L, // 1333a00308e871 + 5159114766869153L, // 1254300308e2a1 + 5010222567273893L, // 11ccc5585e35a5 + 5531345265857969L, // 13a6baadb395b1 + 4757105827961849L, // 10e6900308dbf9 + 4563545968487959L, // 103685585e2e17 + 4719882778062997L, // 10c4b5585e3095 + 4928331857496557L, // 11824aadb389ed + 5322896186424389L, // 12e925585e3c45 + 5538789875837723L, // 13ad800308eb1b + 4690104338143981L, // 10a9a00308daed + 4943221077456049L, // 118fd5585e34b1 + 4987888737334627L, // 11b875585e3563 + 5300562356485079L, // 12d4d5585e3bd7 + 5367563846302937L, // 1311c5585e3cd9 + 5293117746505229L, // 12ce100308e60d + 5255894696606263L, // 12ac35585e3a37 + 5211227036727601L, // 128395585e3931 + 5285673136525447L, // 12c74aadb39087 + 4526322918589091L, // 1014aaadb382a3 + 4593324408406963L, // 10519aadb383b3 + 5449454556080573L, // 135c400308e9bd + 4995333347314369L, // 11bf3aadb38ac1 + 5107002497010847L, // 1224caadb38c9f + 5382453066262463L, // 131f500308e7bf + 5553679095797237L, // 13bb0aadb395f5 + 4898553417577403L, // 116735585e33bb + 4682659728164237L, // 10a2daadb3858d + 4771995047921369L, // 10f41aadb386d9 + 4585879798427209L, // 104ad5585e2e49 + 5069779447111979L, // 1202f00308e12b + 4861330367678597L, // 11455aadb38885 + 4965554907395353L, // 11a425585e3519 + 5188893206788243L, // 126f45585e3893 + 4831551927759449L, // 112a45585e3259 + 5337785406383909L, // 12f6b00308e725 + 5092113277051363L, // 1217400308e1e3 + 5456899166060341L, // 136305585e3f35 + 5427120726141077L, // 1347f00308e895 + 5270783916565829L, // 12b9c00308e545 + 5561123705777023L, // 13c1d00308eb7f + 4749661217982049L, // 10dfcaadb38661 + 5121891716970409L, // 123255585e37a9 + 5486677605979391L, // 137e1aadb394ff + }; const int ReRandomizer::m_countPrimes = sizeof ReRandomizer::m_primes / sizeof(int); const int ReNameScrambler::m_indexOfNodeChar[] = { -1, -1, -1, -1, -1, -1, -1, @@ -189,6 +307,8 @@ int ReRandomizer::nextInt(int maxValue, int minValue) { maxValue = rc; } seed_t seed = nextSeed64(); + if (minValue >= 0) + seed = abs(seed); if (minValue == maxValue) rc = minValue; else { @@ -260,22 +380,26 @@ const char* ReRandomizer::nextString(int minLength, int maxLength, * * The operation will be done in place: * - * @param array In/Out: The array to shuffle. - * @param length The length of the array. - * @param elemSize The size of one element of the array. + * @param array IN/OUT: the array to shuffle + * @param length the length of the array + * @param elemSize the size of one element of the array + * @param exchanges count of exchanges: two randomly selected entries will be + * exchanged. If <= 0 a default value will be taken: 1.5*length */ -void ReRandomizer::shuffle(void* array, size_t length, size_t elemSize) { +void ReRandomizer::shuffle(void* array, size_t length, size_t elemSize, + int exchanges) { int ii; char* cptr; int* iptr; - int count = length * 3 / 2; - + int64_t* i64ptr; + int count = exchanges <= 0 ? length * 3 / 2 : exchanges; + int maxIx = length - 1; switch (elemSize) { case 1: cptr = (char*) array; for (ii = 0; ii < count; ii++) { - int ix1 = length - nextInt(1, length); - int ix2 = length - nextInt(1, length); + int ix1 =nextInt(maxIx); + int ix2 =nextInt(maxIx); char x = cptr[ix1]; cptr[ix1] = cptr[ix2]; cptr[ix2] = x; @@ -284,20 +408,32 @@ void ReRandomizer::shuffle(void* array, size_t length, size_t elemSize) { case sizeof(int): iptr = (int*) array; for (ii = 0; ii < count; ii++) { - int ix1 = length - nextInt(1, length); - int ix2 = length - nextInt(1, length); + int ix1 =nextInt(maxIx); + int ix2 =nextInt(maxIx); int x = iptr[ix1]; iptr[ix1] = iptr[ix2]; iptr[ix2] = x; } break; + case sizeof(int64_t): + i64ptr = (int64_t*) array; + for (ii = 0; ii < count; ii++) { + int ix1 = nextInt(maxIx); + int ix2 = nextInt(maxIx); + if (i64ptr[ix1] <= 0 || i64ptr[ix2] <= 0) + ix1 += 0; + int64_t x = i64ptr[ix1]; + i64ptr[ix1] = i64ptr[ix2]; + i64ptr[ix2] = x; + } + break; default: { char buffer[0x10000]; assert(elemSize < sizeof buffer); iptr = (int*) array; for (ii = 0; ii < count; ii++) { - int ix1 = length - nextInt(1, length); - int ix2 = length - nextInt(1, length); + int ix1 =nextInt(maxIx); + int ix2 =nextInt(maxIx); char* p1 = ((char*) array) + ix1 * elemSize; char* p2 = ((char*) array) + ix2 * elemSize; memcpy(buffer, p1, elemSize); @@ -518,7 +654,9 @@ ReMultiSeedRandomizer::ReMultiSeedRandomizer(int countSeeds, const char* name) : */ ReRandomizer::seed_t ReMultiCongruentialGenerator::nextSeed64() { m_currentSeed = (m_currentSeed + 1) % m_countSeeds; - seed_t rc = m_seeds[m_currentSeed] * m_factor + m_increment; + int ixFactor = int((m_seeds[m_currentSeed] >> 7) % (m_countPrimes - 1)); + seed_t rc = m_seeds[m_currentSeed] * m_primes[ixFactor] + + (m_primes[ixFactor + 1] >> 1); m_seeds[m_currentSeed] = rc; rc = ((rc & 0x7fffffff) << 33) | ((rc >> 31) & 0x1ffffffffLL); ++m_counter; @@ -729,23 +867,17 @@ void ReKISSRandomizer::textToSeed(const QByteArray& text) { * @param contentRandom a pseudo random generator * @param logger the logger */ -ReByteScrambler::ReByteScrambler(ReRandomizer& contentRandom, - int reservedLength, int markerLength, ReLogger* logger) : +ReByteScrambler::ReByteScrambler(ReRandomizer& contentRandom, 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); } /** @@ -875,20 +1007,24 @@ void ReByteScrambler::encodeContent(const QByteArray& source, /** * 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 + * @param metaInfoLength the length of the "reserved area" + * @param markerLength length of a mark to ensure header's integrity + * @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) +bool ReByteScrambler::initFromHeader(int metaInfoLength, int markerLength, + const QByteArray* header, QByteArray& info) { TRACE("initFromHeader():\n"); bool rc = true; if (header == NULL) header = &m_header; - if (header->length() < m_headerLength ){ + int headerLength = sizeof(int64_t) + markerLength + metaInfoLength; + if (header->length() < headerLength ){ m_logger->logv(LOG_ERROR, LOC_DECODE_CONTENT_1, "header length too small: %d/%d", - header->length(), m_headerLength); + header->length(), headerLength); rc = false; } else { int64_t random = * reinterpret_cast(header->constData()); @@ -896,17 +1032,20 @@ bool ReByteScrambler::initFromHeader(const QByteArray* header, QByteArray& info) m_contentRandom.modifySeed(random); QByteArray marker; marker.append(reinterpret_cast(header->constData()+ sizeof(int64_t)), - m_markerLength); + 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; + if (markerLength > 0){ + m_contentRandom.nextString(markerLength, markerLength, marker2); + if (marker != marker2){ + m_logger->logv(LOG_ERROR, LOC_DECODE_CONTENT_2, "invalid marker: %s / %s", + ReStringUtils::hexDump(marker, markerLength, markerLength).constData(), + ReStringUtils::hexDump(marker2, markerLength, markerLength).constData()); + rc = false; + } } char last = 0x47; - const char* src = reinterpret_cast(header->data() + sizeof (int64_t) + m_markerLength); + const char* src = reinterpret_cast(header->data() + + sizeof (int64_t) + markerLength); int length = *src++; TRACE1("info: Length: %d\n", length); info.resize(0); @@ -924,33 +1063,39 @@ bool ReByteScrambler::initFromHeader(const QByteArray* header, QByteArray& info) /** * Initializes the scrambler header. * + * * Format of the header: *
random (8 byte)
  * marker (m_markerLength byte)
- * reserved (m_reservedLength byte)
+ * reserved (reservedLength byte)
  * 
* - * @param info the content of the "reserved area" + * @param metaInfoLength the length of the "reserved area" + * @param markerLength length of a mark to ensure header's integrity + * @param info the content of the "reserved area". If too few space + * the content will be cut */ -void ReByteScrambler::initHeader(const QByteArray& info) +void ReByteScrambler::initHeader(int metaInfoLength, int markerLength, + const QByteArray& info) { TRACE("initHeader():\n"); int64_t random = m_realRandom.nextSeed64(); m_contentRandom.reset(); m_contentRandom.modifySeed(random); - m_header.fill(' ', m_headerLength); + int headerLength = sizeof(int64_t) + markerLength + metaInfoLength; + m_header.fill(' ', headerLength); * reinterpret_cast(m_header.data()) = random; - if (m_markerLength > 0){ + if (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); + m_contentRandom.nextString(markerLength, markerLength, m_buffer); + memcpy(m_header.data() + sizeof(int64_t), m_buffer, 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); + char* trg = reinterpret_cast(m_header.data() + sizeof (int64_t) + markerLength); + int infoLength = min(info.length(), metaInfoLength - 1); + TRACE2("info: length: %d reserved: %d\n", infoLength, metaInfoLength); *trg++ = infoLength; - for (int ix = 0; ix < infoLength && ix < m_reservedLength; ix++){ + for (int ix = 0; ix < infoLength && ix < metaInfoLength; ix++){ last = *trg++ = m_contentRandom.nextChar() ^ info.at(ix) ^ last; } TRACE_IT(("random: %016lx marker: %s\n", random, diff --git a/base/ReRandomizer.hpp b/base/ReRandomizer.hpp index 4fb334e..c296edb 100644 --- a/base/ReRandomizer.hpp +++ b/base/ReRandomizer.hpp @@ -32,7 +32,8 @@ public: int nextInt(int maxValue = INT_MAX, int minValue = 0); int64_t nextInt64(int64_t maxValue = LLONG_MAX, int64_t minValue = 0); const char* nextString(int minLength, int maxLength, QByteArray& buffer); - void shuffle(void* array, size_t length, size_t elemSize); + void shuffle(void* array, size_t length, size_t elemSize, + int exchanges = -1); public: virtual void dump() { } @@ -75,7 +76,7 @@ protected: int m_counter; public: // the first 125 prime numbers - static const int m_primes[]; + static const int64_t m_primes[]; static const int m_countPrimes; }; @@ -237,22 +238,20 @@ private: */ class ReByteScrambler{ public: - ReByteScrambler(ReRandomizer& contentRandom, - int reservedLength, int markerLength, ReLogger* logger); + ReByteScrambler(ReRandomizer& contentRandom, 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); + void initHeader(int metaInfoLength, int markerLength, + const QByteArray& info = ReStringUtils::m_empty); + bool initFromHeader(int metaInfoLength, int markerLength, + 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; }; diff --git a/cunit/cuReRandomizer.cpp b/cunit/cuReRandomizer.cpp index f840b66..48c8840 100644 --- a/cunit/cuReRandomizer.cpp +++ b/cunit/cuReRandomizer.cpp @@ -198,21 +198,23 @@ public: QByteArray src(content); QByteArray trg; QByteArray trg2; + int markerLength = 4; + int metaInfoLength = 8; ReKISSRandomizer rand; rand.nearTrueRandom(); QByteArray info; rand.nextString(10, 20, info); - scrambler.initHeader(info); + scrambler.initHeader(metaInfoLength, markerLength, info); scrambler.encodeContent(src, trg); QByteArray info2; - scrambler.initFromHeader(NULL, info2); + scrambler.initFromHeader(metaInfoLength, markerLength, NULL, info2); scrambler.decodeContent(trg, trg2); checkEqu(src, trg2); checkT(info.startsWith(info2)); } void testContentEncoding(){ ReKISSRandomizer dataRandom; - ReByteScrambler scrambler(dataRandom, 8, 4, &m_logger); + ReByteScrambler scrambler(dataRandom, &m_logger); checkContent("12345678abc", scrambler); checkContent("8765432112345678ab", scrambler); checkContent("8765432112345678", scrambler); diff --git a/cunit/cunit.pro b/cunit/cunit.pro index 1a2bb9d..8f8bf06 100644 --- a/cunit/cunit.pro +++ b/cunit/cunit.pro @@ -51,11 +51,13 @@ SOURCES += main.cpp \ cuReStateStorage.cpp \ cuReSettings.cpp \ cuReMatcher.cpp \ - allTests.cpp + allTests.cpp \ + ../os/ReCryptFileSystem.cpp HEADERS += \ ../base/ReFile.hpp \ ../base/rebase.hpp \ ../gui/ReEdit.hpp \ ../math/ReMatrix.hpp \ - ../math/remath.hpp + ../math/remath.hpp \ + ../os/ReCryptFileSystem.hpp diff --git a/os/ReCryptFileSystem.cpp b/os/ReCryptFileSystem.cpp new file mode 100644 index 0000000..1af6608 --- /dev/null +++ b/os/ReCryptFileSystem.cpp @@ -0,0 +1,456 @@ +/* + * 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. +*/ + + +#include "base/rebase.hpp" +#include "os/reos.hpp" + +enum { + LOC_ADD_ENTRY_1 = LOC_FIRST_OF(LOC_CRYPTFILESYSTEM), // 12301 + LOC_REMOVE_ENTRY_1, // 12302 + LOC_READ_META_FILE_1, // 12303 + LOC_READ_META_FILE_2, // 12304 + LOC_READ_META_FILE_3, // 12305 + LOC_WRITE_META_1, // 12306 + LOC_WRITE_META_2, // 12307 +}; + +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; +const QString ReCryptFileSystem::NODE_META_DEVICE = ".0"; +const QString ReCryptFileSystem::NODE_META_DIR = ".1"; +const int ReCryptDirectory::MARKER_LENGTH = 4; +const int ReCryptDirectory::META_INFO_LENGTH = sizeof (ReCryptDirectory::MetaInfo_t); +const int ReCryptDirectory::META_DIR_HEADER_LENGTH = sizeof(int64_t) + + ReCryptDirectory::MARKER_LENGTH + ReCryptDirectory::META_INFO_LENGTH; +// space for the struct and the node: +const int ReCryptDirectory::MAX_ENTRY_SIZE = sizeof(ReCryptDirectory::FileEntry_t) + + 512; + +/** + * Constructor. + * + * @param hostFileSystem the filesystem which does the storage (with + * encrypted names and content + * @param nameRandom a pseudo random generator for names + * @param contentRandom a pseudo random generator for content + */ +ReCryptFileSystem::ReCryptFileSystem(ReFileSystem& hostFileSystem, + ReRandomizer& contentRandom, ReLogger* logger) : + ReFileSystem("cryptfs", logger), + ReCryptDirectory(contentRandom, this, logger), + m_host(hostFileSystem) +{ +} + +/** + * Destructor. + */ +ReCryptFileSystem::~ReCryptFileSystem() { +} + +/** Frees resources like open files. + */ +void ReCryptFileSystem::close() +{ +} + +/** + * Fills a list with the items of the current directory. + * + * @param matcher the matching processor + * @return the count of the found entries (list.size()) + */ +int ReCryptFileSystem::listInfos(const ReIncludeExcludeMatcher& matcher, + ReFileMetaDataList& list) { + return 0; +} + +/** + * Creates a directory. + * + * @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; +} + +/** + * Reads a part of a file into a buffer. + * + * @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; +} + +/** 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; +} + +/** + * 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; +} + +/** + * 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; +} + +/** + * Constructor + * + * @param parent the parent filesystem + * @param logger the logger + */ +ReCryptDirectory::ReCryptDirectory(ReRandomizer& contentRandom, + ReCryptFileSystem* parent, ReLogger* logger) : + ReByteScrambler(contentRandom, logger), + m_list(), + m_parent(parent), + m_changed(false), + m_logger(logger), + m_currentNode(), + m_fileBuffer(), + m_entryBuffer(), + m_blockSize(1024 * 1024) +{ + m_fileBuffer.reserve(m_blockSize); + m_entryBuffer.reserve(m_blockSize + MAX_ENTRY_SIZE + 10); +} + +/** + * Destructor. + */ +ReCryptDirectory::~ReCryptDirectory() +{ + if (m_changed) + writeMetaFile(); +} + +/** + * Adds an file entry to the directory. + * + * @param entry the meta data of the file to add + * @return true: success + */ +bool ReCryptDirectory::addEntry(ReFileMetaData& entry) +{ + bool rc = true; + if (find(entry.m_node)){ + rc = ! m_logger->logv(LOG_ERROR, LOC_ADD_ENTRY_1, "file exists yet: %s", + entry.m_node.constData()); + } else { + m_list.append(entry); + m_changed = true; + } + return rc; +} + +/** + * Makes a node name from an id. + * + * @param id a unique number of the file + * @return a unique node name derived from the id + */ +QString ReCryptDirectory::buildHostedNode(int id) const{ + QByteArray rc; + static const int BASE = 'Z' - 'A' + 1; + while(id > 0){ + rc.insert(0, 'a' + id % BASE); + id /= BASE; + } + return QString(rc); +} + +/** + * Makes an id from an node name in the hosted filesystem. + * + * @param hostedNode the node to convert + * @return -1: invalid node name
+ * otherwise: the id of the node + */ +int ReCryptDirectory::buildId(const QString& hostedNode) const{ + int id = 0; + static const int BASE = 'Z' - 'A' + 1; + for (int ix = 0; id >= 0 && ix < hostedNode.length(); ix++){ + int digit = hostedNode.at(ix).unicode() - QChar('a').unicode(); + if (digit < 0 || digit >= BASE) + id = -1; + else + id = id*BASE + digit; + } + return id; +} + +/** + * Search an file entry by name. + * + * @param node the filename without path + * @return NULL: not found
+ * otherwise: the found file + * + */ +const ReFileMetaData* ReCryptDirectory::find(const QString& node) const +{ + const ReFileMetaData* rc = NULL; + ReFileMetaDataList::const_iterator it; + for (it = m_list.cbegin(); it != m_list.cend(); ++it){ + if (it->m_node == node){ + rc = &*it; + } + } + return rc; +} + +/** + * Removes an entry given by the name. + * + * @param node the filename without path + * @return + */ +bool ReCryptDirectory::removeEntry(const QString& node) +{ + bool rc = true; + const ReFileMetaData* entry = find(node); + if (entry == NULL) + rc = ! m_logger->logv(LOG_ERROR, LOC_REMOVE_ENTRY_1, "cannot remove file %s: not found", + node.toUtf8().constData()); + else { + ReFileMetaData& entry2 = *(ReFileMetaData*) entry; + //@ToDo: + //m_list.removeOne(entry2); + assert(false); + ReFileSystem& host = m_parent->host(); + ReFileMetaData hostedFile; + QString hostedNode = buildHostedNode(entry->m_id); + if (host.first(hostedNode, hostedFile)) + host.remove(hostedFile); + m_changed = true; + } + return rc; +} + +/** + * Reads the file containing the metadata of the files. + * + * @return true: success + */ +bool ReCryptDirectory::readMetaFile() +{ + bool rc = true; + m_list.clear(); + QString fnMetaFile = m_parent->directory() + ReCryptFileSystem::NODE_META_DIR; + FILE* fp = fopen(fnMetaFile.toUtf8().constData(), "rb"); + if (fp != NULL){ + QByteArray header; + header.resize(META_DIR_HEADER_LENGTH); + int nRead = fread(header.data(), 1, META_DIR_HEADER_LENGTH, fp); + if (nRead != META_DIR_HEADER_LENGTH){ + rc = ! m_logger->logv(LOG_ERROR, LOC_READ_META_FILE_1, + "header of %s too small: %d/%d", + fnMetaFile.toUtf8().constData(), nRead, META_DIR_HEADER_LENGTH); + } else { + QByteArray info; + rc = initFromHeader(META_INFO_LENGTH, MARKER_LENGTH, &header, info); + if (rc){ + const MetaInfo_t* meta = reinterpret_cast(info.constData()); + if (meta->m_countFiles > 0){ + m_fileBuffer.resize(m_blockSize); + m_entryBuffer.resize(0); + int sumLength = 0; + while ( (nRead = fread(m_fileBuffer.data(), + 1, m_blockSize, fp)) > 0){ + sumLength += nRead; + if (nRead < m_blockSize) + m_fileBuffer.resize(nRead); + decodeContent(m_fileBuffer, m_fileBuffer); + m_entryBuffer.append(m_fileBuffer); + splitBlock(sumLength < meta->m_size, + m_entryBuffer); + } + if (sumLength != meta->m_size){ + m_logger->logv(LOG_ERROR, LOC_READ_META_FILE_2, + "file %s too small: %d/%d", + fnMetaFile.toUtf8().constData(), + sumLength, meta->m_size); + } + } + } + } + } + return rc; +} + +/** + * Writes the metadata of the directory into a file. + * + * @return true: success + */ +bool ReCryptDirectory::writeMetaFile() +{ + bool rc = true; + QByteArray header; + QByteArray meta; + meta.resize(sizeof(MetaInfo_t)); + MetaInfo_t* meta2 = reinterpret_cast(meta.data()); + meta2->m_countFiles = m_list.length(); + meta2->m_size = meta2->m_countFiles * sizeof(FileEntry_t); + ReFileMetaDataList::const_iterator it; + for (it = m_list.cbegin(); it != m_list.cend(); ++it){ + int length = it->m_node.toUtf8().length(); + meta2->m_size += length + (length < 256 ? 0 : 1); + } + initHeader(META_INFO_LENGTH, MARKER_LENGTH, meta); + QByteArray node; + for (it = m_list.cbegin(); it != m_list.cend(); ++it){ + node = it->m_node.toUtf8(); + int length = node.length(); + meta2->m_size += length + (length < 256 ? 0 : 1); + } + QString fnMetaFile = m_parent->directory() + ReCryptFileSystem::NODE_META_DIR; + FILE* fp = fopen(fnMetaFile.toUtf8().constData(), "rb"); + if (fp == NULL){ + m_logger->logv(LOG_ERROR, LOC_WRITE_META_1, "cannot write (%d): %s", + errno, fnMetaFile); + } else { + m_fileBuffer.append(header); + int ixList = 0; + while (ixList++ < m_list.length()){ + const ReFileMetaData& file = m_list.at(ixList++); + FileEntry_t trg; + trg.m_created = file.m_created.toMSecsSinceEpoch(); + trg.m_modified = file.m_modified.toMSecsSinceEpoch(); + trg.m_owner = file.m_owner; + trg.m_group = file.m_group; + trg.m_size = file.m_size; + trg.m_mode = file.m_mode; + trg.m_id = file.m_id; + node = file.m_node.toUtf8(); + int length = node.length(); + trg.m_nodeLength = length < 256 ? length : 0; + m_fileBuffer.append(reinterpret_cast(&trg), sizeof trg); + m_fileBuffer.append(node); + if (length >= 256) + m_fileBuffer.append('\0'); + if (m_fileBuffer.length() >= m_blockSize || ixList >= m_list.length()){ + m_entryBuffer.resize(0); + if (m_fileBuffer.length() > m_blockSize){ + m_entryBuffer = m_fileBuffer.mid(m_blockSize); + m_fileBuffer.resize(m_blockSize); + } + encodeContent(m_fileBuffer, m_fileBuffer); + int nWritten = fwrite(m_fileBuffer.constData(), 1, + m_fileBuffer.length(), fp); + if (nWritten != m_fileBuffer.length()){ + rc = ! m_logger->logv(LOG_ERROR, LOC_WRITE_META_2, + "write error (%d): %s [%d/%d]", errno, + nWritten, m_fileBuffer.length()); + } + } + } + } + return rc; +} + +/** + * Splits a block with many metadata entries into single entries. + * + * @param isLast truethe given block is the last in the file + * @param block the data to split.
+ * Format: FileEntry_t_1 node1 File_entry2 node2 ...
+ * Precondition: the block starts with a FileEntry_t
+ * Postcondition: the block is empty or starts with the + * first FileEntry_t which is not processed. All processed + * entries are deleted from the buffer. block.length() < MAX_ENTRY_SIZE + */ +void ReCryptDirectory::splitBlock(bool isLast, QByteArray& block){ + const FileEntry_t* src = reinterpret_cast + (block.constData()); + ReFileMetaData file; + int position = 0; + const char* srcPtr = reinterpret_cast(block.constData()); + const char* endPtr = srcPtr + block.length() - (isLast ? 0 : MAX_ENTRY_SIZE); + while (srcPtr < endPtr){ + const FileEntry_t* src = reinterpret_cast(srcPtr); + file.m_created.setMSecsSinceEpoch(src->m_created); + file.m_modified.setMSecsSinceEpoch(src->m_modified); + file.m_owner = src->m_owner; + file.m_group = src->m_group; + file.m_size = src->m_size; + file.m_mode = src->m_mode; + file.m_id = src->m_id; + srcPtr += sizeof(FileEntry_t); + int nodeLength = src->m_nodeLength != 0 ? src->m_nodeLength : strlen(srcPtr); + QByteArray node(srcPtr, nodeLength); + file.m_node = node; + m_list.append(file); + srcPtr += nodeLength + (src->m_nodeLength != 0 ? 0 : 1); + } + block.remove(0, srcPtr - block.constData()); + printf("List: %d Rest: %d\n", m_list.length(), block.length()); +} +/** + * Gets the filename of an entry in the hosted filesystem. + * + * @param entry the name was built for this file + * @return the full name of the hosted (encrypted) file + */ +const QString& ReCryptDirectory::hostedFilename(const ReFileMetaData& entry) +{ + QString node = buildHostedNode(entry.m_id); + m_currentNode = ReFileUtils::pathAppend(m_parent->directory(), node); + return m_currentNode; +} diff --git a/os/ReCryptFileSystem.hpp b/os/ReCryptFileSystem.hpp new file mode 100644 index 0000000..9d4c139 --- /dev/null +++ b/os/ReCryptFileSystem.hpp @@ -0,0 +1,112 @@ +/* + * 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 RECRYPTFILESYSTEM_HPP +#define RECRYPTFILESYSTEM_HPP + +class ReCryptFileSystem; + +class ReCryptDirectory : protected ReByteScrambler{ +public: + typedef struct { + int64_t m_size; + //@ millisec from epoch + int64_t m_modified; + //@ millisec from epoch + int64_t m_created; + int32_t m_id; + int16_t m_owner; + int16_t m_group; + mode_t m_mode; + // 0: strlen(node) > 255 + uint8_t m_nodeLength; + } FileEntry_t; + typedef struct { + int32_t m_countFiles; + int32_t m_size; + } MetaInfo_t; +public: + ReCryptDirectory(ReRandomizer& contentRandom, ReCryptFileSystem* parent, + ReLogger* logger); + ~ReCryptDirectory(); +public: + bool addEntry(ReFileMetaData& entry); + const ReFileMetaData* find(const QString& node) const; + bool removeEntry(const QString& entry); + bool readMetaFile(); + bool writeMetaFile(); +protected: + int buildId(const QString& hostedNode) const; + QString buildHostedNode(int id) const; + const QString& hostedFilename(const ReFileMetaData& entry); + void splitBlock(bool isLast, QByteArray& block); +public: + static const int MARKER_LENGTH; + static const int META_INFO_LENGTH; + static const int META_DIR_HEADER_LENGTH; + static const int MAX_ENTRY_SIZE; +protected: + ReFileMetaDataList m_list; + ReCryptFileSystem* m_parent; + bool m_changed; + ReLogger* m_logger; + QString m_currentNode; + QByteArray m_fileBuffer; + QByteArray m_entryBuffer; + int m_blockSize; +}; + +/** + * A filesystem with encrypted filenames and file content. + * + * The storage is done with a 'host filesystem'. + * The filenames used in the interface (parameters) are clear text. + * The filenames of the base filesystem are encrypted. + * 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: public ReFileSystem, + protected ReCryptDirectory +{ +public: + static const int NODE_LENGHT; + static const int HEADER_LENGTH; + static const int CHECKSUM_LENGHT; + static const int MARKER_LENGHT; + static const QString NODE_META_DIR; + static const QString NODE_META_DEVICE; +public: + ReCryptFileSystem(ReFileSystem& hostFileSystem, + ReRandomizer& contentRandom, ReLogger* logger); + ~ReCryptFileSystem(); +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); +public: + /** Returns the filesystem hosting the encrypted files. + * @return the hosting filesystem + */ + ReFileSystem& host() const { + return m_host; + } + +protected: + ReFileSystem& m_host; +}; + +#endif // RECRYPTFILESYSTEM_HPP diff --git a/os/ReFileSystem.cpp b/os/ReFileSystem.cpp index 7ff1ebe..516ebfd 100644 --- a/os/ReFileSystem.cpp +++ b/os/ReFileSystem.cpp @@ -32,17 +32,6 @@ enum { LOC_SET_PROPERTIES_5, // 12017 }; -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. * @@ -277,7 +266,13 @@ ReFileSystem::ErrorCode ReLocalFileSystem::makeDir(const QString& node) { * EC_NOT_ACCESSIBLE parent not readable */ ReFileSystem::ErrorCode ReLocalFileSystem::setDirectory(const QString& path) { - ErrorCode rc = m_dir.setCurrent(path) ? EC_SUCCESS : EC_PATH_NOT_FOUND; + ErrorCode rc; + if (ReFileUtils::isAbsolutPath(path)) + rc = m_dir.setCurrent(path) ? EC_SUCCESS : EC_PATH_NOT_FOUND; + else + rc = m_dir.setCurrent(ReFileUtils::pathAppend( + m_dir.absolutePath(), path)) + ? EC_SUCCESS : EC_PATH_NOT_FOUND; m_directory = m_dir.absolutePath(); ReQStringUtils::ensureLastChar(m_directory, OS_SEPARATOR); return rc; @@ -545,14 +540,17 @@ ReFileMetaData::ReFileMetaData() : * @param size the filesize (0 for directories) */ ReFileMetaData::ReFileMetaData(const QString& node, const QDateTime& modified, - const QDateTime& created, int owner, int group, mode_t mode, int64_t size) : + const QDateTime& created, int owner, int group, mode_t mode, int64_t size, + int32_t id) : m_node(node), m_modified(modified), m_created(created), + m_size(size), m_owner(owner), m_group(group), - m_mode(mode), - m_size(size) { + m_id(id), + m_mode(mode) +{ } @@ -571,10 +569,12 @@ ReFileMetaData::ReFileMetaData(const ReFileMetaData& source) : m_node(source.m_node), m_modified(source.m_modified), m_created(source.m_created), + m_size(source.m_size), m_owner(source.m_owner), m_group(source.m_group), - m_mode(source.m_mode), - m_size(source.m_size) { + m_id(source.m_id), + m_mode(source.m_mode) +{ } @@ -592,118 +592,7 @@ ReFileMetaData&ReFileMetaData::operator =(const ReFileMetaData& source) { m_group = source.m_group; m_mode = source.m_mode; m_size = source.m_size; + m_id = source.m_id; return *this; } -/** - * Constructor. - * - * @param hostFileSystem the filesystem which does the storage (with - * encrypted names and content - * @param nameRandom a pseudo random generator for names - * @param contentRandom a pseudo random generator for content - */ -ReCryptFileSystem::ReCryptFileSystem(ReFileSystem& hostFileSystem, - ReRandomizer& nameRandom, ReRandomizer& contentRandom, ReLogger* logger) : - ReFileSystem("cryptfs", logger), - ReByteScrambler(contentRandom, NODE_LENGHT, sizeof(int32_t), logger), - m_host(hostFileSystem) { -} - -/** - * Destructor. - */ -ReCryptFileSystem::~ReCryptFileSystem() { -} - -/** Frees resources like open files. - */ -void ReCryptFileSystem::close() -{ -} - -/** - * Fills a list with the items of the current directory. - * - * @param matcher the matching processor - * @return the count of the found entries (list.size()) - */ -int ReCryptFileSystem::listInfos(const ReIncludeExcludeMatcher& matcher, - ReFileMetaDataList& list) { - return 0; -} - -/** - * Creates a directory. - * - * @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; -} - -/** - * Reads a part of a file into a buffer. - * - * @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; -} - -/** 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; -} - -/** - * 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; -} - -/** - * 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 90d67f2..f664234 100644 --- a/os/ReFileSystem.hpp +++ b/os/ReFileSystem.hpp @@ -17,7 +17,7 @@ public: ReFileMetaData(); ReFileMetaData(const QString& node, const QDateTime& modified, const QDateTime& created, int owner = -1, int group = -1, - mode_t mode = (mode_t) - 1, int64_t size = 0); + mode_t mode = (mode_t) - 1, int64_t size = 0, int32_t id = 0); virtual ~ReFileMetaData(); ReFileMetaData(const ReFileMetaData& source); ReFileMetaData& operator =(const ReFileMetaData& source); @@ -25,10 +25,12 @@ public: QString m_node; QDateTime m_modified; QDateTime m_created; + int64_t m_size; int16_t m_owner; int16_t m_group; + // unique inside the directory: + int32_t m_id; mode_t m_mode; - int64_t m_size; }; typedef QList ReFileMetaDataList; @@ -186,40 +188,5 @@ protected: FILE* m_writeFile; }; -/** - * A filesystem with encrypted filenames and file content. - * - * The storage is done with a 'host filesystem'. - * The filenames used in the interface (parameters) are clear text. - * The filenames of the base filesystem are encrypted. - * 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: public ReFileSystem, protected ReByteScrambler { -public: - 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: -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; -}; #endif /* OS_REFILESYSTEM_HPP_ */ diff --git a/os/reos.hpp b/os/reos.hpp index a93b8d8..ba2c10e 100644 --- a/os/reos.hpp +++ b/os/reos.hpp @@ -50,5 +50,6 @@ inline bool operator >(const ReFileTime_t& time1, const ReFileTime_t& time2) { #endif } #include "os/ReFileSystem.hpp" +#include "os/ReCryptFileSystem.hpp" #endif /* OS_REOS_HPP_ */ diff --git a/remodules.hpp b/remodules.hpp index 35a8073..0d27c65 100644 --- a/remodules.hpp +++ b/remodules.hpp @@ -34,6 +34,7 @@ enum { LOC_STATESTORAGE, // 120 LOC_FILESYSTEM, LOC_RANDOMIZER, + LOC_CRYPTFILESYSTEM, }; #define LOC_FIRST_OF(moduleNo) (moduleNo*100+1) class RplModules { -- 2.39.5